F10 — Roll-out: API back-compat audit
The performance program added new query params, two new POST/GET retrieve routes, a search-vector column, and evolved one list response shape. F10.1 audits every one of those changes against a single rule:An existing client that passes none of the new params must see the same response shape (no key removed, no array→object swap) as before the program.New behavior is opt-in. This note is the audit; the verdict column is what an old client experiences on a no-param call.
Query-param additions (all additive — old client unaffected)
New endpoints (purely additive)
Schema additions (no response surface)
The one response-shape evolution — and its gate
GET /collections/:id/records is the only route whose default response shape
changed. F6.2 (“cursor-paginate collection records, bounded by default”) evolved it
from a bare array CanonicalRecord[] to the keyset envelope
{ records, nextCursor }. A pre-F6.2 client doing res.map(...) / res.length
would break on the object.
Gate (F10.1, collections.controller.ts): the controller returns the legacy
bare array when the caller passes none of the new pagination/view params
(entity_id/drifted/updated_after/view/limit/cursor). status predates
F6.2 and does not opt a caller in. Any new param ⇒ the caller is
pagination-aware ⇒ the { records, nextCursor } envelope. The page stays bounded
(DEFAULT_RECORD_LIMIT) in both branches — the charter’s safety bound is preserved;
only the wrapper differs by opt-in.
- Accepted nuance: a no-param call is now bounded to
DEFAULT_RECORD_LIMIT(25) where it was once unbounded. This is a deliberate, charter-mandated safety bound (a large collection must never ship “everything” in one read). The shape (the load-bearing back-compat concern) is preserved; the bound is the intended improvement, and a client that needs more pages opts into the cursor.
collection records, MCP driftless_collection_record
action:list) are pagination-aware in F10.2 / F10.3 — they pass limit/cursor,
so they consume the envelope and page server-side rather than relying on the legacy
array.
Test: apps/api/src/collections/collections.controller.records-backcompat.integration.spec.ts
asserts: no-param ⇒ bare array; status alone ⇒ bare array; limit/cursor/view
⇒ envelope (and pages to exhaustion).
