You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[O2B-1623] Add HTTP API documentation (OpenAPI spec, generated reference and /api-docs page) - #2261
The HTTP API is now documented at /api-docs (styled page with collapsible endpoints and curl examples). Raw versions are available at /api-docs/API.md (Markdown, suited for LLMs) and /api-docs/openapi.yaml (OpenAPI 3.1 spec, suited for tools and MCP servers).
Pilot: only the tags endpoints are documented so far.
The pages are served without authentication; calling the API from them still needs a token.
GET /api/tags/:tagId/runs and GET /api/tags/:tagId/log are removed: they only ever answered 501 Not implemented (or were never bound). They now answer 404 like any unknown route. The GUI and the tests did not use them.
Notable changes for developers:
lib/server/api-docs/openapi.yaml is the only file to edit by hand. Run npm run docs:api afterwards to regenerate API.md and index.html (generated, committed, never edited by hand). The generator is scripts/build-api-docs.js and the page styles are in scripts/api-docs.css.
Every non-GET operation must declare x-llm-exclude: true|false (write operations are not meant for LLM / MCP tool use); the generator fails otherwise. The spec also gives LLMs usage rules (always paginate, 100 items per request at most).
Security of the generator: spec content is treated as untrusted. Raw HTML and unsafe link schemes are neutralised, and values put in curl examples are shell-quoted. Checked with hostile input (quote break-out, $(...), HTML in title and description, javascript: links).
New devDependencies: js-yaml 4.3.2 (already in the lockfile through eslint) and marked 18.0.14 (MIT, no dependencies, no install scripts, released more than two weeks ago). Neither is shipped to production. npm audit reports nothing for them (it still reports the existing vulnerable js-yaml 3.x nested in nyc).
WebUiServer serves the three files from lib/server/api-docs/ (inside lib/ so they are part of the Docker image and the dev bind mount).
Tags router: removed the duplicated /runs route whose controller (TagsController.patchRun) does not exist, the two 501 stub routes and their stub controllers (getRuns, patchLog).
The route binder (lib/server/routers/index.js) now throws, naming the route, when a route declares a controller that is not a function. Before, such routes were silently skipped, which hid the missing patchRun. Grouping nodes without a controller key (/statistics, /dpl-process) are unaffected. Unit tests added in test/lib/server/routers.
Not included yet: a test checking the spec against the routers, and a CI check that the generated files are up to date.
Describe the tags endpoints (list, create, get by id or name, update, delete, logs of a tag) with parameters, schemas, errors, required roles and
examples. Operations that change data are flagged `x-llm-exclude: true`, and the spec carries instructions for LLMs (always paginate, 100 items max).
`npm run docs:api` builds `API.md` (Markdown with curl examples) and `index.html` (styled page, collapsible endpoints) from the OpenAPI spec.
- Fails when a non-GET operation does not declare `x-llm-exclude`
- Spec content is treated as untrusted when rendering: raw HTML is escaped, unsafe link schemes are dropped, and values put in curl examples are
shell-quoted
- New devDependencies `js-yaml` (already in the lockfile through eslint) and `marked`, pinned to a release older than two weeks
Serve the generated HTML page (`/api-docs`), the Markdown version for LLMs (`/api-docs/API.md`) and the spec (`/api-docs/openapi.yaml`). The files
live under `lib/server` so that they are part of the Docker image.
❌ Patch coverage is 70.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.46%. Comparing base (eca7057) to head (99dbed6).
- `GET /tags/:tagId/runs` was declared twice: once with a controller answering 501 and once with `TagsController.patchRun`, which does not exist,
so the binder silently skipped it
- `GET /tags/:tagId/log` answered 501 as well
None of them is used by the GUI or covered by tests, and none did anything but advertise endpoints that do not exist. They now answer 404 like any
unknown route. The matching `getRuns` and `patchLog` stub controllers are removed.
… not a function
The route binder silently skipped routes whose controller was undefined (for example a typo or a missing export, as with the removed
`GET /tags/:tagId/runs`). It now throws, naming the route. Nodes that only group children, such as `/statistics` and `/dpl-process`, are not affected.
Unit tests check that every declared route binds, that grouping nodes are ignored, and that undefined controllers (alone or inside a list) are rejected.
- Allow epoch milliseconds for archivedAt in UpdateTag
- URL-encode query values in the curl examples
- Darken method badge and link colours to reach a 4.5:1 contrast
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Six unresolved moderate findings affect API accuracy, generated shell examples, and untrusted-content sanitization.
No open issues 🎉
3 previously missed issues
In code that hasn't changed since last review
Missing required validation for query.name
lib/server/api-docs/openapi.yaml:131
GetTagByNameDto does not mark query.name as required, so a request without this parameter passes DTO validation and decodeURIComponent(undefined) in the controller path can throw instead of returning the documented validation response. Either make the DTO field required (with a regression test) or change this contract to match the current behavior before publishing it as the API reference.
Tag pattern incorrectly documents and enforces allowed characters
lib/server/api-docs/openapi.yaml:320
The description says tag text permits only words, digits, -, and +, but the pattern includes | in its character class and is not anchored; it therefore documents stricter validation than the current CreateTagDto actually enforces (for example, UNIX:... already passes the server validation). Anchor/fix the DTO and schema together, or describe the real accepted values here.
POSIX shell escaping corrupts exclamation marks in URLs
scripts/build-api-docs.js:72
This shell escaping incorrectly prefixes ! with a backslash inside a double-quoted POSIX shell string. POSIX shells preserve that backslash ("a\\!b" becomes a\\!b), while encodeURIComponent leaves ! unescaped, so a spec value containing ! produces a different URL in the generated curl example. Do not escape ! for POSIX double quotes, or quote the complete URL with a method that handles all values correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I have a JIRA ticket
Notable changes for users:
/api-docs(styled page with collapsible endpoints andcurlexamples). Raw versions are available at/api-docs/API.md(Markdown, suited for LLMs) and/api-docs/openapi.yaml(OpenAPI 3.1 spec, suited for tools and MCP servers).tagsendpoints are documented so far.token.GET /api/tags/:tagId/runsandGET /api/tags/:tagId/logare removed: they only ever answered501 Not implemented(or were never bound). They now answer 404 like any unknown route. The GUI and the tests did not use them.Notable changes for developers:
lib/server/api-docs/openapi.yamlis the only file to edit by hand. Runnpm run docs:apiafterwards to regenerateAPI.mdandindex.html(generated, committed, never edited by hand). The generator isscripts/build-api-docs.jsand the page styles are inscripts/api-docs.css.x-llm-exclude: true|false(write operations are not meant for LLM / MCP tool use); the generator fails otherwise. The spec also gives LLMs usage rules (always paginate, 100 items per request at most).curlexamples are shell-quoted. Checked with hostile input (quote break-out,$(...), HTML in title and description,javascript:links).js-yaml4.3.2 (already in the lockfile through eslint) andmarked18.0.14 (MIT, no dependencies, no install scripts, released more than two weeks ago). Neither is shipped to production.npm auditreports nothing for them (it still reports the existing vulnerablejs-yaml3.x nested innyc).WebUiServerserves the three files fromlib/server/api-docs/(insidelib/so they are part of the Docker image and the dev bind mount)./runsroute whose controller (TagsController.patchRun) does not exist, the two501stub routes and their stub controllers (getRuns,patchLog).lib/server/routers/index.js) now throws, naming the route, when a route declares a controller that is not a function. Before, such routes were silently skipped, which hid the missingpatchRun. Grouping nodes without acontrollerkey (/statistics,/dpl-process) are unaffected. Unit tests added intest/lib/server/routers.Changes made to the database:
🤖 Generated with Claude Code