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
4 changes: 2 additions & 2 deletions docs/qa/platform-checklist/areas/api-backend.json
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,7 @@
"source": [
"packages/spec/liveness/crud_endpoints.json (the ADR-0049 ledger this item answers: five live `operations.*` switches + `dataPrefix`, two dead keys)",
"packages/spec/src/api/rest-server.zod.ts#CrudEndpointsConfigSchema (the declared contract, its defaults and the two retiredKey tombstones)",
"packages/rest/src/rest-server.ts#registerCrudEndpoints (the six mounts and their five gates), (normalizeConfig — the parsed sub-config every consumer reads), (parseDeclaredSubConfig — the construction-time refusal), (registerDiscoveryEndpoints — discovery.routes.data built from dataPrefix), (getRoutes — the route table the mount clauses read)",
"packages/rest/src/rest-server.ts#registerCrudEndpoints (the six mounts and their five gates), (normalizeConfig — the parsed sub-config every consumer reads), (parseDeclaredSubConfig — the construction-time refusal), (getRoutes — the route table the mount clauses read) + packages/rest/src/discovery-routes.ts#registerDiscoveryEndpoints (discovery.routes.data built from dataPrefix)",
"#14691 (the ADR-0049 retirement of patterns/objectParamStyle) · #11984 (parse-and-consume instead of cast) · ADR-0122 (author state) · ADR-0076 D12 (advertise only what is mounted)",
"sibling clause: api-backend.api-methods-verb-gate (the per-OBJECT exposure gate this config-level switch must stay distinguishable from) · api-backend.route-ledger-live-parity (the routing-404 control technique)"
],
Expand Down Expand Up @@ -2383,7 +2383,7 @@
"source": [
"packages/spec/liveness/metadata_endpoints.json (the ADR-0049 ledger this item answers: prefix, enableCache, maskObjectFields and three endpoints.* live, cacheTtl and endpoints.schema dead)",
"packages/spec/src/api/rest-server.zod.ts#MetadataEndpointsConfigSchema (the declared contract — four endpoints.* switches whose describe() strings enumerate every mount they gate since #15542/#15854, the ADR-0106 D8 docblock and the two retiredKey tombstones)",
"packages/rest/src/rest-server.ts#registerMetadataEndpointsInner (metaPath, the four endpoint gates and registerPerItemRoute — the per-item switch spelled as a call so the later members of that face carry it), (resolveObjectMasker — the metaType/maskObjectFields fork), (normalizeConfig — isObjectSchemaMaskingEnabled and the OS_ALLOW_UNMASKED_OBJECT_METADATA escape hatch), (registerDiscoveryEndpoints — discovery.routes.metadata built from prefix), (getRoutes)",
"packages/rest/src/rest-server.ts#registerMetadataEndpointsInner (metaPath, the four endpoint gates and registerPerItemRoute — the per-item switch spelled as a call so the later members of that face carry it), (resolveObjectMasker — the metaType/maskObjectFields fork), (normalizeConfig — isObjectSchemaMaskingEnabled and the OS_ALLOW_UNMASKED_OBJECT_METADATA escape hatch), (getRoutes) + packages/rest/src/discovery-routes.ts#registerDiscoveryEndpoints (discovery.routes.metadata built from prefix)",
"ADR-0106 D8 (per-caller field masking of served object schemas) · #14691 (the two retirements) · #7526 (the /meta/types ordering fix the `types` switch takes with it) · ADR-0076 D12 · #15542 / #15854 (the switch-radius ruling that created `maintenance` and gave `item` its own writes) · #15543 (why the measured blast radius of that move is zero: no shipped boot path authors a RestServerConfig)",
"sibling clause: platform-core.metadata-registry-serving (it drives the served REGISTRY on the default config; this item covers the config that decides what is served and to whom) · platform-core.docs-audience-gate (the audience-gated types that are a cache carve-out here)"
],
Expand Down
2 changes: 1 addition & 1 deletion packages/qa/dogfood/test/authz-conformance.matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export const AUTHZ_CONFORMANCE: AuthzPrimitive[] = [
// #22430 — the API-description endpoints, under the ruling recorded on #22146
// (the API-description endpoints refuse an anonymous caller with 401).
{ id: 'anonymous-deny-api-description', summary: 'anonymous-deny on the API-description endpoints (the document and its viewer)', state: 'enforced',
enforcement: 'rest/rest-server.ts registerOpenApiEndpoints — BOTH handlers (the document and its viewer page, on every base the server mounts) open with enforceAuth (→ shouldDenyAnonymous) as their first act, ahead of the bundled-artifact load and the protocol resolution, so a refused request does no work and does not reveal whether a document is bundled; an anonymous caller gets the REST seam\'s flat 401 UNAUTHENTICATED, a signed-in caller is served as before, and a session held by the ADR-0069 auth-policy gate gets that gate\'s 403',
enforcement: 'rest/discovery-routes.ts registerOpenApiEndpoints — BOTH handlers (the document and its viewer page, on every base the server mounts) open with enforceAuth (→ shouldDenyAnonymous) as their first act, ahead of the bundled-artifact load and the protocol resolution, so a refused request does no work and does not reveal whether a document is bundled; an anonymous caller gets the REST seam\'s flat 401 UNAUTHENTICATED, a signed-in caller is served as before, and a session held by the ADR-0069 auth-policy gate gets that gate\'s 403',
proof: 'showcase-anonymous-deny-surfaces.dogfood.test.ts',
// The REST family at ledger granularity. The family is exactly these two
// routes and both handlers open with the floor, which is the property a
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 @@ -1628,7 +1628,8 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
// [#23050 slice 4] Length 4 → 5 (`sharing-routes.ts`), still 0 over it.
// [#23050 slice 5] Length 5 → 6 (`analytics-routes.ts`), still 0 over it.
// [#23050 slice 6] Length 6 → 7 (`security-routes.ts`), still 0 over it.
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
// [#23050 slice 7] Length 7 → 8 (`discovery-routes.ts`), still 0 over it.
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(8);
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
29 changes: 23 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 @@ -520,10 +520,11 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
'terminator spelling), PLUS `registerPerItemRoute(` call sites; counted over this file AND every ' +
'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` and `security-routes.ts`, the modules the bodies of `registerDataActionEndpoints`, ' +
'`registerBatchEndpoints`, `registerApprovalsEndpoints`, `registerSharingEndpoints`, ' +
'`registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, `registerSecurityExplainEndpoints` and ' +
'`registerSecurityEndpoints` moved to; ' +
'`analytics-routes.ts`, `security-routes.ts` and `discovery-routes.ts`, the modules the bodies of ' +
'`registerDataActionEndpoints`, `registerBatchEndpoints`, `registerApprovalsEndpoints`, ' +
'`registerSharingEndpoints`, `registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, ' +
'`registerSecurityExplainEndpoints`, `registerSecurityEndpoints`, `registerDiscoveryEndpoints` and ' +
'`registerOpenApiEndpoints` 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 @@ -717,24 +718,40 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
// slice's seam, the same two spellings TWICE, because the module carries
// two registrars (two host literals' forwarders, four; two host
// interfaces' members, four). No call site was added.
// [#23050 slice 7] 70 / 19 / 51 UNCHANGED, the same measurement again:
// `registerDiscoveryEndpoints`' and `registerOpenApiEndpoints`' bodies
// (four registration sites, two and two — the API root and `/discovery`,
// `/openapi.json` and `/docs` — all outside `registerMetadataEndpoints`, so
// all four in the blind spot) moved to `discovery-routes.ts`, which joins
// the list (length 7 -> 8) with its own control.
// `this.routeManager.register(` stays 63 over the eight files
// (23 here + 9 + 5 + 7 + 8 + 1 + 6 + 4), `private register*Endpoints(`
// stays 16 (both registrars are still declared here), and `enforceAuth`
// 92 -> 96 is RE-ANCHORED, not relaxed: the OpenAPI pair's two call sites
// moved with their routes and are counted in both readings; the four new
// occurrences are this slice's seam, the two spellings ONCE, because only
// the OpenAPI body reads `enforceAuth` (its host literal's forwarder, two;
// its host interface's member, two) — the discovery document is served to
// anyone, so its literal forwards no `enforceAuth`. No call site was added.
controls: {
'private register*Endpoints(': 16,
'this.routeManager.register(': 63,
'registrar list length': 7,
'registrar list length': 8,
'data-action-routes.ts: this.routeManager.register(': 9,
'batch-routes.ts: this.routeManager.register(': 5,
'approvals-routes.ts: this.routeManager.register(': 7,
'sharing-routes.ts: this.routeManager.register(': 8,
'analytics-routes.ts: this.routeManager.register(': 1,
'security-routes.ts: this.routeManager.register(': 6,
'discovery-routes.ts: this.routeManager.register(': 4,
// 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
// shape moved and force this provenance to be re-read.
'registerPerItemRoute(': 8,
'const registerPerItemRoute =': 1,
'forwarder slice: this.routeManager.register(': 1,
enforceAuth: 92,
enforceAuth: 96,
},
note:
'The single non-tripwire probe names ONE registrar of 16. The other 15 can never mint a key: ' +
Expand Down
Loading
Loading