Skip to content

fix(agent-bff): expose search on unfolded request schemas - #1863

Open
Tonours wants to merge 5 commits into
mainfrom
fix/prd-1103-unfolded-search
Open

fix(agent-bff): expose search on unfolded request schemas#1863
Tonours wants to merge 5 commits into
mainfrom
fix/prd-1103-unfolded-search

Conversation

@Tonours

@Tonours Tonours commented Aug 31, 2026

Copy link
Copy Markdown
Member

What

The unfolded (per-collection) OpenAPI document exposes search and searchExtended on every list and count request. Generated clients were missing both inputs although the runtime honours them on all four path families — list, count, relation list, relation count.

  • ListRequest_<key> and CountRequest_<key> carry search / searchExtended as $refs to one shared Search / SearchExtended pair, registered through ComponentPool.reuse exactly like Page and Timezone.
  • Relation requests inherit both through their allOf head.
  • The relation descriptions are split by shape: list says "Filter, sort, projection and search", count says only "Filter and search". The previous shared string promised sort and projection to count, which carries neither.
  • The count description no longer says "matching a filter and a search" — both keys are optional, and the useful statement is the one the generic document already made: it accepts the same search inputs as list, so a count can be trusted against the list it describes.

fixes PRD-1103

Overlaps with #1855

That branch closes the request bodies (additionalProperties: false) and, to do it, had to publish search / searchExtended on the unfolded bodies too — a closed body that omits an input the runtime accepts would declare valid requests invalid. So the two PRs touch the same lines, deliberately, from opposite directions.

Whichever lands second will conflict on registerRequests. #1855 also flattens the relation bodies out of their allOf, so the "relations inherit through the allOf head" sentence above becomes stale once it merges — the inputs then arrive by spread instead, and the outcome for a consumer is identical.

Known limitation

Same as the generic document: a collection that is not searchable still shows a documented search input, and using it answers 400 "Collection is not searchable". Gating on a searchable flag needs a signal the BFF capabilities do not carry today.

How to test

  • yarn workspace @forestadmin/agent-bff test test/openapi — redocly lint over the served document included
  • yarn workspace @forestadmin/agent-bff test
  • Two consecutive builds of the unfolded document produce identical bytes.

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 31, 2026

Copy link
Copy Markdown

PRD-1103

@qltysh

qltysh Bot commented Aug 31, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (1)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/agent-bff/src/openapi/unfolded-paths.ts100.0%
Total100.0%
🚦 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.

@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.

Read against PRD-1103 and the repo standards. The fix itself is right: search / searchExtended land on the unfolded ListRequest_* / CountRequest_* as $refs to shared components, the property order matches the generic ListRequestSchema / CountRequestSchema so the new parity test passes for the right reason, and relations inherit both through the allOf head. ActionRequest is the only other generic request shape and it has no missing input, so nothing else of this bug class is open. Two wording notes below.

Comment thread packages/agent-bff/src/openapi/openapi-document.ts Outdated
Comment thread packages/agent-bff/src/openapi/unfolded-paths.ts Outdated
@Tonours

Tonours commented Sep 1, 2026

Copy link
Copy Markdown
Member Author

Review pass done — GO, no findings on the change itself. Every claim checked against the runtime: all four path families really do honour search/searchExtended (request-schemas.ts, both relation parsers spreading the same flat inputs, all four handlers reaching applySearch), the unfolded keys match the generic ones in order, and relations inherit through the allOf head.

It did surface two pre-existing omissions in the same prose I was already editing, so they are fixed here rather than left for a third pass:

  • README.md:14 listed "filter, projection and paging" — sort was missing too, not just search.
  • The 415 dropped-inputs sentence listed "filter, search, sort, or page" and omitted projection, which a non-JSON content type drops exactly the same way.

Both now name every input that travels in the body.

One thing worth flagging for whoever merges: this PR and #1855 touch the same lines from opposite directions. #1855 closes the request bodies with additionalProperties: false, and to do that it had to publish search/searchExtended on the unfolded bodies too — a closed body omitting an input the runtime accepts would declare valid requests invalid. It also flattens the relation bodies out of their allOf, so the "relations inherit through the allOf head" sentence in this description goes stale once it lands; the inputs then arrive by spread and a consumer sees no difference. Whichever merges second resolves registerRequests.

@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.

Approving. The fix is right where it matters: search / searchExtended land on the unfolded ListRequest_* / CountRequest_* as $refs to one shared component pair registered like Page and Timezone, the property order matches the generic ListRequestSchema / CountRequestSchema so the new parity test passes for the right reason, and relations inherit both through the allOf head. ActionRequest is the only other generic request shape and it carries no missing input, so nothing else of this bug class is open.

Both wording notes addressed — the README sentence now names search (and sort), and the count description reuses the generic phrasing.

@Tonours
Tonours force-pushed the fix/prd-1103-unfolded-search branch from f1cf465 to 1ad9d90 Compare September 2, 2026 16:19
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