Uh oh!
There was an error while loading. Please reload this page.
chore(spec): govern the four RestServerConfig sub-objects in the liveness ledger - #14638
Conversation
…ess ledger WIP Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
…ness ledger Four new ledger files classify all 32 authorable properties of CrudEndpointsConfigSchema, MetadataEndpointsConfigSchema, BatchEndpointsConfigSchema and RouteGenerationConfigSchema — the RestServerConfig sub-objects a host writes when it constructs the REST server — enrolled through the gate's SPEC_ONLY_SCHEMAS override, the route query / qa / manifest already take. 17 properties are live with a symbol-anchored consumer and a producer pointer at the normalizer. 15 are dead: the ten keys the census measured, with crud.patterns and routes.overrides expanded into a row per member. No key is removed, enforced, deprecated or re-described; rest-server.zod.ts is not edited. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
📓 Docs Drift Check
What this run could not see
Coarse fallback — 128 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#14369
Lands the ten declared-but-unread
RestServerConfigkeys in the liveness ledger, with the census re-run and pinned to a ref. Per the triage ruling, the dispatchable unit is the LEDGER: no key is removed, enforced, deprecated or re-described,packages/spec/src/api/rest-server.zod.tsis not edited, and the@examplefence is left for the per-key follow-up.Correction: the card's named landing is wrong-typed
The card names
packages/spec/liveness/api.json. Measured onorigin/main, that file isApiEndpointSchema's ledger ("type": "api", and its onlycacheTtlrow isApiEndpointSchema.cacheTtl, a different key fromRestServerConfig.metadata.cacheTtl).RestServerConfigSchemais server/plugin construction config and is not a registered metadata type, so appending rows toapi.jsonwould have put them under a schema the gate never walks — orphan rows on arrival.The route non-metadata-type schemas take is
SPEC_ONLY_SCHEMASinpackages/spec/scripts/liveness/check-liveness.mts, the wayquery,webhook,validation,qaandmanifestare governed. This PR follows that precedent.Why four roots and not one
RestServerConfigSchemais the obvious single root and measurement rules it out. The ledger walk drills exactly one level (check-liveness.mtsclassifiesprops[key]and, when the entry declareschildren, one level beneath it — there is no recursion, and no ledger file in the repo carries nestedchildren). With the whole config as the root, the four sub-objects would BE the drilled level, sometadata.endpoints.schemaandbatch.operations.upsertMany— two of the card's ten — would have no row of their own. Their container's blanket verdict would belive(three of four members gate a real route mount), silently covering a dead key: the #4956 shape, in the file written to end it.Rooting on the four sub-schemas puts every one of the ten keys at a drillable coordinate, so each carries its own falsifiable verdict.
RestApiConfigSchema(the fifth sub-object,api) is deliberately not enrolled — its consumption seam is still validate-only and is the subject of #14366, so a census of it would record a half that is about to move.Container coverage is unchanged by this PR: still 58 blanket verdicts over 301 child keys, 7 deferrals over 273. No row is added to
undrilled-containers.baseline.json— the shrink-only ratchet is not touched.Files
packages/spec/liveness/crud_endpoints.jsoncrud_endpoints=CrudEndpointsConfigSchemapackages/spec/liveness/metadata_endpoints.jsonmetadata_endpoints=MetadataEndpointsConfigSchemapackages/spec/liveness/batch_endpoints.jsonbatch_endpoints=BatchEndpointsConfigSchemapackages/spec/liveness/route_generation.jsonroute_generation=RouteGenerationConfigSchemaEnrolment:
GOVERNED+SPEC_ONLY_SCHEMASinpackages/spec/scripts/liveness/check-liveness.mts(import + four entries + the rationale block).README.mdgains four "Current state" rows and its heading moves 31 → 35;state-counts.mdwas regenerated by the gate (pnpm --filter @objectstack/spec gen:liveness-counts), never by hand.Census, re-run and pinned
Ref:
2514d49f388e898e666ae04f19ba376d04db5422(2514d49f3), the merge base this branch is cut from. Method: read sites inpackages/rest/srcnon-test sources, excludingNormalizedRestServerConfig's type declaration (rest-server.tslines 723-786) andnormalizeConfigitself (3518-3616), comments excluded; plus a repo-wide grep outsidepackages/specand that file; plusobjectui@d4c6a86.routes.includeObjectsroutes.excludeObjectsroutes.nameTransformroutes.overridesenabled/basePath/operations)crud.patternsmethod/path/summary/description)crud.objectParamStylemetadata.cacheTtlmetadata.endpoints.schemabatch.defaultAtomicbatch.operations.upsertManyTen keys, fifteen rows: the two container keys are expanded into a row per member so the verdict is falsifiable per key rather than inherited. The card's first list is confirmed live in the same pass and carries
liverows withpath#symbolevidence plus aproducerpointer atrest-server.ts#normalizeConfig:crud.operations.{create,read,update,delete,list}andcrud.dataPrefix(5 independent consumers);metadata.{prefix,enableCache,maskObjectFields}andmetadata.endpoints.{types,items,item};batch.{maxBatchSize,enableBatchEndpoint}andbatch.operations.{createMany,updateMany,deleteMany}.Repo-wide grep for
nameTransform/objectParamStyle/defaultAtomicoutsidepackages/specandrest-server.tsreturns only changesets, the generated reference pagecontent/docs/references/api/rest-server.mdx, and #11984's own refusal tests — no consumer.objectui@d4c6a86is clean (0 hits for every key, and 0 forRestServerConfigitself). The closed cloud runtime was not reachable from the measuring container, so every row declares"evidenceScope": "in-repo"rather than claiming a sweep that was not run.No premise change. All ten keys still measure 0. Two sharpenings the re-run added, both recorded in the rows rather than acted on:
metadata.endpoints.schemagates a route that does not exist (packages/rest/srcmounts no path ending in/schemaat all), andbatch.operations.upsertManyis its twin (the protocol carriescreateManyData/updateManyData/deleteManyDataand noupsertManyData).metadata.cacheTtl's negative-bound observation travels in that key's ledger note, per the triage ruling, and is not filed as a separate defect.What #11984 settled, and what it did not
Kept as the note's own distinction: #11984 made
RestServer.normalizeConfigPARSE and CONSUME these four sub-objects instead of casting them, so an out-of-enum or out-of-range value is refused at construction. That settles accept/reject. Executing a declared contract does not give a key a consumer — which is whyroutes.nameTransformis validated against its enum and still mounts exactly what'none'mounts.Out of scope, reported not fixed
api.documentationandapi.responseFormat(and their children) also measure 0 read sites inpackages/rest/srcat this ref — dead keys in the same declared-but-unenforced class, on the one sub-object this PR does not enrol. Not classified here and not filed as part of this card; recorded for the dev report so theapihalf can be dispatched with the finding in hand.Changeset
packages/spec/liveness/**is named inpackages/spec'sfiles, so the ledgers ship in the published tarball — apatchchangeset for@objectstack/specis included andpnpm check:published-filesis green. Noskip-changesetlabel.Gates
Derived on the final head with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(36 commands) and run with each exit code captured before any pipe. At0e9a1f50a:pnpm --filter @objectstack/spec check:liveness,check:generated(all 15 artifacts current),check:empty-state,check:strictness-ledger,check:variant-docs,check:published-files,check:merge-driver,check:adr-0087-registration,check:pm-governed-merges,pnpm check:nul-bytes.check-test-completeness(exit 3, its own text says it grades a savedturbo run testlog and none was named),check:dual-build-cjs-loads(exit 3, "PREREQUISITE NOT MET — this gate reads built output"; its 93-case self-test passes),check-dev-prereqs(exit 1, "1 unmet precondition, not a list of problems" — 66 of 67 packages have nodist/). CI checks out fresh and builds, so all three are measured there.pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/liveness scripts/zod-graph.test.ts src/system/metadata-form-zod-reconciliation.test.ts— 13 files, 360 tests, all pass (the gate script is edited, so its own suite is not optional).pnpm --filter @objectstack/spec typecheck— green (tsc --noEmit+check:scripts-typecheck+check:test-typecheck).The gate is what judges this work: with the four files absent,
check:livenessreds with four UNCLASSIFIED types; with them present and the README/state-counts halves missing, it reds on the index and on the generated count artifact. Both were observed on the way in.🤖 Generated with Claude Code
https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
Generated by Claude Code