Skip to content

feat(api): add lite list endpoints for projects, members, cycles, and modules#9410

Open
akhil-vamshi-konam wants to merge 3 commits into
previewfrom
feat-lite-endpoints
Open

feat(api): add lite list endpoints for projects, members, cycles, and modules#9410
akhil-vamshi-konam wants to merge 3 commits into
previewfrom
feat-lite-endpoints

Conversation

@akhil-vamshi-konam

@akhil-vamshi-konam akhil-vamshi-konam commented Jul 13, 2026

Copy link
Copy Markdown

Description

Adds lightweight, cursor-paginated list endpoints for projects, workspace members, project members, cycles, and modules to support picker/reference use cases with reduced payload sizes.

Changes

  • Added new lite endpoints:

    • GET /workspaces/{slug}/projects-lite/
    • GET /workspaces/{slug}/members-lite/
    • GET /workspaces/{slug}/projects/{project_id}/project-members-lite/
    • GET /workspaces/{slug}/projects/{project_id}/cycles-lite/
    • GET /workspaces/{slug}/projects/{project_id}/modules-lite/
  • Introduced lightweight serializers for projects and members.

  • Added optional include_archived query parameter for the projects-lite endpoint.

  • Added OpenAPI documentation for all new endpoints.

  • Added contract tests covering response shape, pagination, archived filtering, and error scenarios.

  • Updated issue listing to return a clear 400 response when unsupported pql or filters query parameters are provided.

Summary by CodeRabbit

  • New Features
    • Added lightweight, paginated API listings for projects, cycles, modules, workspace members, and project members.
    • New “lite” endpoints: projects-lite, cycles-lite, modules-lite, members-lite (workspace members), and project-members-lite (GET-only).
    • Project lite supports include_archived; cycles/modules/member listings exclude archived items by default.
  • Bug Fixes
    • Listing now returns HTTP 400 when unsupported work-item filtering parameters are provided.
  • Tests
    • Added contract tests covering pagination, response shape, permissions, and archived/non-archived filtering for the new endpoints.

@CLAassistant

CLAassistant commented Jul 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10b66347-0fca-46c9-8aea-8918805bf052

📥 Commits

Reviewing files that changed from the base of the PR and between 7ac1288 and 2d75b86.

📒 Files selected for processing (1)
  • apps/api/plane/utils/order_queryset.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/plane/utils/order_queryset.py

📝 Walkthrough

Walkthrough

Added lightweight paginated API endpoints for projects, cycles, modules, workspace members, and project members. Added lite serializers, routing, archived-record filtering, ordering safeguards, contract tests, and validation rejecting unsupported issue filters.

Changes

Lite API surface

Layer / File(s) Summary
Response contracts and exports
apps/api/plane/api/serializers/*, apps/api/plane/api/views/__init__.py
Added flattened lite member serializers, exported new serializers and endpoints, and exposed archived_at in ProjectLiteSerializer.
Projects-lite listing
apps/api/plane/api/views/project.py, apps/api/plane/api/urls/project.py, apps/api/plane/tests/contract/api/test_projects_lite.py
Added a workspace-scoped paginated projects-lite endpoint with archive filtering, ordering, access filtering, and contract tests.
Cycles and modules-lite listings
apps/api/plane/api/views/{cycle,module}.py, apps/api/plane/api/urls/{cycle,module}.py, apps/api/plane/tests/contract/api/test_{cycles,modules}_lite.py, apps/api/plane/utils/order_queryset.py
Added project-scoped paginated endpoints that exclude archived cycles and modules, sanitize ordering, and include route wiring and contract tests.
Member-lite listings
apps/api/plane/api/views/member.py, apps/api/plane/api/urls/member.py, apps/api/plane/tests/contract/api/test_members_lite.py
Added workspace and project member-lite endpoints with permissions, related-object loading, pagination, and response-shape tests.
Issue filter validation
apps/api/plane/api/views/issue.py
Rejects issue list requests containing pql or filters with HTTP 400.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant API Route
  participant Lite Endpoint
  participant Database
  participant Lite Serializer
  Client->>API Route: GET lite collection
  API Route->>Lite Endpoint: Dispatch request
  Lite Endpoint->>Database: Query filtered records
  Database-->>Lite Endpoint: Paginated records
  Lite Endpoint->>Lite Serializer: Serialize results
  Lite Serializer-->>Client: Paginated lite response
Loading

Possibly related PRs

  • makeplane/plane#9292: Introduces related order_by sanitization and allowlist changes used by cycle and module listing logic.
  • makeplane/plane#9349: Modifies the same issue-list endpoint path with related query-parameter validation.

Suggested reviewers: dheeru0198, pablohashescobar

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding lite list endpoints for projects, members, cycles, and modules.
Description check ✅ Passed The description covers the main changes well, but it omits the template's Type of Change, Test Scenarios, References, and Screenshots sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 feat-lite-endpoints

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.

@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: 6

🧹 Nitpick comments (5)
apps/api/plane/tests/contract/api/test_members_lite.py (1)

86-102: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding error-scenario and role-assertion tests for TestProjectMembersLite.

TestWorkspaceMembersLite includes test_unknown_workspace_is_rejected and asserts item["role"] == 20 in test_lite_member_shape. TestProjectMembersLite has neither — no test for unknown workspace/project rejection, and test_lite_member_shape doesn't verify the role value. Adding these would match the workspace test coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/api/test_members_lite.py` around lines 86 -
102, Extend TestProjectMembersLite with an unknown workspace/project rejection
test matching TestWorkspaceMembersLite, using the existing URL helper and
expected error status. Update test_lite_member_shape to assert the returned
member’s role equals 20, while preserving the existing field-presence checks.
apps/api/plane/tests/contract/api/test_modules_lite.py (1)

52-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider asserting the lite field shape.

Same gap as test_cycles_lite.py: the test verifies pagination and archived exclusion but does not assert the lite field set. Adding field-shape assertions (like test_projects_lite.py does) would verify the "lite" contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/api/test_modules_lite.py` around lines 52 - 61,
Update TestModulesLite.test_paginated_and_excludes_archived to assert that each
returned module contains exactly the expected lite response fields, following
the field-shape assertion pattern used by the related lite contract tests. Keep
the existing pagination, status, and archived-module assertions unchanged.
apps/api/plane/tests/contract/api/test_cycles_lite.py (2)

63-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider asserting the lite field shape.

The test verifies pagination and archived exclusion but does not assert which fields are present or absent in the response items. test_projects_lite.py includes test_returns_only_lite_fields that checks the lite field set and confirms heavy fields like total_members are absent. Adding a similar assertion here would verify the "lite" contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/api/test_cycles_lite.py` around lines 63 - 72,
Update TestCyclesLite.test_paginated_and_excludes_archived to assert each
returned cycle item matches the lite response field set, including that heavy
fields such as total_members are absent. Reuse the established field-shape
assertion pattern from test_projects_lite.py while preserving the existing
pagination and archived-cycle checks.

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Contract tests for cycles-lite and modules-lite don't verify the lite field shape. Both tests assert pagination and archived exclusion but omit field-shape checks — the "lite" contract (which fields are present/absent) is untested. test_projects_lite.py includes test_returns_only_lite_fields that checks the lite field set and confirms heavy fields are absent.

  • apps/api/plane/tests/contract/api/test_cycles_lite.py#L63-72: Add assertions verifying lite fields present (e.g., id, name, start_date, end_date) and computed/heavy fields absent.
  • apps/api/plane/tests/contract/api/test_modules_lite.py#L52-61: Add similar field-shape assertions for the modules-lite response items.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/api/test_cycles_lite.py` at line 1, Update the
cycles-lite and modules-lite contract tests, specifically their response-item
assertions near the existing pagination and archived-exclusion checks, to verify
the expected lite fields are present and computed/heavy fields are absent.
Mirror the field-shape validation used by test_returns_only_lite_fields in
test_projects_lite.py, covering representative fields such as id, name,
start_date, and end_date where applicable.
apps/api/plane/api/views/cycle.py (1)

360-399: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

CycleLiteSerializer uses fields = "__all__", undermining the "lite" purpose.

The serializer docstring says "minimal data transfer" but fields = "__all__" serializes every Cycle model field (including external_id, external_source, deleted_at, etc.). This is inconsistent with ProjectLiteSerializer, which uses an explicit field list and excludes computed fields like total_members. Define an explicit minimal field set (e.g., id, name, start_date, end_date, description, project, workspace, owned_by) to match the "lite" contract and prevent accidental exposure of future model fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/api/views/cycle.py` around lines 360 - 399, The
CycleLiteSerializer currently serializes all Cycle model fields, contradicting
its lightweight contract. Update CycleLiteSerializer to use an explicit minimal
fields list including id, name, start_date, end_date, description, project,
workspace, and owned_by, excluding computed and internal fields and preventing
future fields from being exposed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/plane/api/views/cycle.py`:
- Line 392: Update the cycle query ordering to pass the requested value through
the existing sanitize_order_by() helper before calling order_by(), preserving
"-created_at" as the default. Apply the same validation to the matching raw
request.GET order_by usage in the module and project endpoints.

In `@apps/api/plane/api/views/issue.py`:
- Around line 317-318: Update the unsupported_filters check in the issue-listing
view to detect whether “pql” or “filters” exists in request.GET, regardless of
its value. Preserve the existing 400 response for any supplied unsupported
parameter, including empty values.

In `@apps/api/plane/api/views/member.py`:
- Line 254: Align the non-existent workspace and project handling with the
documented OpenAPI responses: update the error returns in
WorkspaceMemberLiteAPIEndpoint and ProjectMemberLiteAPIEndpoint from HTTP 400 to
HTTP 404, preserving their existing not-found response payloads and schema
declarations.
- Around line 304-321: Add an explicit project existence check in the `get`
method before querying `project_members`, validating the project belongs to the
workspace identified by `slug`. Return the documented 404 response when no
matching project exists, while preserving the existing member listing behavior
for valid projects.

In `@apps/api/plane/api/views/project.py`:
- Line 416: Sanitize the lite endpoint ordering before passing it to
QuerySet.order_by(): in apps/api/plane/api/views/project.py:416, use
sanitize_order_by with PROJECT_ORDER_BY_ALLOWLIST and "-created_at" as the
default; in apps/api/plane/api/views/module.py:314, apply the same pattern with
the module-specific order-by allowlist and appropriate default, preserving
graceful fallback for invalid input.
- Around line 401-405: Update the workspace existence check in the project view
to return HTTP 404 when the Workspace lookup by slug fails, matching the 404
response declared by the project_docs schema; leave the error payload unchanged.

---

Nitpick comments:
In `@apps/api/plane/api/views/cycle.py`:
- Around line 360-399: The CycleLiteSerializer currently serializes all Cycle
model fields, contradicting its lightweight contract. Update CycleLiteSerializer
to use an explicit minimal fields list including id, name, start_date, end_date,
description, project, workspace, and owned_by, excluding computed and internal
fields and preventing future fields from being exposed.

In `@apps/api/plane/tests/contract/api/test_cycles_lite.py`:
- Around line 63-72: Update TestCyclesLite.test_paginated_and_excludes_archived
to assert each returned cycle item matches the lite response field set,
including that heavy fields such as total_members are absent. Reuse the
established field-shape assertion pattern from test_projects_lite.py while
preserving the existing pagination and archived-cycle checks.
- Line 1: Update the cycles-lite and modules-lite contract tests, specifically
their response-item assertions near the existing pagination and
archived-exclusion checks, to verify the expected lite fields are present and
computed/heavy fields are absent. Mirror the field-shape validation used by
test_returns_only_lite_fields in test_projects_lite.py, covering representative
fields such as id, name, start_date, and end_date where applicable.

In `@apps/api/plane/tests/contract/api/test_members_lite.py`:
- Around line 86-102: Extend TestProjectMembersLite with an unknown
workspace/project rejection test matching TestWorkspaceMembersLite, using the
existing URL helper and expected error status. Update test_lite_member_shape to
assert the returned member’s role equals 20, while preserving the existing
field-presence checks.

In `@apps/api/plane/tests/contract/api/test_modules_lite.py`:
- Around line 52-61: Update TestModulesLite.test_paginated_and_excludes_archived
to assert that each returned module contains exactly the expected lite response
fields, following the field-shape assertion pattern used by the related lite
contract tests. Keep the existing pagination, status, and archived-module
assertions unchanged.
🪄 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: 9947e3d4-3777-4ea9-aec7-846b5b2293b1

📥 Commits

Reviewing files that changed from the base of the PR and between dc9d80b and 2085908.

📒 Files selected for processing (17)
  • apps/api/plane/api/serializers/__init__.py
  • apps/api/plane/api/serializers/member.py
  • apps/api/plane/api/serializers/project.py
  • apps/api/plane/api/urls/cycle.py
  • apps/api/plane/api/urls/member.py
  • apps/api/plane/api/urls/module.py
  • apps/api/plane/api/urls/project.py
  • apps/api/plane/api/views/__init__.py
  • apps/api/plane/api/views/cycle.py
  • apps/api/plane/api/views/issue.py
  • apps/api/plane/api/views/member.py
  • apps/api/plane/api/views/module.py
  • apps/api/plane/api/views/project.py
  • apps/api/plane/tests/contract/api/test_cycles_lite.py
  • apps/api/plane/tests/contract/api/test_members_lite.py
  • apps/api/plane/tests/contract/api/test_modules_lite.py
  • apps/api/plane/tests/contract/api/test_projects_lite.py

Comment thread apps/api/plane/api/views/cycle.py Outdated
Comment thread apps/api/plane/api/views/issue.py
Comment thread apps/api/plane/api/views/member.py
Comment thread apps/api/plane/api/views/member.py
Comment thread apps/api/plane/api/views/project.py
Comment thread apps/api/plane/api/views/project.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants