Skip to content

[SILO-1158] chore: add context for project in relations API#8860

Merged
sriramveeraghanta merged 2 commits into
previewfrom
chore-modify_relations_response
Apr 20, 2026
Merged

[SILO-1158] chore: add context for project in relations API#8860
sriramveeraghanta merged 2 commits into
previewfrom
chore-modify_relations_response

Conversation

@Saurabhkmr98

@Saurabhkmr98 Saurabhkmr98 commented Apr 6, 2026

Copy link
Copy Markdown
Member

Description

  • Modified the work item relations GET endpoint to return {project_id, issue_id} objects instead of flat UUID arrays, enabling consumers to identify which project each related work item belongs to.
  • Replaced the single aggregate + ArrayAgg query with a .values() query that fetches each relation row with its associated project IDs, then builds the response in Python with proper deduplication for symmetric relation types (duplicate, relates_to).
  • Cleaned up unused imports (ArrayAgg, ArrayField, Coalesce, UUIDField) and updated the OpenAPI example to reflect the new response shape.

Response format change

Before:

{
  "blocking": ["<issue_uuid>", "<issue_uuid>"],
  "blocked_by": ["<issue_uuid>"],
  ...
}

After:

{
  "blocking": [
    {"project_id": "<project_uuid>", "issue_id": "<issue_uuid>"},
    {"project_id": "<project_uuid>", "issue_id": "<issue_uuid>"}
  ],
  "blocked_by": [
    {"project_id": "<project_uuid>", "issue_id": "<issue_uuid>"}
  ],
  ...
}

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Summary by CodeRabbit

  • Refactor
    • Relation endpoints now return structured relation entries (project_id + issue_id) instead of raw IDs, enabling clear cross-project references.
  • Bug Fixes
    • Relation lists are consistently grouped, deduplicated, and initialized as empty when none exist, fixing incorrect/misplaced relation entries.

@Saurabhkmr98 Saurabhkmr98 requested a review from dheeru0198 April 6, 2026 11:54
@makeplane

makeplane Bot commented Apr 6, 2026

Copy link
Copy Markdown

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai

coderabbitai Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 788829e0-899f-4d11-8ec5-475268895d1f

📥 Commits

Reviewing files that changed from the base of the PR and between 7645c59 and 8fb1f22.

📒 Files selected for processing (1)
  • apps/api/plane/api/serializers/issue.py

📝 Walkthrough

Walkthrough

The issue relations aggregation was moved from DB-level array aggregation to manual per-relation iteration with deduplication. The API response shape for relations changed from UUID lists to objects with project_id and issue_id; relation grouping logic was adjusted to populate bidirectional lists correctly.

Changes

Cohort / File(s) Summary
Issue relations view refactor
apps/api/plane/api/views/issue.py
Removed array-aggregation imports/usage (UUIDField, Coalesce, ArrayAgg, ArrayField). Replaced with iteration over a .values(...) queryset containing issue_project_id and related_issue_project_id. Reworked grouping logic for blocking/blocked_by, duplicate/relates_to, start_before/start_after, finish_before/finish_after. Implemented manual deduplication and initialize empty lists before iteration. Response entries now objects {project_id, issue_id}.
Serializers: relation ref type
apps/api/plane/api/serializers/issue.py
Added IssueRelationRefSerializer (fields: project_id, issue_id). Updated IssueRelationResponseSerializer to use IssueRelationRefSerializer for lists blocking, blocked_by, duplicate, relates_to, start_after, start_before, finish_after, finish_before and revised help text to reflect (project_id, issue_id) pairs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through relations, one by one,

swapped arrays for loops and careful fun,
paired each issue with its project ID,
deduped the paths so all is tidy,
nibbles of logic — a rabbit's small deed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding project context to the relations API response format.
Description check ✅ Passed The PR description provides detailed information about the changes, includes before/after response format examples, and correctly identifies the change type.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore-modify_relations_response

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/plane/api/views/issue.py`:
- Around line 2291-2323: The API changed: list_work_item_relations now returns
relation refs ({project_id, issue_id}) but the serializer and web consumer still
expect flat UUID lists and issue objects; update
apps/api/plane/api/serializers/issue.py to document the new shape (replace the
ListField(UUIDField()) relation fields with a ListField of a dict/nested
serializer containing "project_id" and "issue_id") so the OpenAPI contract
matches list_work_item_relations, and update the consumer in
apps/web/core/store/issue/issue-details/relation.store.ts (the code that
currently iterates and calls addIssue(item) around lines 115-133) to either
extract and pass the correct issue id (item.issue_id) to addIssue or adapt
addIssue to accept the {project_id, issue_id} ref; make the serializer and the
web store consistent with list_work_item_relations across all relation fields
(blocking, blocked_by, duplicate, relates_to, start_after, start_before,
finish_after, finish_before).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6bf17114-9b1c-4ece-bb20-9e3d7d964eb0

📥 Commits

Reviewing files that changed from the base of the PR and between bb128e3 and 7645c59.

📒 Files selected for processing (1)
  • apps/api/plane/api/views/issue.py

Comment on lines 2291 to 2323
"blocking": [
"550e8400-e29b-41d4-a716-446655440000",
"550e8400-e29b-41d4-a716-446655440001",
{
"project_id": "550e8400-e29b-41d4-a716-446655440010",
"issue_id": "550e8400-e29b-41d4-a716-446655440000",
},
{
"project_id": "550e8400-e29b-41d4-a716-446655440010",
"issue_id": "550e8400-e29b-41d4-a716-446655440001",
},
],
"blocked_by": [
{
"project_id": "550e8400-e29b-41d4-a716-446655440011",
"issue_id": "550e8400-e29b-41d4-a716-446655440002",
},
],
"blocked_by": ["550e8400-e29b-41d4-a716-446655440002"],
"duplicate": [],
"relates_to": ["550e8400-e29b-41d4-a716-446655440003"],
"relates_to": [
{
"project_id": "550e8400-e29b-41d4-a716-446655440010",
"issue_id": "550e8400-e29b-41d4-a716-446655440003",
},
],
"start_after": [],
"start_before": ["550e8400-e29b-41d4-a716-446655440004"],
"start_before": [
{
"project_id": "550e8400-e29b-41d4-a716-446655440012",
"issue_id": "550e8400-e29b-41d4-a716-446655440004",
},
],
"finish_after": [],
"finish_before": [],
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Propagate this response-shape change end-to-end.

list_work_item_relations now returns relation refs ({project_id, issue_id}), but apps/api/plane/api/serializers/issue.py still documents these fields as ListField(UUIDField()), and apps/web/core/store/issue/issue-details/relation.store.ts:115-133 still consumes issue.id and passes each item into addIssue(). As-is, this ships the wrong OpenAPI contract and will break the current relations UI unless the web consumer/service is updated in the same PR or the old id-based shape is preserved.

Also applies to: 2337-2413

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/plane/api/views/issue.py` around lines 2291 - 2323, The API changed:
list_work_item_relations now returns relation refs ({project_id, issue_id}) but
the serializer and web consumer still expect flat UUID lists and issue objects;
update apps/api/plane/api/serializers/issue.py to document the new shape
(replace the ListField(UUIDField()) relation fields with a ListField of a
dict/nested serializer containing "project_id" and "issue_id") so the OpenAPI
contract matches list_work_item_relations, and update the consumer in
apps/web/core/store/issue/issue-details/relation.store.ts (the code that
currently iterates and calls addIssue(item) around lines 115-133) to either
extract and pass the correct issue id (item.issue_id) to addIssue or adapt
addIssue to accept the {project_id, issue_id} ref; make the serializer and the
web store consistent with list_work_item_relations across all relation fields
(blocking, blocked_by, duplicate, relates_to, start_after, start_before,
finish_after, finish_before).

@sriramveeraghanta sriramveeraghanta merged commit 45b4fc8 into preview Apr 20, 2026
13 checks passed
@sriramveeraghanta sriramveeraghanta deleted the chore-modify_relations_response branch April 20, 2026 09:59
PhilippeCaira pushed a commit to PhilippeCaira/plane that referenced this pull request Apr 22, 2026
…e#8860)

* add context for project in relations API

* modify issue relation serializer
dadenegarco added a commit to dadenegarco/plane-fa that referenced this pull request May 8, 2026
Apply 6 UX improvements from upstream while preserving our Persian/RTL,
i18n, and onboarding customizations.

UI revamps
- Power-K shortcuts modal: wrap shortcut list in propel ScrollArea so
  long content scrolls within the modal (WEB-6784, makeplane#8872) — kept our
  i18n placeholder t("power_k_categories.search_shortcuts")
- Instance not ready: full visual redesign using DefaultLayout +
  gradient bg/logo webp assets (WEB-6599, makeplane#8755). Two new webp assets
  added under apps/web/app/assets/auth/
- Intake action buttons: switch to design tokens (warning/danger/success
  variants), use propel IconButton + new CheckCircle/CloseCircleFilled
  icons, replace inline ChevronUp/Down buttons with IconButton
  (WEB-6702, makeplane#8801). Mobile header preserved RTL me-2 fix on lines 106
  and 111

Onboarding
- Skip role & use-case steps for self-hosted instances. Reads
  instanceConfig.is_self_managed and routes PROFILE_SETUP directly to
  WORKSPACE_CREATE_OR_JOIN. handleStepBack now respects the same flag
  (WEB-6840, makeplane#8890). Kept our t() i18n in stepChange toasts and our
  ps-4/pe-6 RTL classes in header

Backend
- Auth logging: detailed events for email validation, user lookup,
  password strength, GitHub OAuth email retrieval. Dedicated logger
  configured in settings/local.py and production.py (WEB-5225, makeplane#7998).
  estimate.py drops unused MaxValueValidator import. project.py drops
  unused ProjectUserProperty import
- Sub-issue query: optimized annotations and subqueries for better
  performance on large issue trees (makeplane#8889)

Skipped
- 3.7 SILO external API endpoints (makeplane#8664, makeplane#8763, makeplane#8661, makeplane#8860): brings
  a migration 0121_alter_estimate_type that conflicts with our
  0121_profile_calendar_system; ~500 LOC of estimate/relations/summary
  endpoints only useful with SILO integration. Defer until needed

Notes
- ICON_PROPERTIES extracted from inbox-status-icon.tsx into a separate
  inbox-status-icon-properties.ts file (react-refresh-friendly split)
- bypassed lint-staged --max-warnings=0 hook because all eslint
  warnings in touched files are pre-existing tech debt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
eyriehq-admin added a commit to eyriehq/plane-plus that referenced this pull request May 19, 2026
* [WEB-6784] feat scrollbar in shortcuts modal (makeplane#8872)

* fix: update border for project timezone

* feat: added scrollbar in keyboard shortcuts modal

* fix: remove unnecessary changes

* fix: remove redundant overflow

* [WEB-6785] fix: update border for project timezone (makeplane#8870)

* chore: remove Intercom integration and chat support components (makeplane#8875)

Intercom is no longer used. This removes all related frontend components,
hooks, custom events, API config, types, and i18n keys.

* chore: update dependencies (Django, cryptography, axios, lodash) (makeplane#8880)

* chore: update dependencies (Django, cryptography, axios, lodash)

- Django 4.2.29 → 4.2.30
- cryptography 46.0.6 → 46.0.7
- axios 1.13.5 → 1.15.0
- lodash 4.17.23 → 4.18.0

* chore: update lodash from 4.18.0 to 4.18.1

* [WEB-6840] feat: skip role & use-case steps for self-hosted instances (makeplane#8890)

* chore(deps): bump pytest (makeplane#8891)

Bumps the pip group with 1 update in the /apps/api/requirements directory: [pytest](https://github.com/pytest-dev/pytest).


Updates `pytest` from 9.0.2 to 9.0.3
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](pytest-dev/pytest@9.0.2...9.0.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* enhance sub-issue query performance with optimized annotations and subqueries (makeplane#8889)

* fix: enforce workspace membership on V2 asset endpoints (makeplane#8885)

WorkspaceFileAssetEndpoint had no authorization checks beyond
authentication, allowing any logged-in user to create, read, patch,
and delete assets in any workspace by slug. DuplicateAssetEndpoint
only authorized the destination workspace, letting users copy assets
from workspaces they don't belong to.

Add @allow_permission decorators to all WorkspaceFileAssetEndpoint
methods and scope DuplicateAssetEndpoint's source asset lookup to
workspaces where the caller is an active member.

Ref: GHSA-qw87-v5w3-6vxx

* fix: replace IS_SELF_MANAGED with WEBHOOK_ALLOWED_IPS allowlist (makeplane#8884)

* fix: replace IS_SELF_MANAGED toggle with explicit WEBHOOK_ALLOWED_IPS allowlist

Instead of blanket-allowing all private IPs on self-managed deployments,
webhook URL validation now blocks all private/internal IPs by default and
only permits specific networks listed in the WEBHOOK_ALLOWED_IPS env
variable (comma-separated IPs/CIDRs).

* fix: address PR review comments for webhook SSRF protection

- Sanitize error messages to avoid leaking internal details to clients
- Guard against TypeError with mixed IPv4/IPv6 allowlist networks
- Re-validate webhook URL at send time to prevent DNS-rebinding
- Add unit tests for mixed-version IP network allowlists

* [SILO-1158] chore: add context for project in relations API (makeplane#8860)

* add context for project in relations API

* modify issue relation serializer

* fix: sanitize filenames in upload paths to prevent path traversal (makeplane#8879)

* fix: sanitize filenames in upload paths to prevent path traversal (GHSA-v57h-5999-w7xp)

Add server-side filename sanitization across all file upload endpoints
to prevent path traversal sequences (../) in user-supplied filenames
from being incorporated into S3 object keys. While S3 keys are flat
strings and not vulnerable to filesystem traversal, this adds
defense-in-depth and prevents S3 key pollution.

Changes:
- Add sanitize_filename() utility in path_validator.py
- Sanitize filenames in get_upload_path() for FileAsset and IssueAttachment models
- Sanitize name parameter in all upload view endpoints

* fix: address PR review feedback on filename sanitization

- Remove unused `import re`
- Normalize backslashes to forward slashes before os.path.basename()
  so Windows-style paths (e.g. ..\..\..\evil.txt) are handled on POSIX
- Strip whitespace before removing leading dots so " .env" is caught
- Return None instead of "unnamed" for empty input so existing
  `if not name` validation guards remain effective
- Add `or "unnamed"` fallback at call sites that lack a name guard

* fix: use random hex name as fallback in get_upload_path instead of "unnamed"

* fix: resolve ruff E501 line too long in DuplicateAssetEndpoint

* chore(ci): suppress CodeQL file coverage deprecation warning (makeplane#8916)

* chore(ci): suppress CodeQL file coverage deprecation warning

Explicitly opt into the new default behavior where CodeQL skips
computing file coverage information on pull requests for improved
analysis performance.

* Update .github/workflows/codeql.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: update CODEOWNERS for apps and deployments (makeplane#8919)

* chore: update CODEOWNERS for apps and deployments

Assign owners per app/area so reviews are routed to the right
maintainers.

* chore: update the codeowners

* chore: add Claude Code skills for PR descriptions and release notes (makeplane#8920)

* chore: add Claude Code skills for PR descriptions and release notes

* chore(skills): update release-notes branches to canary->master and example version to v1.3.0

* chore(skills): address PR review comments

- pr-description: infer base branch from PR metadata, fix Improvement wording, reference template's screenshot placeholder verbatim
- release-notes: add `text` language to unlabeled fenced code block

* chore: bump up the package version

* chore(deps): bump lxml (makeplane#8925)

Bumps the pip group with 1 update in the /apps/api/requirements directory: [lxml](https://github.com/lxml/lxml).


Updates `lxml` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](lxml/lxml@lxml-6.0.0...lxml-6.1.0)

---
updated-dependencies:
- dependency-name: lxml
  dependency-version: 6.1.0
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump axios, uuid and add security overrides (makeplane#8930)

* chore(deps): bump axios, uuid and add security overrides

Bump axios 1.15.0 → 1.15.2 and uuid 13.0.0 → 14.0.0 in the catalog,
and add pnpm overrides pinning postcss >=8.5.10, follow-redirects
>=1.16.0, and routing axios/uuid through the catalog.

* fix: overrides

* fix: add WEBHOOK_ALLOWED_HOSTS allowlist for internal webhook targets (makeplane#9078)

* fix: add WEBHOOK_ALLOWED_HOSTS allowlist for internal webhook targets

The IP-based allowlist alone isn't practical for containerised deployments
where service IPs are dynamic. Adds a hostname-based bypass for trusted
internal services (e.g. Silo via docker-compose / k8s service DNS) and
makes the previously hardcoded ["plane.so"] domain blocklist configurable
via WEBHOOK_DISALLOWED_DOMAINS.

- validate_url accepts allowed_hosts (exact, case-insensitive match;
  skips DNS lookup for trusted names)
- WebhookSerializer wires both settings through and lets allowlisted
  hosts bypass the disallowed-domain check
- Exposes WEBHOOK_ALLOWED_HOSTS in aio/cli deployment env files

* fix: default WEBHOOK_DISALLOWED_DOMAINS to empty for self-hosted

* fix: pass WEBHOOK_ALLOWED_HOSTS to send-time webhook re-validation

* fix: pnpm path for Docker builds (makeplane#9079)

Add $PNPM_HOME/bin to PATH so corepack-installed pnpm binaries are
resolvable during Docker builds.

* fix(brand): replace upstream Plane logos and copy with Plane Plus in onboarding screens

- not-ready-view.tsx: swap gradient-logo.webp (3D Plane diamond) → EyrieHQ icon;
  "Welcome to Plane" → "Welcome to Plane Plus"
- tour/root.tsx: "Welcome to Plane, {name}" → "Welcome to Plane Plus, {name}";
  copy updated to match
- admin/instance-not-ready.tsx: drop PlaneTakeOffImage → EyrieHQ icon;
  "Welcome aboard Plane!" → "Welcome aboard Plane Plus!"
- admin/new-user-popup.tsx: drop TakeoffIcon SVGs + unused theme imports → EyrieHQ icon;
  "Welcome to Plane instance portal" → "Welcome to Plane Plus"

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: b-saikrishnakanth <130811169+b-saikrishnakanth@users.noreply.github.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Phạm Nguyên Phương <69796528+PhuongPN6689@users.noreply.github.com>
Co-authored-by: Saurabh Kumar <70131915+Saurabhkmr98@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: EyrieHQ <eyriehq@eyriehq.com>
Co-authored-by: Surya <surya@eyriehq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants