Skip to content

feat(agent-bff): serve the static OpenAPI document behind the agent gate - #1810

Open
Tonours wants to merge 3 commits into
mainfrom
feature/prd-886-openapi-static-document
Open

feat(agent-bff): serve the static OpenAPI document behind the agent gate#1810
Tonours wants to merge 3 commits into
mainfrom
feature/prd-886-openapi-static-document

Conversation

@Tonours

@Tonours Tonours commented Aug 6, 2026

Copy link
Copy Markdown
Member

Stacked on #1809 (chore/dedupe-zod-single-v4-resolution). Base is that branch, not main; #1809 must be reviewed and merged first. Hard prerequisite: @asteasolutions/zod-to-openapi takes zod as a peer dependency, so without the dedupe yarn can bind it to a different zod copy than the one agent-bff builds its schemas from.

fixes PRD-886

What

GET /agent/openapi.json serves an OpenAPI 3.1 document describing the six generic BFF routes (list, count, relation list/count, action form/execute). Generated from Zod, built once at boot, static: path placeholders only, no tenant data. The only environment-derived value is the package version.

Why this mount point

The BFF has no deny-by-default gate: auth applies only to paths under /agent. Mounting the route inside the agentScoped chain, right after the auth middlewares, inherits the existing gate, so an unauthenticated request gets a 401 before path matching. Root mounting would have made the document public. The route sits before buildAgentRouteMiddlewares, so it answers even when AGENT_URL is unset and never calls the agent.

How

  • New src/openapi/ module: extendZodWithOpenApi loaded once, request/response/error schemas, registry plus OpenApiGeneratorV31, and a serializeOpenApi shared with the future CLI subcommand.
  • Schemas written against the code, not prior docs: /agent/v1 prefix, recursive condition-tree filter, PascalCase operators (required), sort[].direction optional, page.offset must be a multiple of limit, parentId string or number, recordIds required even when empty.
  • Every status a route actually returns is declared, including 502 (transport failure), 413 (16kb body cap), 429 (agent rate-limiting). 501 is declared only on execute and points at a separate schema because that body carries no message field.
  • Additive: the only edit outside src/openapi/ is one line in the cli-core.ts middleware chain. No existing route, handler, or schema changed.

Known limits: action 200 responses are typed unknown (belongs with the action work); relation list/count skip capabilities validation, so their 422 field errors are unreachable, and the ConditionTree description says so (#1801 fixes the validation gap). Per-collection unfolding is PRD-684/PRD-685.

How to test

yarn workspace @forestadmin/agent-bff test
yarn workspace @forestadmin/agent-bff lint

Against a running agent:

FOREST_AUTH_SECRET=... FOREST_ENV_SECRET=... FOREST_SERVER_URL=... \
FOREST_APP_URL=... AGENT_URL=http://localhost:3009/forest HTTP_PORT=4599 \
node packages/agent-bff/dist/cli.js

curl -i localhost:4599/agent/openapi.json                        # 401, no document
curl -i localhost:4599/openapi.json                              # 404
curl -s -H "X-Forest-Bff-Key: <session>" \
  localhost:4599/agent/openapi.json | npx @redocly/cli lint -    # valid

Ran on this branch: 767 tests pass (41 added), lint and build clean. redocly lint runs inside the suite, so the document cannot go invalid unnoticed. An end-to-end pass against a live agent covered the 401 gate (no leak in the body), the root 404, the authenticated 200, redocly validation over HTTP, and eight unauthenticated path variants (trailing slash, case change, %6f, dot segments, .., doubled slash): none serves the document.

Definition of Done

General

  • Write an explicit title for the Pull Request, following Conventional Commits specification
  • Test manually the implemented changes
  • Validate the code quality (indentation, syntax, style, simplicity, readability)

Security

  • Consider the security impact of the changes made

@linear-code

linear-code Bot commented Aug 6, 2026

Copy link
Copy Markdown

PRD-886

Comment thread packages/agent-bff/src/openapi/openapi-document.ts Outdated
Comment thread packages/agent-bff/src/openapi/openapi-document.ts
Comment thread packages/agent-bff/src/openapi/schemas.ts
@Tonours
Tonours force-pushed the feature/prd-886-openapi-static-document branch from ba29239 to dc83756 Compare August 6, 2026 17:19
Comment thread packages/agent-bff/src/openapi/schemas.ts
@Tonours
Tonours force-pushed the feature/prd-886-openapi-static-document branch 3 times, most recently from 595c4b6 to ece634c Compare August 6, 2026 17:48
@Tonours
Tonours force-pushed the feature/prd-886-openapi-static-document branch from ece634c to b11c332 Compare August 6, 2026 20:48
@qltysh

qltysh Bot commented Aug 7, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (6)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/agent-bff/src/cli-core.ts100.0%
New Coverage rating: A
packages/agent-bff/src/openapi/openapi-document.ts100.0%
New Coverage rating: A
packages/agent-bff/src/openapi/zod-openapi.ts100.0%
New Coverage rating: A
packages/agent-bff/src/http/body-limit.ts100.0%
New Coverage rating: A
packages/agent-bff/src/openapi/schemas.ts100.0%
New Coverage rating: A
packages/agent-bff/src/openapi/openapi-routes.ts91.7%20
Total98.7%
馃 Increase coverage with AI coding...
In the `feature/prd-886-openapi-static-document` branch, add test coverage for this new code:

- `packages/agent-bff/src/openapi/openapi-routes.ts` -- Line 20

馃殾 See full report on Qlty Cloud 禄

馃洘 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@Tonours
Tonours force-pushed the chore/dedupe-zod-single-v4-resolution branch from 3e81c4b to 04d3ba9 Compare August 7, 2026 07:39
@Tonours
Tonours force-pushed the feature/prd-886-openapi-static-document branch from d51081e to 9652148 Compare August 7, 2026 07:42
@Tonours
Tonours force-pushed the feature/prd-886-openapi-static-document branch from 9652148 to ec8c3e0 Compare August 7, 2026 13:01
Base automatically changed from chore/dedupe-zod-single-v4-resolution to main August 10, 2026 09:43
Comment thread packages/agent-bff/src/openapi/openapi-routes.ts

@nbouliol nbouliol left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Clean additive change, the gate placement and test coverage are solid.

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.

2 participants