Skip to content

feat(openapi): describe the catalog read endpoints (browse + sync)#5790

Merged
bokelley merged 1 commit into
mainfrom
feat/openapi-catalog-browse-sync
Jul 1, 2026
Merged

feat(openapi): describe the catalog read endpoints (browse + sync)#5790
bokelley merged 1 commit into
mainfrom
feat/openapi-catalog-browse-sync

Conversation

@bokelley

@bokelley bokelley commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Completes the property-catalog OpenAPI surface started in #5787 — the read/consume side of the "send us facts" loop (resolve → sync locally → build lists), from RFC #5782.

Problem

GET /api/registry/catalog and /catalog/sync are live but were absent from static/openapi/registry.yaml, so the SDK's browseCatalog/syncCatalog (the only pieces of #5782 not yet in @adcp/sdk 9.7.0) couldn't be typed.

Change (documentation of live endpoints — no behavior change)

  • browseCatalogGET /api/registry/catalog: filtered, cursor-paginated browse; each entry carries the property's identifiers[].
  • syncCatalogGET /api/registry/catalog/sync: delta since a server_timestamp watermark (capped 10,000/page) — a different pagination mechanism from browse's opaque cursor, documented as such.
  • Schemas mirror the route handlers + catalog-db result types exactly (browse entries include identifiers[]; sync entries are raw CatalogProperty with timestamps). property_rid documented as a non-authoritative handle, per feat(openapi): describe the property-catalog fact-contribution endpoints #5787.

Where it fits

Closes the loop after 9.7.0, which shipped the write surface (resolveIdentifiers, fileCatalogDispute/getCatalogDispute, claim/verify, saveProperty). Once this publishes, adcp-client regenerates types and adds browseCatalog() / syncCatalog() — then the full RFC #5782 surface is real end-to-end.

🤖 Generated with Claude Code

Completes the property-catalog OpenAPI surface started in #5787. The catalog
read/consume endpoints are live but were absent from static/openapi/registry.yaml,
so the SDK's read-side (browseCatalog/syncCatalog — the second half of the
resolve→sync→build-lists loop from RFC #5782) couldn't be typed.

- browseCatalog — GET /api/registry/catalog: filtered, cursor-paginated browse;
  each entry carries the property's identifiers.
- syncCatalog — GET /api/registry/catalog/sync: delta since a `server_timestamp`
  watermark (capped 10,000/page), distinct from browse's opaque cursor.

Schemas mirror the route handlers + catalog-db result types (browse entries
carry identifiers[]; sync entries are raw CatalogProperty with timestamps).
property_rid documented as a non-authoritative handle, consistent with #5787.

Once published, adcp-client regenerates types and adds browseCatalog()/
syncCatalog() alongside the shipped resolveIdentifiers/fileCatalogDispute/
claim/verify surface (@adcp/sdk 9.7.0). No behavior change — documentation of
live endpoints only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mintlify

mintlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
adcp 🟢 Ready View Preview Jul 1, 2026, 7:09 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@aao-release-bot aao-release-bot 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.

Clean documentation of two live endpoints. Right shape: browse and sync are genuinely different pagination mechanisms (opaque keyset cursor vs. monotonic watermark), and documenting them as distinct rather than forcing one abstraction is correct.

Things I checked

  • Browse schema mirrors the handler. CatalogBrowseEntry (property_rid, property_id, classification, source, status, identifiers[]) matches the object built at catalog-api.ts:210-217 exactly; identifiers reuses CatalogIdentifier {type,value}, matching the { type: i.identifier_type, value: i.identifier_value } projection at L216. Response {entries, total, next_cursor} matches listProperties (catalog-db.ts:393-397). All 9 query params are optional and match the req.query.* reads.
  • Sync schema mirrors CatalogProperty field-for-field. All 10 columns present with correct nullability (property_id, adagents_url, created_by nullable; rest required), matching the interface at catalog-db.ts:19-30 and the SELECT * at L406. All 10 in the required array — sound, since NOT NULL guarantees presence.
  • Timestamps typed string. created_at/updated_at/source_updated_at are Date in TS but pg + res.json serialize to ISO strings; z.string() is the on-the-wire shape. Correct.
  • since marked required: true — handler 400s when absent (catalog-api.ts:237-239), and the schema wires that 400 to ErrorSchema ({error: string}). Fail-closed on the required watermark.
  • Generated yaml is consistent with the .ts — field order, nullability, required arrays, examples all match. test:openapi gates any drift.
  • property_rid framing — "non-authoritative join/match handle, never an authorization credential" is verbatim-consistent with the #5787 baseline. ad-tech-protocol-expert: sound-with-caveats, no spec drift, operationIds SDK-safe.
  • No changeset expected: this edits server-internal OpenAPI source plus its generated artifact — not static/schemas/source/**, docs/reference/**, or a spec-package build script.

Follow-ups (non-blocking — file as issues)

  • min_resolves and active_since are documented but no-ops. listProperties (catalog-db.ts:330-398) never reads filters.min_resolves or filters.active_since — the handler passes them through, so the doc is faithful to the handler, but the DB layer ignores them. Documenting a param that does nothing will mislead SDK users. Either wire them up or drop them from the surface.
  • Sync pagination is dual, not watermark-only. syncProperties returns both server_timestamp and a next_cursor (the last row's property_rid, set when a page fills — catalog-db.ts:414). The syncCatalog description says pagination is "by the returned server_timestamp watermark," which undersells next_cursor: a since window exceeding 10,000 rows must page via the cursor, with ORDER BY updated_at, property_rid implying watermark-advances-window / cursor-tiebreaks-within. The schema correctly declares both required, so the contract is right — only the prose is imprecise. One-line clarification would close it.

LGTM. Follow-ups noted below.

@bokelley bokelley merged commit dc19f75 into main Jul 1, 2026
15 checks passed
@bokelley bokelley deleted the feat/openapi-catalog-browse-sync branch July 1, 2026 20:03
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.

1 participant