Uh oh!
There was an error while loading. Please reload this page.
fix(qa): HttpTestAdapter resolves the Data Protocol mount from discovery, and degrades loudly - #9385
Conversation
…degrades loudly (#7983) The record action types built their URLs from the DEFAULTS of RestApiConfigSchema.apiPath and CrudEndpointsConfigSchema.dataPrefix, so a deployment that moved the mount got a 404 that reads like the suite author's own URL mistake. The adapter now probes `{apiBase}/discovery` once per run and addresses whatever `routes.data` advertises, following the getRoute precedent in @objectstack/client; the schema-derived convention stays as the fallback and taking it is announced, naming the mount, the evidence and the remedy. Co-Authored-By: Claude <noreply@anthropic.com>
) The knownGaps entry and the deployment/cli.mdx paragraph both said the record action types address the DEFAULT mount only. The discovery probe closes the crud.dataPrefix row, so both are NARROWED rather than deleted: api.apiPath moves the discovery document itself out from under the probe and is still out of reach, and that row must keep saying so. Adds the changeset with the measured before/after table. Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 23 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive: ⛔ 3 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop):
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#7983
The record-shaped
os testaction types (create_record,read_record,update_record,delete_record,query_records) built their URLs from the defaults ofRestApiConfigSchema.apiPathandCrudEndpointsConfigSchema.dataPrefix, becauseHttpTestAdapteris handed an origin and nothing else. A deployment that moved the mount got a 404 that reads like the suite author's own URL mistake rather than a platform limitation.The adapter now asks the server, following the
getRouteprecedent in@objectstack/client(copied from, never edited — that package is another card's this round): one memoisedGET {apiBase}/discoveryper run, addressing whateverroutes.dataadvertises, with the schema-derived convention as the fallback.What this closes, and what it does not
Measured per config off
RestServer's own normalized config — both bases read back from the server, never recomputed by the harness:/api/v1/datacrud.dataPrefix: '/objects'/api/v1/objectsHTTP Error 404api.apiPath: '/api/2026-01'/api/2026-01/dataHTTP Error 404HTTP Error 404, now naming the mountThe
apiPathrow is not closed, and the reason is structural rather than an oversight:registerDiscoveryEndpointsmounts the document at${basePath}/discovery(rest-server.ts), soapiPathmoves the base that discovery itself sits under — the document that would name the new mount is behind the very prefix the probe is missing. ThedataPrefixrow closes exactly because the discovery handler substitutes the configured prefix intoroutes.data(rest-server.ts), so reading it beats recomputing it here.The one discovery document at a fixed path does not rescue the
apiPathcase, and is deliberately not probed:/.well-known/objectstackis the runtime dispatcher's, andgetDiscoveryInfocomposesdata: ${prefix}/datafrom the dispatcher's own prefix — it never readscrud.dataPrefixor the RESTapiPath, so it reports/api/v1/datawhatever the REST server serves. Trusting it would attach a false provenance ("discovery told us") to the same 404.So that case degrades loudly instead (Route and surface ownership section 3): the fallback prints a warning naming the mount it will address, the probe that failed and the remedy, and every 404/405 from a record action carries the mount it addressed and where that mount came from. A 400/422 is left undecorated — it reached the right route and got a real answer, so burying the server's own message under a URL would mislead.
api_callis unchanged, issues no probe at all, and remains the escape hatch for a host the probe cannot reach. Per the Zone 1 ruling on the card, noos test --api-pathflag is added — that would widen the public CLI surface.Docs and checklist
Both places this limitation was written down are narrowed, not deleted, because the
apiPathrow is still a real gap: thefixtures.knownGapsentry indocs/qa/platform-checklist/areas/cli.json(item revision 3, with its history row) and the paragraph incontent/docs/deployment/cli.mdx.Tests
packages/core/src/qa/http-adapter.test.tspins the record URLs against a discovery document that deliberately advertises a non-default mount, so a pin that ignored the probe would still pass and does not. Also pinned: one probe per run including concurrent starts, the bearer token on the probe, the dispatcher's{ data: ... }envelope as well as the bare document, four distinct fallback modes each asserting mount plus evidence plus remedy, warn-once-per-run, that/.well-known/is never probed, and thatapi_callneither probes nor gets decorated.Verification
All run on
99592d0ab, the head of this branch:pnpm --filter @objectstack/core test— 35 files, 857 tests passed.pnpm check:type-check-debt— the ratchet re-measured 33 ledger entries, 1926 raw tsc errors, none above its recorded number, "surplus: none". This is the real typecheck for this package:@objectstack/corehas notypecheckscript, so a filtered invocation would match zero scripts and exit 0 without checking anything.node scripts/pm/dispatch-gates.mjsand run:check:changeset-gate-self-tests,check:cross-package-test-inputs,check:docs-audit-scope,check:docs-redirects,check:role-word,check:kernel-hook-pairs,check:test-source-alias,check:objectui-changeset, the four@objectstack/specliveness checks,check:adr-0087-registration,check:changeset-no-major,check:empty-changeset,check:cross-package-test-inputs,docs-audit/check-affected-docs, plus the convention-triggered test-file familycheck:query-options-erasure,check:engine-double-contract,check:where-matcher,check:type-check-coverage. All green.packages/restdirect-mount-base-follows-apipath.test.ts— 6/6, corroborating that discovery followsapiPath.No gate was weakened, no threshold lowered, no baseline rebaselined, no test skipped.
Generated by Claude Code