chore(spec): govern the four RestServerConfig sub-objects in the liveness ledger - #14638
Merged
os-sam merged 2 commits intoSep 2, 2026
Merged
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
Contributor
📓 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): |
os-sam
marked this pull request as ready for review
September 2, 2026 16:42
os-sam
enabled auto-merge
September 2, 2026 16:42
This was referenced Sep 2, 2026
os-sam
deleted the
claude/issue-14369-rest-server-config-liveness-ledger
branch
September 2, 2026 18:37
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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