Skip to content

Commit f115b1f

Browse files
fix(rest): REST refusals, notes and the OpenAPI text state each decision in words instead of a tracker number (stage 2) (#21188)
Part of #20752 Clause-②: no **Stage 2 of 5 of the `domain:cli` lane under the maintainer's A / A ruling (5902360492): the `packages/rest` strings.** The card stays open for stages 3-5, so this PR carries no closing keyword. Text only: no status, error `code`, field, route, export or control flow moves. ## What this does The REST layer's refusal envelopes, a boot warning, the served OpenAPI descriptions, a `/discovery` capability description and the route ledger's notes sent the reader to a tracker number for the reason behind them. In form D, as stage 1 (PR #21172) and the engine lane's stages applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words. All 34 ledgered occurrences in `packages/rest` (claim `5933139597`): `rest-route-ledger.ts` 29, `openapi-builtin-paths.ts` 2, `import-mapping.ts` 1, `rest-api-plugin.ts` 1, `rest-server.ts` 1 (the `:4830` string only). ### Rewritten in words | Where (head line) | Cited | The text now says | Decision read from | |---|---|---|---| | `import-mapping.ts:93` `UNSUPPORTED_TRANSFORM` message | 2611 | "...which the import path does not execute (there is no server-side sandbox), so the import is refused rather than run with that transform skipped" | landing commit fce8ff4 (javascript: no server-side sandbox, never silently skipped) | | `openapi-builtin-paths.ts:152` response description | 5588 | "This section is built from the routes this server actually mounts ... Per-route payload schemas are not derived here and are deliberately not invented." | ruling C, comment 5200114550 (rest produces the built-in section from its own route table) and ACCEPT 5201374820 (no invented schema or status) | | `openapi-builtin-paths.ts:157` request-body description | 5588 | "Its shape is route-specific; this document leaves it undescribed rather than invent one." | same | | `rest-route-ledger.ts:178` discovery note | 5682 (a PR) | "...through the double assertion: the live body parses against `DiscoverySchema`, and it carries no key the protocol does not declare" | PR 5682 body and its reverse-verification comment 5198848731 | | `rest-route-ledger.ts:221` `_migrate-stored` note | 4327 | "ADR-0087 stored-row canonicalization, the route form of `os migrate meta --stored`: it rewrites stored `sys_metadata` rows in place to their canonical form" | card body; commits 83cf2d3 and 8aacf94 | | `rest-route-ledger.ts:228` book-tree note | 12038 ("ruling 5A") | "...re-exported into `/api`, never declared there a second time" | ruling 5434804846, item 5A | | `rest-route-ledger.ts:249` `GET /meta/:type/:name` note | 5950 | "...the ADR-0010 protection envelope this schema now declares, every key optional because the cached branch never publishes it" | landing commit 361bd5b | | `rest-route-ledger.ts:251` `PUT /meta/:type/:name` note | 12702 | adds "so a tenant org admin authors their own org's overlays without platform-wide `manage_metadata`" | card body; ACCEPT 5439334711 | | `rest-route-ledger.ts:267` audit note | 11678 (twice) | "The schema predates this row: it joined the spec when `MetadataProtocol` gained its optional `auditMetaItem` member ... conformance: the audit-door capture suite" | card option B; os-dev-report 5405323732 and ACCEPT 5405332618 | | `rest-route-ledger.ts:290` legal-next-state note | 9180 | "Step 2 of the singular-segment ruling retired the plural ... twin" (the sentence already ends "the `/meta` type segment is singular, always") | ruling in the card body; re-weigh 5311434183 | | `rest-route-ledger.ts:290` same note, last clause | 10179 (404) | "...`meta-state-plural-tolerance.test.ts`, which pins both halves as behaviour so this note cannot quietly stop being true" | landing commit 53a48c9 (PR #10613) | | `rest-route-ledger.ts:293` published-snapshot note | 7526 | "...the fall-through into the compound-name route, before this path had a registration of its own, structurally could not do" | card body; ACCEPT 5251269251 | | `rest-route-ledger.ts:313` `GET /ui/view` note | 3611 | "the client was moved to the path form both surfaces accept, rather than this server registering the query dialect as a second spelling" | card option A | | `rest-route-ledger.ts:379` search note | 8140 | "...a near miss that would compile here and be false" | card thread (bind only a type verified against the route's actual emit) | ### Citation only (the sentence already stated the decision) - `rest-route-ledger.ts:213`, `:216`, `:225`, `:228`, `:267`, `:272`, `:275` (12038, the bracketed prefix): each note goes on to say the schema is a transcription of the producer's declared return, with its conformance suite. - `rest-route-ledger.ts:221` (12038 ruling 2C): "DELIBERATELY UNBOUND — ... a second declaration in spec would drift against the CLI rendering the same report." - `rest-route-ledger.ts:293` (12038 ruling 1C): "The named schema is DELIBERATELY OPAQUE (`z.unknown()`) ... never a union frozen against the type registry." - `rest-route-ledger.ts:251` (6603) and `:253` (7019): "Gated on `manage_metadata` ... a session alone is no longer enough" and the DELETE reasoning. - `rest-route-ledger.ts:253`, `:269`, `:272` (12702): each already names the shared verdict and the caller's own org partition. - `rest-route-ledger.ts:362`, `:379` (11924): "Filled with its conformance coverage", the ruled condition. - `rest-route-ledger.ts:462` (3610, 7563): "Moved off the bare POST /packages to this path: ..." and "Mounted UNCONDITIONALLY — ... answers an honest 404 on a deployment that composes none." - `rest-api-plugin.ts:530` (3963): "`api.requireAuth` was removed and is IGNORED — anonymous access to object data is always denied." - `rest-server.ts:4830` (1604): the `transactionalBatch` description keeps ADR-0034, a customer-resolvable reference the gate keeps. Every cited card was read (REST, open or closed) before its string was rewritten. One answers 404: 10179, read through its landing commit 53a48c9. `rest-route-ledger.ts:290`'s "(10179)" was the string the dead-citation sweep left for this card's form-D stage (commit 04b202e, its Acceptance notes). ## Ledger (`scripts/doc-authoring-prose-id.baseline.json`) Recomputed with `node scripts/check-doc-authoring.mjs --census-ledger` (exit 0, no growth refusal) into a scratch file, then copied into place. The diff deletes 30 lines and adds none: exactly the five `packages/rest` rows. Every other row is byte-identical. After merging `origin/main` (`454bbb6866`) the recomputed ledger is byte-identical to the committed one. | | before (`b9087d77e9`) | after | |---|---|---| | `packages/rest` | 34 occurrences, 20 pairs, 5 files | 0 | | whole ledger | 584 occurrences, 395 pairs, 152 files | 550 occurrences, 375 pairs, 147 files | `pnpm check:doc-authoring`: before, "487 pinned site(s) across 152 file(s) ... no growth, no burn-down unrecorded"; after, "463 pinned site(s) across 147 file(s) ... no growth, no burn-down unrecorded". No gate is added or loosened; `scripts/check-doc-authoring.mjs` is untouched. ## Changeset `.changeset/20752-rest-strings-state-the-decision.md`: `patch` for `@objectstack/rest`. Measured after the build: the four new non-ledger sentences are each in `dist/index.js` and `dist/index.cjs`, and each old spelling (`see framework` plus the number, `invented (` plus the number, `removed (` plus the number, the batch description's number) is in 0 files. The route ledger does not ship: `REST_ROUTE_LEDGER` and the new ledger sentences are in 0 files under `packages/rest/dist`. ## Text-only proof A TypeScript-AST skeleton of each changed `.ts` file, where every string literal and template text is one placeholder, consecutive literal operands of a `+` chain merge, and comments and JSDoc are never read. `b9087d77e9` against the fix commit, and again `454bbb6866` (the merged `origin/main`) against the head: 5 of 5 SAME, with token and literal-slot counts identical per file. Control: the same tool reports DIFF on `import-mapping.ts` across `8368f1c005`, a real code change. ## Pins No test, fixture or snapshot asserts any of the old strings with its number. Each old fragment was searched repo-wide; the only hits outside the five files are comments, the runtime ledger's twin notes (stage 3) and a checklist anchor. So nothing is re-pinned and there is no ablation to run. The one pin on a rewritten string, `rest-config-parse-not-cast.test.ts:407` (`toContain` of "`api.requireAuth` was removed"), asserts a substring the rewrite keeps, and runs green in the suite below. ## Tests All on the merged head, through `scripts/pm/os-verify-lock.sh`, every verdict `VERDICT command-exit 0`: - Build: `turbo run build --filter=@objectstack/rest...`, 25/25 tasks. - `@objectstack/rest`, both vitest projects (`local` and `repo`): 259 files passed (259), 4989 tests passed, 254 skipped. Before the merge: 258 files, 4946 passed, 254 skipped. - `@objectstack/rest` `typecheck`, including `check:test-typecheck: OK`. - The three `@objectstack/client` suites that import the ledger as source (`client-url-conformance`, `rest-route-ledger-coverage`, `route-ledger-response-schema`): 3 files, 9 tests passed. ## Gates - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (no paths) at `d2b6ede4e9`: 66 commands, run one at a time from the worktree, every exit code recorded before any pipe. 66 of 66 exit 0. `--ran`: "66 derived famil(ies) accounted for — 66 run, 0 NOT-MEASURED (a DERIVED zero — all 66 recorded an exit code and none of them is 3)". - `check:dual-build-cjs-loads` first answered `PREREQUISITE NOT MET` (exit 3: only the `rest` closure was built). After a full `turbo run build` of `./packages/*` and `./packages/*/*` (71/71 tasks), it and the other four dist-reading gates were re-run, all exit 0: 105 require entry points across 66 packages load; `check:dts-closure` 71 built packages, 167/167 declaration files present; `check:sourcemap-no-sources-content` 68 packages, 522 maps; `check:lean-entry-closure` and `check:published-files` green. - `check:doc-authoring`: "463 pinned site(s) across 147 file(s) ... no growth, no burn-down unrecorded". `check:issue-citations`: "no issue citations added against 454bbb6 (5 file(s) read)". `check:nul-bytes`: OK, 9832 files. - Outside the derived set: `check:meta-type-normalized` (a declared wide-population family whose scan root is `packages/rest/src`), exit 0, "OK (27 file(s), no raw `:type` param decisions)". The other declared wide-population families, the artifact roster, the path-scheduled CI jobs and the type-check lanes are CI's. NOT MEASURED: `check-issue-citations.mjs --census` and the shard-attestation and test-completeness steps, reason: their argv takes values that exist only inside a CI run. - `pnpm lint` (`eslint . --no-inline-config`, repo-wide, not narrowed) at `d2b6ede4e9`: exit 0, 119 s under the lock. ## Acceptance notes - `docs/qa/platform-checklist/areas/records-forms.json:4068`: an acceptance clause says the `UNSUPPORTED_TRANSFORM` message "names the missing server-side sandbox and framework" plus the number. The message still names the missing sandbox, and no longer the number. Editing a checklist clause is a semantic edit that bumps the item's revision and history, so it is outside this claim; noted for the checklist's next pass, not filed. - The runtime ledger twins of several rewritten notes (`packages/runtime/src/route-ledger.ts:497`, `:507`, `:509`) still carry their numbers. They are stage 3. --- _Generated by [Claude Code](https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0d42104 commit f115b1f

7 files changed

Lines changed: 42 additions & 56 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/rest': patch
3+
---
4+
5+
REST refusals, warnings and the served OpenAPI text no longer cite tracker numbers; each one states the decision behind it in words
6+
7+
Clause-②: no
8+
9+
A few strings `@objectstack/rest` sends to callers and operators pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
10+
11+
- `POST /data/:object/import` with a named mapping that declares a `javascript` transform: the `UNSUPPORTED_TRANSFORM` message now says the import path does not execute it (there is no server-side sandbox), so the import is refused rather than run with that transform skipped.
12+
- `GET /openapi.json`: the built-in section's response description says the section is built from the routes this server actually mounts and that payload schemas are deliberately not invented; the request-body description says the document leaves the route-specific shape undescribed rather than invent one.
13+
- The boot warning for a config that still sets the retired `api.requireAuth` drops its citation; it already says the key was removed and anonymous access to object data is always denied.
14+
- `/discovery`'s `capabilities.transactionalBatch.description` cites ADR-0034 alone.
15+
16+
Text only: no status, error code, field, route or control flow moves. A client that matches the old message text (for example the tracker-number suffix the `UNSUPPORTED_TRANSFORM` message used to end with) needs the new spelling.

‎packages/rest/src/import-mapping.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export async function resolveNamedMapping(
9090
if (entry?.transform === 'javascript') {
9191
return {
9292
ok: false, status: 400, code: 'UNSUPPORTED_TRANSFORM',
93-
error: `Mapping "${mappingName}" uses transform "javascript", which the import path does not execute (no server-side sandbox; see framework#2611)`,
93+
error: `Mapping "${mappingName}" uses transform "javascript", which the import path does not execute (there is no server-side sandbox), so the import is refused rather than run with that transform skipped`,
9494
};
9595
}
9696
}

‎packages/rest/src/openapi-builtin-paths.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ const PUBLIC_TAG = 'public';
149149
const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
150150

151151
const RESPONSE_NOTE =
152-
'Response envelope. This section describes the route surface — which method and path exist, ' +
153-
'and what each is for. Per-route payload schemas are not derived here and are deliberately not ' +
154-
'invented (#5588).';
152+
'Response envelope. This section is built from the routes this server actually mounts — which method ' +
153+
'and path exist, and what each is for. Per-route payload schemas are not derived here and are ' +
154+
'deliberately not invented.';
155155

156156
const REQUEST_BODY_NOTE =
157-
'JSON request body. Its shape is route-specific and is not described by this document (#5588).';
157+
'JSON request body. Its shape is route-specific; this document leaves it undescribed rather than invent one.';
158158

159159
/**
160160
* Is this wire path served by the document being built for `basePath`?

‎packages/rest/src/rest-api-plugin.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ export function createRestApiPlugin(config: RestApiPluginConfig = {}): Plugin {
527527
if ((config.api as any)?.requireAuth !== undefined
528528
|| (config.api as any)?.api?.requireAuth !== undefined) {
529529
ctx.logger.warn(
530-
'[security] `api.requireAuth` was removed (#3963) and is IGNORED — anonymous access to '
530+
'[security] `api.requireAuth` was removed and is IGNORED — anonymous access to '
531531
+ 'object data is always denied. Publish public surfaces by declaration instead: a public '
532532
+ 'form view, a share link, or `book.audience: \'public\'`.',
533533
);

‎packages/rest/src/rest-route-ledger.ts‎

Lines changed: 19 additions & 19 deletions
Large diffs are not rendered by default.

‎packages/rest/src/rest-server.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4827,7 +4827,7 @@ export class RestServer {
48274827
description:
48284828
'Atomic cross-object batch endpoint (POST {basePath}/batch): all-or-nothing '
48294829
+ 'create/update/delete across objects in one transaction, with intra-batch '
4830-
+ '{ $ref: <opIndex> } parent references (#1604 / ADR-0034).',
4830+
+ '{ $ref: <opIndex> } parent references (ADR-0034).',
48314831
};
48324832

48334833
// [#7541] Global search — the same two-layer AND, for the

‎scripts/doc-authoring-prose-id.baseline.json‎

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -437,36 +437,6 @@
437437
"packages/qa/downstream-contract/src/stack.ts": {
438438
"#2035": 1
439439
},
440-
"packages/rest/src/import-mapping.ts": {
441-
"#2611": 1
442-
},
443-
"packages/rest/src/openapi-builtin-paths.ts": {
444-
"#5588": 2
445-
},
446-
"packages/rest/src/rest-api-plugin.ts": {
447-
"#3963": 1
448-
},
449-
"packages/rest/src/rest-route-ledger.ts": {
450-
"#10179": 1,
451-
"#11678": 2,
452-
"#11924": 2,
453-
"#12038": 9,
454-
"#12702": 4,
455-
"#3610": 1,
456-
"#3611": 1,
457-
"#4327": 1,
458-
"#5682": 1,
459-
"#5950": 1,
460-
"#6603": 1,
461-
"#7019": 1,
462-
"#7526": 1,
463-
"#7563": 1,
464-
"#8140": 1,
465-
"#9180": 1
466-
},
467-
"packages/rest/src/rest-server.ts": {
468-
"#1604": 1
469-
},
470440
"packages/runtime/src/action-execution.ts": {
471441
"#11519": 1,
472442
"#5933": 1

0 commit comments

Comments
 (0)