Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/23050-s11-form-liveness-citations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@objectstack/spec': patch
---

The liveness ledger's three public-form rows cite the code that reads their keys where it now lives

Clause-②: no (only the rows' evidence paths move and every status stays `live`: `ViewSchema` accepts `form.sections`, `form.sharing` and `formViews` exactly as before, and no state count moves)

- `liveness/view.json`: the `form.sections` and `form.sharing` rows cited `packages/rest/src/rest-server.ts` for the two public form doors, `GET /forms/:slug` and `POST /forms/:slug/submit`. `@objectstack/rest` moved the body of the registrar that mounts them, `RestServer#registerFormEndpoints`, to `packages/rest/src/form-routes.ts` with no behaviour change, so their three path references follow it.
- `liveness/view.json`: the `formViews` row cited the doors' `findPublicFormView`, which moved with that body and reaches every form view through `anonymousFormIntakeCandidates`. The row now cites that rule where it is declared, `packages/spec/src/ui/anonymous-form-intake.ts#anonymousFormIntakeCandidates`, the code on the read path that names `formViews`.
- The quoted code, the verdicts and the notes are unchanged.
2 changes: 1 addition & 1 deletion docs/qa/platform-checklist/areas/access-security.json
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@
"source": [
"packages/metadata-core/src/anonymous-form-intake.ts#anonymousFormIntakeWithdrawnIn (the one judgement the doors make over the environment's list: a body of the same view name withdraws a candidate matched by slot or by slug; the package is not compared)",
"packages/metadata-core/src/anonymous-form-intake.ts#anonymousFormExplicitWithdrawals (explicit only: a sharing that keeps its publicLink and sets enabled or allowAnonymous to false; a schema-parsed artifact carries the default enabled false, which counts)",
"packages/rest/src/rest-server.ts#registerFormEndpoints (resolveFormBySlug: the environment's view list alone, judged against itself as the layer beneath each candidate; the Default Organization's legacy read was deleted with ADR-0131 C7, and the tenancy service is still read for the posture; a withdrawn form answers 404 FORM_NOT_FOUND on both doors)",
"packages/rest/src/form-routes.ts#registerFormEndpoints (resolveFormBySlug: the environment's view list alone, judged against itself as the layer beneath each candidate; the Default Organization's legacy read was deleted with ADR-0131 C7, and the tenancy service is still read for the posture; a withdrawn form answers 404 FORM_NOT_FOUND on both doors)",
"packages/metadata-protocol/src/protocol.ts#getMetaItems (the environment's view list the doors read: one item per package that ships a view name, ADR-0048; a package-less copy stands in for every package with no copy of its own, packages/metadata-protocol/src/protocol.ts#servedViewExpansion)",
"packages/metadata-protocol/src/protocol.ts#organizationScopedWriteRefusal (every organization-scoped write refused 403 NOT_OVERRIDABLE, ADR-0131 D6; PR #22515 deleted the intake-specific organization refusals and the row anchor revision 1 cited, and since PR #22447 the /meta doors hand the protocol no organization, so an organization-active administrator's save is environment-wide)",
"content/docs/ui/public-data-collection.mdx, section '4. Withdraw a public form' (the published rules and the known limit for packages and names; when this revision was written its 'Known limit: legacy copies' paragraph still described the Default Organization read that ADR-0131 C7 deleted from the doors)",
Expand Down
3 changes: 2 additions & 1 deletion packages/qa/dogfood/test/authz-conformance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,8 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
// [#23050 slice 8] Length 8 → 9 (`email-routes.ts`), still 0 over it.
// [#23050 slice 9] Length 9 → 10 (`search-routes.ts`), still 0 over it.
// [#23050 slice 10] Length 10 → 11 (`ui-routes.ts`), still 0 over it.
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(11);
// [#23050 slice 11] Length 11 → 12 (`form-routes.ts`), still 0 over it.
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(12);
expect(REST_SERVER_REGISTRAR_PATHS[0]).toBe(REST_SERVER);
const listed = REST_SERVER_REGISTRAR_PATHS.map((file) => readFileSync(join(REPO_ROOT, file), 'utf8'));
for (const probe of [MECHANICS, ROUTES]) {
Expand Down
28 changes: 22 additions & 6 deletions packages/qa/dogfood/test/authz-probe-blind-spot.census.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,11 +529,12 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
'module on the registrar list (`packages/rest/src/rest-server-registrar-files.ts`) — ' +
'`data-action-routes.ts`, `batch-routes.ts`, `approvals-routes.ts`, `sharing-routes.ts`, ' +
'`analytics-routes.ts`, `security-routes.ts`, `discovery-routes.ts`, `email-routes.ts`, ' +
'`search-routes.ts` and `ui-routes.ts`, the modules the bodies of `registerDataActionEndpoints`, ' +
'`registerBatchEndpoints`, `registerApprovalsEndpoints`, `registerSharingEndpoints`, ' +
'`registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, `registerSecurityExplainEndpoints`, ' +
'`registerSecurityEndpoints`, `registerDiscoveryEndpoints`, `registerOpenApiEndpoints`, ' +
'`registerEmailEndpoints`, `registerSearchEndpoints` and `registerUiEndpoints` moved to; ' +
'`search-routes.ts`, `ui-routes.ts` and `form-routes.ts`, the modules the bodies of ' +
'`registerDataActionEndpoints`, `registerBatchEndpoints`, `registerApprovalsEndpoints`, ' +
'`registerSharingEndpoints`, `registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, ' +
'`registerSecurityExplainEndpoints`, `registerSecurityEndpoints`, `registerDiscoveryEndpoints`, ' +
'`registerOpenApiEndpoints`, `registerEmailEndpoints`, `registerSearchEndpoints`, ' +
'`registerUiEndpoints` and `registerFormEndpoints` moved to; ' +
'reachable = those inside registerMetadataEndpoints',
// [#15542 / #15854] ⭐ THE POPULATION RULE LEARNED A SECOND SPELLING, and
// the numbers it produces did NOT move: 80 / 19 / 61, exactly as before.
Expand Down Expand Up @@ -778,10 +779,24 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
// new occurrences are this slice's seam, the same two spellings once (the
// host literal's forwarder, two; the host interface's member, two). No call
// site was added.
// [#23050 slice 11] 70 / 19 / 51 UNCHANGED, the same measurement again:
// `registerFormEndpoints`' body (two registration sites, `GET
// {base}/forms/:slug` and `POST {base}/forms/:slug/submit`, outside
// `registerMetadataEndpoints`, so in the blind spot) moved to
// `form-routes.ts`, which joins the list (length 11 -> 12) with its own
// control. `this.routeManager.register(` stays 63 over the twelve files
// (18 here + 9 + 5 + 7 + 8 + 1 + 6 + 4 + 1 + 1 + 1 + 2),
// `private register*Endpoints(` stays 16 (the registrar is still declared
// here), and `enforceAuth` stays 108: the two doors never call it (their
// authorization is the form's own declaration), so no call site moved, and
// this slice's host literal and interface name no such member. Measured at
// the move commit, before the list learned the module: population 68 and
// `this.routeManager.register(` 61 over eleven files, the two sites out of
// reach.
controls: {
'private register*Endpoints(': 16,
'this.routeManager.register(': 63,
'registrar list length': 11,
'registrar list length': 12,
'data-action-routes.ts: this.routeManager.register(': 9,
'batch-routes.ts: this.routeManager.register(': 5,
'approvals-routes.ts: this.routeManager.register(': 7,
Expand All @@ -792,6 +807,7 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
'email-routes.ts: this.routeManager.register(': 1,
'search-routes.ts: this.routeManager.register(': 1,
'ui-routes.ts: this.routeManager.register(': 1,
'form-routes.ts: this.routeManager.register(': 2,
// Both halves of the new rule carry their own control, so neither can go
// silently to zero: a helper deleted and its routes inlined back would
// still read population 80, and only these two controls would notice the
Expand Down
22 changes: 20 additions & 2 deletions packages/rest/src/execctx-consumer-census.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ const SOURCE = readFileSync(resolve(HERE, 'rest-server.ts'), 'utf8');
*
* [#23050 slice 10] …and `registerUiEndpoints`' body to `ui-routes.ts`, with
* its one.
*
* [#23050 slice 11] …and `registerFormEndpoints`' body to `form-routes.ts`,
* with none: the public form doors resolve no caller (their authorization is
* the form's own declaration).
*/
const SITE_FILES = REST_SERVER_REGISTRAR_FILES;
const SOURCES = new Map<string, string>(SITE_FILES.map((file) => [
Expand Down Expand Up @@ -165,9 +169,15 @@ const EXTRA_MOVED_REGISTRARS: Readonly<Partial<Record<(typeof SITE_FILES)[number
* `resolveExecCtx` member; its module's other registrar, the OpenAPI pair,
* reads it twice and carries the forwarder. A body that starts reading the
* seam gains a forwarder, and §2's exact count reds until this entry goes.
*
* [#23050 slice 11] `registerFormEndpoints`' body reads no `resolveExecCtx`
* either (the AST walk of the body finds no read): the public form doors run
* as the form grant and resolve no caller, so their host literal names no
* `resolveExecCtx` member.
*/
const MOVED_REGISTRARS_READING_NO_EXECCTX: Readonly<Partial<Record<(typeof SITE_FILES)[number], number>>> = {
'discovery-routes.ts': 1,
'form-routes.ts': 1,
};

/** A stack frame in any censused file, as `<file>:<line>:<column>`. */
Expand Down Expand Up @@ -695,13 +705,21 @@ describe('[#13160] §2 the consumer surface, counted from the tree', () => {
// mentions in). Twelve forwarders now: (11 - 1) + 3 - 1, the module
// carrying one registrar that reads the seam, so neither map gains an
// entry.
expect(SITE_FILES).toHaveLength(11);
//
// [#23050 slice 11] 62 sites / 125 mentions UNCHANGED — the same MOVE.
// `registerFormEndpoints`' body left for `form-routes.ts` with NO site:
// 22 + 9 + 5 + 7 + 8 + 1 + 5 + 2 + 1 + 1 + 1 + 0 = 62 sites. Its host
// literal and host interface name no `resolveExecCtx` member, so no
// mention moved and `rest-server.ts` stays at 60. Still twelve
// forwarders: (12 - 1) + 3 - 2, the module counted in
// `MOVED_REGISTRARS_READING_NO_EXECCTX`.
expect(SITE_FILES).toHaveLength(12);
expect(SITES.length).toBe(62);
expect([...SOURCES.values()].reduce((n, text) => n + text.split('resolveExecCtx').length - 1, 0)).toBe(125);
const extraMovedRegistrars = Object.values(EXTRA_MOVED_REGISTRARS).reduce((n, k) => n + (k ?? 0), 0);
expect(extraMovedRegistrars).toBe(3);
const registrarsReadingNoExecCtx = Object.values(MOVED_REGISTRARS_READING_NO_EXECCTX).reduce((n, k) => n + (k ?? 0), 0);
expect(registrarsReadingNoExecCtx).toBe(1);
expect(registrarsReadingNoExecCtx).toBe(2);
expect(FORWARDER_LINES, 'one host-literal resolveExecCtx forwarder per moved registrar whose body reads it: one was respelt or removed, or a module moved without joining SITE_FILES')
.toHaveLength(SITE_FILES.length - 1 + extraMovedRegistrars - registrarsReadingNoExecCtx);
});
Expand Down
Loading
Loading