Skip to content

Commit ff29410

Browse files
docs(qa): re-point 17 platform-checklist clauses the 17.7 pre-release runs proved stale or mis-asserted (#21741)
Fixes #21735 Clause-②: no ## What this changes Re-points 17 clauses on 16 items in `docs/qa/platform-checklist/areas/*.json`. The 17.7 pre-release runs named on the card proved each one stale or mis-asserted. Every item keeps its id, area and selectors, gets exactly one `revision` bump (both rows of `integration-system.external-schema-introspection` ride one bump), and gets one `history` entry that cites the source commit and card. No product code changes. No run record. `docs/qa/**` publishes nothing, so there is no changeset. Each row was re-derived from source at the claim ref `316be321ef`, not copied from the card. Line numbers below are at that commit. The checklist itself carries symbol citations only, because its validator refuses `file:line`. | # | item | clause | old → new (short) | source re-read @316be321ef | matches card? | |---|---|---|---|---|---| | 1 | access-security.share-link-capability-tokens | A5 record-gone leg, step 7 | 410 RECORD_GONE → 404 INVALID_OR_EXPIRED, byte-identical to an unknown token | share-link-service.ts:923 (`if (!record) return null`), share-links.ts:128 + :228 (`invalidOrExpired()` fall-through) | Y | | 2 | ai.agent-tool-skill-metadata-roundtrip | A4, step 7 | draft PUT on the package-shipped skill succeeds → draft on a runtime-created name (200, `?state=draft`); package-shipped is 403 NOT_OVERRIDABLE | metadata-plugin.zod.ts:1200-1210 (tool/skill `allowOrgOverride: false`), sys-metadata-repository.ts:1694 | Y | | 3 | api-backend.batch-transactional-discovery | A5, step 6 | default mixed batch "neither blocks" → names `options.continueOnError: true`, and asserts the default stop + NOT_ATTEMPTED tail as a second leg | batch.zod.ts:81-85, :209-214 | Y (took both legs the card offers) | | 4 | api-backend.server-timing-admin-gated | A1-A3, steps 1 and 4 | env flag as a second admin gate → env off: `X-OS-Debug-Timing` is admin-only; `OS_SERVER_TIMING=true` sends spans to everyone; `X-OS-Debug-Timing-Detail` admin-only | hono-plugin.ts:83-104, :311-353 | Y | | 5 | identity-auth.two-factor-enrollment-reveal | A6, step 8, browser-lane knownGap | toast-only, no QR → `sys_user.enable_two_factor` declares resultDialog (qrcode + code-list); knownGap reworded in the same revision | sys-user.object.ts:526-549 | Y | | 6 | identity-auth.two-factor-backup-codes | A6, step 9, title, knownGap | regenerate lockout path → `generate_backup_codes` declares a one-shot resultDialog | sys-user.object.ts:570-599 | Y | | 7 | integration-system.external-schema-introspection | A1 | columnCount 5 → 7 (initObjects adds created_at / updated_at) | external-fixture.ts:36-45, sql-driver.ts:12506-12508 | Y | | 8 | integration-system.external-schema-introspection | A3, step 6 | `fields.FIELD.primaryKey` + type-only import → `// Remote primary key:` comment, `ObjectSchema` value import | external-datasource-service.ts:283, :956 | Y | | 9 | platform-core.activation-ledger-registration-home | A5, step 6 | "41 names" → count dropped, the one-owner membership asserted (46 at this ref, noted as context) | platform-object-names.ts:47 (46 names; `sys_metadata_activation` occurs once) | Y (chose drop; see below) | | 10 | platform-core.marketplace-install-local-lifecycle | A7 + its step | restart needed to unload → hot withdrawal from the running kernel, no restart | marketplace-install-local-plugin.ts:1302, :1370 | Y | | 11 | records-forms.field-unique-enforcement | A1, step 1, fixtures, knownGap | memory driver (stock default) → stock SQLite; 409 UNIQUE_VIOLATION, object named, "No record was written."; `object.field` stays a memory-pin assertion; SQL knownGap inverted | duplicate-record-error.ts:129-137; serve.ts:3202 (memory refused) | Y | | 12 | cli.migrate-plan-apply-json | A5, step 4, source, variants | in_sync → in_sync_partial on the showcase (federated objects unexamined); "nine subcommands" → 13 | apply.ts:235, plan.ts:301-311; 13 Command files in commands/migrate/ | Y (13 measured) | | 13 | cli.migrate-meta-codemod | A4, step 8 | `--from` target prints "Nothing to migrate" → empty range prints "⚠ No migration step exists for protocol N → N …"; canonical-source replay; default `--to` 18 | meta.ts:91, :199, :411; chain.ts:100 | Y, with a nuance (below) | | 14 | cli.migrate-duplicates-inventory | A3 + its step | whole-file md5 → rows + `_objectstack_sequences` + `sqlite_master` byte-identical | duplicates.ts:61-66 | Y | | 15 | cli.datasource-introspect-codegen | A6 + its step | unknown-name probe on all three → list-tables / introspect only; validate is a vacuous ok by design | external-datasource-routes.ts:517, external-datasource-service.ts:854-858 | Y | | 16 | cli.plugin-manifest-build-contract | A2, probe (d) | `id: ""` reaches the post-parse guard → located Zod error (reverse-domain rule); guard unreachable | manifest.zod.ts:364, build.ts:121-122 | Y | | 17 | api-backend.enforce-or-remove-authoring-gates | A1, step 2 | retired filter operator rejected at parse/build → green at parse/build, refused at runtime with 400 INVALID_FILTER + the prescription, listed by `os migrate meta` | filter.zod.ts:3256, semantic/17.filter-regex-options-retired.ts:30, sql-driver.ts:17392 | Y, with a nuance (below) | ## Divergences and choices worth a reviewer's eye - **Row 13 (`cli.migrate-meta-codemod`).** The card says to replay a canonical source. Measured: over the real range `--from 17` (default `--to 18`), a canonical source shows no "Applied N mechanical change(s)" block, but it still lists the step-18 semantic advisories. `chain.ts` lists every hop's semantic entries unconditionally. So "Nothing to migrate — …" does **not** print there either. The clause asserts zero mechanical edits plus exit 0, not the success line. - **Row 17 (`api-backend.enforce-or-remove-authoring-gates`).** The full prescription reaches the wire only on a caller-authored `where`. A predicate whose provenance cannot be vouched gets the withheld "RETIRED" sentence, with the full diagnostic in the server log (sql-driver.ts `withheldFilterError`). The verify text says which shape to expect. - **Row 9.** RUNNER.md's convention for counts that move is that the discriminator is the fact, never its digits. A literal is pinned only where the validator enforces it, as `enumSource` does. Nothing enforces this array's length, so the count is dropped from the assertion and kept as context. - **Row 12.** The variants list gains the four subcommands it lacked: account-issuer, audit-metadata-bodies, multi-value-columns and unmapped-columns. - `coverage.json` is untouched. No item's capability mapping moved. ## Verification (at `d52c1fe937`) - `pnpm check:platform-checklist` → exit 0: `OK — 15 areas, 270 items …; line citations: 0 survive …; symbol anchors: 652/662 resolved`. On the base `316be321ef` the same check reads 650/660. The two new anchors (`hono-plugin.ts#serverTiming`, `duplicate-record-error.ts#buildDuplicateMessage`) resolve, and the unresolved count stays at the named residual of 10. - `node scripts/pm/dispatch-gates.mjs --commands`: 13 families derived. All 13 ran with exit 0. `--ran` reconciliation: `13 derived, 13 run, 0 NOT-MEASURED, 0 UNRUN`. --- _Generated by [Claude Code](https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent cf60dbc commit ff29410

8 files changed

Lines changed: 206 additions & 104 deletions

File tree

‎docs/qa/platform-checklist/areas/access-security.json‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@
14991499
"title": "Share-link capability tokens: anon resolve renders the record minus redactFields, password/audience gates hold, revoke/expire refuse without leaking",
15001500
"since": "v16",
15011501
"status": "active",
1502-
"revision": 3,
1502+
"revision": 4,
15031503
"priority": "P2",
15041504
"surface": "api",
15051505
"personas": [
@@ -1526,7 +1526,7 @@
15261526
"mint a password-gated link; anon resolve WITHOUT ?password / x-share-password header → 401; with a WRONG password → 401; with the correct password → 200",
15271527
"mint audience:'signed_in'; anon resolve → 401 SIGN_IN_REQUIRED; mint audience:'email' and resolve with an email OFF the allowlist → refused",
15281528
"DELETE /api/v1/share-links/<idOrToken> (revoke); anon resolve → 410 EXPIRED_OR_REVOKED; mint a short-expiry link and, after it expires, resolve → 410 — the record must never appear",
1529-
"delete the shared record r, then anon resolve the still-live token → 410 RECORD_GONE (fail-closed, #5190)",
1529+
"delete the shared record r, then anon resolve the still-live (un-passworded, link_only) token → 404 INVALID_OR_EXPIRED, byte-identical to the answer for an unknown token (fail-closed, #5190: \"that record is gone\" is itself information) — capture it beside an unknown-token resolve for the byte comparison",
15301530
"GET /api/v1/share-links?object=F&recordId=r as the minter vs a SECOND member — the list returns only the caller's own links"
15311531
],
15321532
"acceptance": [
@@ -1555,10 +1555,10 @@
15551555
"evidence": "the two traces"
15561556
},
15571557
{
1558-
"clause": "revoke / expiry / record-gone name the refusal, NEVER the record: after DELETE, past expiresAt, or record deletion, resolve answers 410 (EXPIRED_OR_REVOKED / RECORD_GONE) — a dead token must never leak the row (#5190 fail-closed)",
1558+
"clause": "revoke / expiry / record-gone refuse, NEVER serving the record: after DELETE or past expiresAt, resolve answers 410 EXPIRED_OR_REVOKED; after record deletion the still-live token answers 404 INVALID_OR_EXPIRED, byte-identical to an unknown token (no distinct record-gone code — that would itself be an existence oracle) — a dead token must never leak the row (#5190 fail-closed)",
15591559
"oracle": "api",
1560-
"verify": "post-revoke, post-expiry, and post-record-delete resolves each answer 410 with no record in the body",
1561-
"evidence": "the three traces"
1560+
"verify": "post-revoke and post-expiry resolves answer 410 EXPIRED_OR_REVOKED; the post-record-delete resolve answers 404 INVALID_OR_EXPIRED whose status + body are byte-identical to an unknown-token resolve; no record in any body (resolveToken returns null at share-link-service.ts loadRecordForServing; the probe's live-row arm falls through to invalidOrExpired(), share-links.ts)",
1561+
"evidence": "the three traces plus the unknown-token control resolve"
15621562
},
15631563
{
15641564
"clause": "the list is caller-scoped: GET /share-links returns only links created_by the caller; a second member cannot enumerate the minter's tokens even with a guessed recordId",
@@ -1610,6 +1610,12 @@
16101610
"date": "2026-08-30",
16111611
"change": "cross-referenced the new UI half (access-security.share-link-landing-page — the /s/:token console page): API semantics stay scored on this item, rendering on that one, so a leak found through the page's network trace is recorded here once and cross-referenced there, never double-counted",
16121612
"ref": "#sweep-2026-08-30"
1613+
},
1614+
{
1615+
"revision": 4,
1616+
"date": "2026-10-04",
1617+
"change": "A5 record-gone leg and step 7 re-pointed to the measured answer: a deleted record's still-live link resolves 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, never 410 RECORD_GONE (resolveToken's #5190 fail-closed record probe — share-link-service.ts loadRecordForServing — returns null, and the route's row probe in share-links.ts falls through to its one generic refusal, invalidOrExpired). Revoke/expiry legs unchanged (410 EXPIRED_OR_REVOKED). Stale clause found by the 17.7 pre-release runs",
1618+
"ref": "#21735"
16131619
}
16141620
]
16151621
},

‎docs/qa/platform-checklist/areas/ai.json‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"title": "agent / tool / skill metadata kinds author, persist and list over the meta surface — retired keys reject with prescriptions, the closed agent kind has no runtime write door",
1010
"since": "v15",
1111
"status": "active",
12-
"revision": 3,
12+
"revision": 4,
1313
"priority": "P1",
1414
"surface": "api",
1515
"personas": ["admin"],
@@ -42,7 +42,7 @@
4242
"boot; sign in as admin; GET /api/v1/meta (meta.getTypes) and GET /api/v1/meta/types — capture which kinds are registered",
4343
"GET /api/v1/meta/agent, /api/v1/meta/tool, /api/v1/meta/skill (route ledger: meta.getItems) and locate the three authored probes",
4444
"GET /api/v1/meta/skill/qa_probe_skill (meta.getItem) and field-diff against the authored source, noting applied defaults (surface:'ask', active:true)",
45-
"PUT /api/v1/meta/skill/qa_probe_skill?mode=draft with an edited copy (skill/tool are allowRuntimeCreate:true); then attempt the same runtime save for the agent kind and capture the outcome (agent is allowRuntimeCreate:false + allowOrgOverride:false — ADR-0063 §2, metadata-plugin.zod.ts)",
45+
"PUT /api/v1/meta/skill/qa_runtime_skill?mode=draft (and /meta/tool/qa_runtime_tool?mode=draft) with a NAME NO PACKAGE SHIPS — a runtime-created item (skill/tool are allowRuntimeCreate:true) — and re-read it with ?state=draft; then PUT /api/v1/meta/skill/qa_probe_skill?mode=draft against the PACKAGE-SHIPPED probe and capture the 403 NOT_OVERRIDABLE (skill/tool are allowOrgOverride:false since ee58392e1 — a package-shipped tool/skill has no per-org overlay); then attempt the same runtime save for the agent kind and capture the outcome (agent is allowRuntimeCreate:false + allowOrgOverride:false — ADR-0063 §2, metadata-plugin.zod.ts)",
4646
"repeat one meta list unauthenticated; capture status",
4747
"POST /api/v1/ai/tools/qa_probe_tool/execute (any payload) on the open-framework boot and capture the 501 — evidence for the read-only-projection clause, NOT an expected execution"
4848
],
@@ -66,10 +66,10 @@
6666
"evidence": "list/get responses + diff"
6767
},
6868
{
69-
"clause": "the runtime write door matches the declared registry posture — BOTH sides: PUT ?mode=draft succeeds for skill (and tool), while the agent kind has NO governed runtime write path (allowRuntimeCreate:false; 'for agents, the code is the record', metadata-plugin.zod.ts — migrateStoredMetadata reports agent rows 'skipped' by design)",
69+
"clause": "the runtime write door matches the declared registry posture — ALL sides: PUT ?mode=draft succeeds for a RUNTIME-CREATED skill (and tool) name — one no package ships (allowRuntimeCreate:true); the same PUT against a PACKAGE-SHIPPED skill/tool is refused 403 NOT_OVERRIDABLE (allowOrgOverride:false, ee58392e1 — ADR-0005 ai row); and the agent kind has NO governed runtime write path (allowRuntimeCreate:false; 'for agents, the code is the record', metadata-plugin.zod.ts — migrateStoredMetadata reports agent rows 'skipped' by design)",
7070
"oracle": "api",
71-
"verify": "skill draft PUT returns 200 and the draft is readable via GET /api/v1/meta/skill/qa_probe_skill?state=draft — ⚠️ the READ parameter is ?state=draft, not ?mode=draft: rest-server.ts keys the draft projection on req.query.state, while ?mode=draft is the WRITE-side parameter, so re-reading with ?mode=draft serves the active item (or 404s when none is active) and reads like the draft never landed. The agent runtime save is refused/unsupported (capture the actual status), and that refusal is recorded as CORRECT, not filed as a bug",
72-
"evidence": "the two PUT responses"
71+
"verify": "the runtime-created skill draft PUT (qa_runtime_skill) returns 200 and the draft is readable via GET /api/v1/meta/skill/qa_runtime_skill?state=draft — ⚠️ the READ parameter is ?state=draft, not ?mode=draft: rest-server.ts keys the draft projection on req.query.state, while ?mode=draft is the WRITE-side parameter, so re-reading with ?mode=draft serves the active item (or 404s when none is active) and reads like the draft never landed. The draft PUT against the package-shipped qa_probe_skill answers 403 code NOT_OVERRIDABLE (sys-metadata-repository.ts assertAllowed, override-artifact intent) — CORRECT, not a bug: a 200 there would be a per-org overlay the registry row forbids. The agent runtime save is refused/unsupported (capture the actual status), and that refusal is recorded as CORRECT, not filed as a bug",
72+
"evidence": "the three PUT responses (runtime-created skill 200 + its ?state=draft read, package-shipped skill 403, agent refusal)"
7373
},
7474
{
7575
"clause": "anonymous-deny holds on the meta surface for AI kinds",
@@ -101,7 +101,13 @@
101101
"history": [
102102
{ "revision": 1, "date": "2026-08-07", "change": "initial — closes the AI hole in capability coverage (no area covered agent/tool/skill kinds)", "ref": "claude/platform-test-checklist-ocwugl" },
103103
{ "revision": 2, "date": "2026-08-07", "change": "expanded to deep-test contract: concrete steps, multi-clause acceptance, negatives, variants", "ref": "claude/platform-test-checklist-ocwugl" },
104-
{ "revision": 3, "date": "2026-08-18", "change": "named the draft READ parameter in clause 4. The clause said the draft is readable after PUT ?mode=draft without saying how; ?mode=draft is the write-side parameter and the read projection keys on req.query.state === 'draft' (rest-server.ts), so a runner re-reading with ?mode=draft gets the active item or a 404 and concludes the draft write silently failed (#9417)", "ref": "#9386" }
104+
{ "revision": 3, "date": "2026-08-18", "change": "named the draft READ parameter in clause 4. The clause said the draft is readable after PUT ?mode=draft without saying how; ?mode=draft is the write-side parameter and the read projection keys on req.query.state === 'draft' (rest-server.ts), so a runner re-reading with ?mode=draft gets the active item or a 404 and concludes the draft write silently failed (#9417)", "ref": "#9386" },
105+
{
106+
"revision": 4,
107+
"date": "2026-10-04",
108+
"change": "A4 / step 7 re-pointed: the draft PUT targets a RUNTIME-CREATED skill/tool name (200, readable via ?state=draft); the same PUT against the package-shipped probe is 403 NOT_OVERRIDABLE, recorded as correct — tool/skill allowOrgOverride was rolled back to false (metadata-plugin.zod.ts tool/skill registry rows, sys-metadata-repository.ts assertAllowed). Assertion defect: the clause expected an overlay of a package-shipped skill to succeed. Source ee58392e1 (#6608)",
109+
"ref": "#21735"
110+
}
105111
]
106112
},
107113
{

0 commit comments

Comments
 (0)