Skip to content

docs(tasks): add OpenAPI YAML for tasks module API#3389

Merged
PierreBrisorgueil merged 7 commits intomasterfrom
feat/tasks-openapi-docs
Apr 5, 2026
Merged

docs(tasks): add OpenAPI YAML for tasks module API#3389
PierreBrisorgueil merged 7 commits intomasterfrom
feat/tasks-openapi-docs

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Contributor

@PierreBrisorgueil PierreBrisorgueil commented Apr 5, 2026

Summary

  • Add modules/tasks/doc/tasks.yml documenting all 6 task endpoints (list, create, get, update, delete, stats) with full request/response schemas, auth requirements, and parameters
  • Add shared SuccessResponse, ErrorResponse schemas and reusable error responses (Unauthorized, Forbidden, NotFound, UnprocessableEntity) to modules/core/doc/index.yml
  • Add MIGRATIONS.md entry explaining how modules can add OpenAPI docs

Closes #3386

Test plan

  • Start dev server, visit /api/docs — verify tasks endpoints render in Scalar UI
  • Visit /api/spec.json — verify tasks paths and schemas are present in merged spec
  • Lint passes
  • Unit tests pass (434/434)

Summary by CodeRabbit

Release Notes

  • New Features

    • OpenAPI specification auto-discovery and dynamic merging across all modules, with consolidated API specification available at new /api/spec.json endpoint and interactive documentation UI at /api/docs
  • Documentation

    • Added reusable OpenAPI components and standardized response definitions for consistent API documentation
    • Added comprehensive Tasks API documentation with complete coverage of CRUD operations and statistics endpoints

Copilot AI review requested due to automatic review settings April 5, 2026 08:14
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

Warning

Rate limit exceeded

@PierreBrisorgueil has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 4 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 15 minutes and 4 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 46e14789-e7b1-47b3-88ae-20b82e6e0130

📥 Commits

Reviewing files that changed from the base of the PR and between a60097d and a8e6350.

📒 Files selected for processing (4)
  • lib/services/express.js
  • modules/core/tests/core.unit.tests.js
  • modules/tasks/doc/tasks.yml
  • modules/tasks/services/tasks.service.js

Walkthrough

This PR implements a module-based OpenAPI documentation system with auto-discovery and aggregation. It adds a /api/spec.json endpoint that merges OpenAPI YAML specifications from individual module directories with a shared base spec, implements validation and proper array concatenation during merging, defines reusable error/success response schemas in the core spec, and includes comprehensive unit tests validating the aggregation behavior.

Changes

Cohort / File(s) Summary
OpenAPI Aggregation & Serving
lib/services/express.js
Refactored spec merging logic to validate each loaded YAML (ensuring it's a plain object), skip invalid documents with logging, concatenate arrays instead of index-merging (for tags/servers/security), and extract spec-serving into a named serveSpec function. Short-circuits setup when swagger is enabled but no files are configured.
Core OpenAPI Base Spec
modules/core/doc/index.yml
Added reusable SuccessResponse and ErrorResponse schemas with standardized field structures, plus response definitions (Unauthorized, Forbidden, NotFound, UnprocessableEntity) for common API error scenarios.
Tasks Module API Documentation
modules/tasks/doc/tasks.yml
New OpenAPI spec documenting complete Tasks API surface including CRUD endpoints (GET /api/tasks, POST /api/tasks, GET/PUT/DELETE /api/tasks/{taskId}), a public stats endpoint (GET /api/tasks/stats), with schemas for Task, TaskCreate, and TaskUpdate plus parameter and security definitions.
Test Coverage & Migration Guide
modules/core/tests/core.unit.tests.js, MIGRATIONS.md
Added unit tests validating spec merging from multiple YAML files, error handling on load failures, and skipping of invalid documents while maintaining successful route registration. Updated migration docs describing the auto-discovery pattern, spec merging, and new /api/spec.json and /api/docs endpoints.

Sequence Diagram

sequenceDiagram
    participant InitSwagger as initSwagger()
    participant ModuleLoader as Module YAML Loader
    participant Validator as Spec Validator
    participant Merger as Spec Merger
    participant Server as Express Server
    participant Client as API Client

    InitSwagger->>ModuleLoader: Load modules/{name}/doc/{name}.yml<br/>+ modules/core/doc/index.yml
    ModuleLoader->>Validator: Parse YAML for each module
    Validator->>Validator: Verify is plain object
    Note over Validator: Skip invalid,<br/>throw on read failure
    Validator->>Merger: Pass validated specs
    Merger->>Merger: mergeWith customizer:<br/>concatenate arrays
    Merger->>Server: Register /api/spec.json route<br/>with merged spec
    Server->>Client: GET /api/spec.json
    Client->>Client: Receive merged OpenAPI JSON<br/>(paths, components, tags, etc.)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding OpenAPI YAML documentation for the tasks module API.
Description check ✅ Passed The description covers what changed, why (implied by documentation purpose), related issue #3386, scope, and validation steps, though the template sections are not fully structured per the provided template.
Linked Issues check ✅ Passed The PR fully addresses #3386 objectives: tasks.yml documents all CRUD endpoints with schemas/auth, core/doc/index.yml adds shared components, and MIGRATIONS.md explains the module doc pattern.
Out of Scope Changes check ✅ Passed All changes are in scope: tasks.yml and core/doc/index.yml docs, MIGRATIONS.md notes, and supporting unit tests/service code updates directly fulfill #3386 requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tasks-openapi-docs

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.

@PierreBrisorgueil
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces first-class OpenAPI documentation for the tasks module and switches the API docs UI from Swagger UI to Scalar, with a merged OpenAPI spec served from the backend.

Changes:

  • Add modules/tasks/doc/tasks.yml documenting tasks CRUD + stats endpoints.
  • Extend modules/core/doc/index.yml with shared SuccessResponse / ErrorResponse schemas and common error responses.
  • Update Express Swagger initialization to serve /api/spec.json and mount Scalar at /api/docs (and update related tests/config/migrations).

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
package.json Adds Scalar Express API reference dependency; removes swagger-ui-express.
package-lock.json Lockfile updates for Scalar dependency swap.
lib/services/express.js Replaces Swagger UI wiring with merged spec JSON + Scalar UI mounting.
config/defaults/development.config.js Removes obsolete Swagger UI options from defaults.
modules/core/doc/index.yml Adds shared schemas/responses for OpenAPI reuse.
modules/tasks/doc/tasks.yml New OpenAPI YAML for tasks endpoints and schemas.
modules/core/tests/core.unit.tests.js Adds unit coverage for initSwagger route registration/spec handler.
modules/audit/tests/audit.middleware.unit.tests.js Updates audit ignore prefix to match new /api/docs route.
MIGRATIONS.md Documents new OpenAPI module doc pattern and Scalar migration notes.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.16%. Comparing base (3e0081b) to head (a8e6350).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3389      +/-   ##
==========================================
+ Coverage   85.06%   85.16%   +0.09%     
==========================================
  Files         112      112              
  Lines        2860     2878      +18     
  Branches      781      787       +6     
==========================================
+ Hits         2433     2451      +18     
  Misses        337      337              
  Partials       90       90              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@lib/services/express.js`:
- Around line 27-39: The initSwagger function needs a JSDoc header and the
inline route handler should be extracted to a named function to satisfy repo
rules; add a JSDoc block above initSwagger with a one-line description, an
`@param` {Express.Application} app describing the Express app argument, and an
`@returns` {void} (or omit if void but include `@returns` per guideline), then move
the anonymous handler into a named function (e.g., serveSpec or getApiSpec) and
use that identifier in app.get('/api/spec.json', serveSpec) so both initSwagger
and the route handler are documented and readable; reference initSwagger and the
new serveSpec/getApiSpec function in your changes.

In `@modules/core/doc/index.yml`:
- Around line 45-50: The shared OpenAPI response "Unauthorized" currently
references the ErrorResponse schema but Passport-protected JWT endpoints return
401 with an empty body; update the docs by adding a new response definition
(e.g., "PassportUnauthorized") that omits the content/schema entirely, and
replace references to "Unauthorized" with "PassportUnauthorized" on
Passport-protected routes (or document those endpoints to use the new response)
so the spec accurately reflects the empty 401 responses returned by Passport.js
JWT routes.

In `@modules/core/tests/core.unit.tests.js`:
- Around line 483-507: The unit tests in core.unit.tests.js only load
modules/core/doc/index.yml so they don't verify that initSwagger's
merge/discovery pulls in other module specs (e.g., modules/tasks/doc/tasks.yml);
update the unit test that registers /api/spec.json to include at least one
additional module YAML (add modules/tasks/doc/tasks.yml to config.files.swagger)
and assert that the merged spec contains an expected path or operation from that
tasks.yml, and add an integration test that boots the real express app, issues
an HTTP GET to /api/spec.json and asserts the merged spec includes both openapi:
'3.0.0' and the task-specific path; refer to expressService.initSwagger and the
registered /api/spec.json handler when locating code to modify.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e5c5ed9d-0214-412d-95d2-42ff6d5cab70

📥 Commits

Reviewing files that changed from the base of the PR and between af0cc3f and 33cf328.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • MIGRATIONS.md
  • config/defaults/development.config.js
  • lib/services/express.js
  • modules/audit/tests/audit.middleware.unit.tests.js
  • modules/core/doc/index.yml
  • modules/core/tests/core.unit.tests.js
  • modules/tasks/doc/tasks.yml
  • package.json
💤 Files with no reviewable changes (1)
  • config/defaults/development.config.js

Document all task endpoints (CRUD + stats) with request/response schemas,
auth requirements, and path parameters. Add shared SuccessResponse and
ErrorResponse schemas to core index for reuse across modules.
- initSwagger: use _.mergeWith to concatenate arrays (not index-merge)
- initSwagger: guard empty file list, add filePath context on YAML errors
- initSwagger: add JSDoc @param/@returns
- tasks.yml: mark OrganizationId header deprecated with correct description
- tasks.yml: add 422 response to GET /api/tasks
- tasks.yml: update PUT description — both fields required, not partial
- tasks.yml: document full DELETE response (id + acknowledged + deletedCount)
- index.yml: add optional error field to ErrorResponse (non-prod only)
…rror cause

- Filter YAML.load results to plain objects (warn + skip null/array/primitive)
- Pass initial {} to reduce so single-file configs merge correctly
- Preserve original parse error as Error cause for better stack traces
…lti-module merge test

- index.yml: Unauthorized response updated to reflect Passport JWT returns empty
  body (no JSON envelope) on 401 — matches actual runtime behavior
- core.unit.tests.js: add test for multi-module YAML merge, asserting merged spec
  contains tasks paths and Task schema from modules/tasks/doc/tasks.yml
@PierreBrisorgueil PierreBrisorgueil force-pushed the feat/tasks-openapi-docs branch from 317ed60 to 252e913 Compare April 5, 2026 09:02
…nd non-object YAML guard

- Empty file list guard: verify initSwagger warns and skips route registration
- YAML parse error: verify throw includes failing file path in message
- Non-object YAML: verify scalar YAML files are skipped (filter(Boolean)) while valid
  files still produce a merged spec
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

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

Inline comments:
In `@lib/services/express.js`:
- Around line 54-61: After merging YAML docs into spec with contents.reduce, add
a guard that detects an empty/invalid merged spec (e.g., _.isEmpty(spec) or
Object.keys(spec).length === 0) and short-circuits the route registration path:
log or throw a descriptive error and return early (similar to the existing empty
file list check) so routes are not registered against an empty {}; update the
code around the spec variable computed by the reduce to perform this check
before any further processing or registration.

In `@modules/core/tests/core.unit.tests.js`:
- Around line 569-584: The test currently performs an asynchronous dynamic
import of fs inside a synchronous test callback so assertions run after test
completion; make the test function async and await the import('fs') promise
before writing the temp file and calling expressService.initSwagger, then run
the assertions and cleanup (unlinkSync) synchronously after awaiting; target the
mocha/jest test named "should skip YAML files..." and update its callback to
async and add await before import('fs') and any other async ops around tmpFile,
expressService.initSwagger, mockGet and mockUse usage.

In `@modules/tasks/doc/tasks.yml`:
- Around line 123-138: Update the PUT operation description to reflect that
TaskUpdate is a partial/optional schema (TaskUpdate and Zod's Task.partial()),
not requiring both title and description; change the sentence that claims "Both
`title` and `description` are required — omitting a field will overwrite it with
`undefined`" to state that fields are optional and omitted fields are left
unchanged (partial update), and ensure the wording mentions the CASL ownership
enforcement still applies (refer to the put operation and the TaskUpdate
schema).
- Around line 74-76: The POST create-task response is documented as '200' but
should be '201 Created' per REST conventions; update the tasks POST endpoint to
return 201 by changing the OpenAPI response entry from '200' to '201' and modify
the controller call that uses responses.success() to either call a new/existing
responses.created() helper or pass an explicit 201 status to
responses.success(); if you add a new helper, implement it in
lib/helpers/responses.js (alongside responses.success) to set status 201 and
return the same payload shape so the spec and implementation match.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9cbf1bdc-b7e6-4489-90ce-21bb445d0c43

📥 Commits

Reviewing files that changed from the base of the PR and between 33cf328 and a60097d.

📒 Files selected for processing (5)
  • MIGRATIONS.md
  • lib/services/express.js
  • modules/core/doc/index.yml
  • modules/core/tests/core.unit.tests.js
  • modules/tasks/doc/tasks.yml

Use async/await with dynamic import('fs') so the test works correctly
in Jest's experimental VM modules ESM mode
…pdate, PUT description

- express.js: add guard after reduce — warn and skip route registration if all
  YAML files were filtered and spec is empty ({})
- tasks.service.js: fix update to only assign defined fields (partial update),
  aligning with Zod TaskUpdate = Task.partial()
- tasks.yml: update PUT description to reflect actual partial-update behavior
- core.unit.tests.js: add test for empty-spec guard (all YAMLs skipped → no routes)
@PierreBrisorgueil PierreBrisorgueil merged commit 92241aa into master Apr 5, 2026
5 checks passed
@PierreBrisorgueil PierreBrisorgueil deleted the feat/tasks-openapi-docs branch April 5, 2026 09:45
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.

feat: document tasks module API (OpenAPI YAML)

2 participants