Skip to content

Commit 66b6443

Browse files
committed
docs(qa): integration-system, identity-auth, cli and attachments checklist rows from the #23104 browser pass (#23169)
The connector picker's lock note is re-measured; webhook delivery moves onto an in-organization webhook with the bulk pair blocked on a maintainer question; email templates read from the registry; the federation fixture reports 7 columns and 'unreachable' is labelled; the 501 and mandatory-topic halves name why they cannot run on stock; the walled posture's boot prerequisites, the deployment-level meta read, the GET verify-email, the distinct IdP sub, the one scaffold template and persona B's attachment read. Claude-Session: https://claude.ai/code/session_012zwsLMxQBwHUYJgPyrpEvx Co-authored-by: Claude <noreply@anthropic.com>
1 parent 63d5572 commit 66b6443

4 files changed

Lines changed: 111 additions & 56 deletions

File tree

‎docs/qa/platform-checklist/areas/attachments-storage.json‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"qa-scratch-authz": {
99
"title": "Scratch authz parents (qa_vault / qa_shared / qa_nofiles) + two real member personas",
1010
"why": "Stock showcase has NO private files-enabled parent: its only `enable.files` object is showcase_project, which is public_read_write AND readable through the showcase `everyone` baseline. Without this recipe the entire authz core of this area — the 403 deny side of download-authz-both-sides, the invisible-parent case of read-inherits-parent-rls, and the read-but-not-edit split of attach-requires-parent-edit — is blocked(fixture) on every run. Run #7635 closed the gap at runtime and scored those items instead of blocking them; this block is that provisioning made permanent and replayable.",
11-
"provenance": "run #7635 (framework 92f26f75) → #7670",
11+
"provenance": "run #7635 (framework 92f26f75) → #7670 Step 6 gained persona B's sys_attachment read after QA run #23166 met the panel's up-front refusal (#23169).",
1212
"app": "showcase",
1313
"requires": [
1414
"an admin session that holds the `manage_metadata` capability — PUT /api/v1/meta/:type/:name is capability-gated per ADR-0066 D1 (#6603), so a bare authenticated session is NOT enough (packages/rest/src/rest-route-ledger.ts, the `PUT /api/v1/meta/:type/:name` row)",
@@ -53,7 +53,7 @@
5353
{
5454
"step": 6,
5555
"call": "bind each persona by inserting a sys_user_permission_set row in system context",
56-
"expect": "persona A = read-but-NOT-edit on the scratch objects (the attach-requires-parent-edit split); persona B = no grant beyond the everyone baseline (the parent-invisible persona). Prove the split INDEPENDENTLY before scoring any storage clause: read the parent as each persona and confirm the intended visibility, so a later 403 is attributable to the storage gate rather than to a mis-bound persona.",
56+
"expect": "persona A = read-but-NOT-edit on the scratch objects (the attach-requires-parent-edit split); persona B = no grant beyond the everyone baseline (the parent-invisible persona). Prove the split INDEPENDENTLY before scoring any storage clause: read the parent as each persona and confirm the intended visibility, so a later 403 is attributable to the storage gate rather than to a mis-bound persona. ⚠ Persona B needs READ on sys_attachment itself (and nothing on the scratch parents), unless its grants and the everyone baseline already carry it: without it the console's attachments panel refuses up front — 'You don't have access to these attachments.' — before any download is attempted, which is the listing gate answering, not the download gate the deny clauses score (QA run #23166). Check B's sys_attachment read as part of the independent split proof.",
5757
"source": "sys_user_permission_set insert in system context, mirroring showcase-permission-zoo.dogfood.test.ts — the binding shape access-security.json's permission-set items already replay. NOTE (ADR-0090 D5): every authenticated member ALSO holds the everyone baseline additively, so persona B's effective access is the UNION of its grants and that baseline — compute the union before calling a read 'invisible'."
5858
}
5959
],
@@ -173,7 +173,7 @@
173173
"title": "Gated downloads: 401 anonymous, 403 parent-invisible, signed URL for the entitled — per gating class (attachments-scope / field-owned / public_read opt-out / ungated)",
174174
"since": "v15.1",
175175
"status": "active",
176-
"revision": 3,
176+
"revision": 4,
177177
"priority": "P1",
178178
"surface": "mixed",
179179
"personas": ["admin (uploader/owner)", "signed-up member who cannot read the parent record", "anonymous"],
@@ -199,7 +199,7 @@
199199
"GET the same routes as the uploader/admin and follow the signed URL",
200200
"compare TTLs: the gated grant uses the short downloadTtl (default 300s), not the 3600s presignedTtl — read expiry material from the minted URL/descriptor where the adapter exposes it",
201201
"flip one file to acl='public_read' (system write) and GET /files/<fileId> anonymously — the opt-out must restore the stable anonymous capability URL",
202-
"in the browser, open the parent record's RecordAttachmentsPanel as the denied member and capture the surfaced copy"
202+
"in the browser, open the parent record's RecordAttachmentsPanel as the denied member — persona B, holding READ on sys_attachment (qa-scratch-authz step 6) — attempt the download, and capture the surfaced copy. Without that read the panel refuses up front ('You don't have access to these attachments.') before any download is attempted: that is the listing gate, not the download denial acceptance[4] scores"
203203
],
204204
"acceptance": [
205205
{
@@ -253,6 +253,12 @@
253253
"date": "2026-08-18",
254254
"change": "clause 3 (acl='public_read' reopens the anonymous capability URL) pinned — QA run #9401 scored this item partial with the OPEN side of the anonymous gate unpinned, which is the half a deny-only suite cannot see: a download-authz suite made only of refusals stays green on a surface that has started refusing everything. automated.ref now names the both-sides pin, records that the TTL branch is read out of the minted URL so the public_read early return is distinguishable from an authorized grant, and states that clause 4 (the panel's denial copy) stays manual with no pin. knownGaps marks the public_read seed gap CLOSED for the API half only, and carries the run's cross-tenant marker so it is not re-derived every wave.",
255255
"ref": "#9483"
256+
},
257+
{
258+
"revision": 4,
259+
"date": "2026-10-13",
260+
"change": "steps[6] names persona B's sys_attachment read, and the area recipe qa-scratch-authz step 6 now provisions it (persona recipe gap, #23166 A4; parked on #23121, carried by #23169). Without read on sys_attachment the attachments panel refuses before any download, so acceptance[4]'s friendly-denial screenshot would capture the listing refusal instead of the download one. QA run #23166 granted B that read and passed the clause. No clause changed",
261+
"ref": "#23169"
256262
}
257263
]
258264
},

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@
391391
"title": "The published first-run closes: create-objectstack scaffold → install → validate → build → boot → health, with the skills boundary holding",
392392
"since": "v15",
393393
"status": "active",
394-
"revision": 3,
394+
"revision": 4,
395395
"priority": "P1",
396396
"surface": "mixed",
397397
"personas": ["new user (published-registry consumer)"],
@@ -409,7 +409,7 @@
409409
"in a scratch dir: `npx -y create-objectstack@latest qa-first-run -t blank --skip-skills; echo $?` (or the repo's bin against the local registry, for the pre-release variant in fixtures.requires) — the scaffolder runs the install ITSELF (pnpm when its probe finds pnpm, npm otherwise), so its exit code and its install output are the install step's evidence. ⛔ Do not follow it with a second `npm install`: on a pnpm-installed scaffold that fails (17.6.0 and 17.7 alike) and the failure is the extra step's, not the product's",
410410
"cd qa-first-run && npm run validate; echo $? — then npm run build; echo $?",
411411
"boot from the artifact exactly as the workflow does: `npx os start --artifact ./dist/objectstack.json --port 8080 > server.log 2>&1 &`, poll /api/v1/health up to 60s, then `curl -fsS http://localhost:8080/api/v1/ready`",
412-
"repeat scaffold + validate + build across the template matrix (variants) — remote templates always ship build; run validate where the script exists",
412+
"repeat scaffold + validate + build across the template matrix (variants — `blank` only since revision 2: create-objectstack's catalog, packages/create-objectstack/src/template-registry.ts, holds the one bundled template); run validate where the script exists",
413413
"skills boundary probe: in a fresh scaffold run `npx -y skills add <objectstack checkout>/skills --all --copy` and compare the installed set to the curated skills/ catalog; then list repo-root discovery and assert no internal skill (dogfood-verification) surfaces",
414414
"capture server.log for any boot error"
415415
],
@@ -423,7 +423,7 @@
423423
{
424424
"clause": "every published template validates and builds — per-variant, no template inferred from a sibling",
425425
"oracle": "build",
426-
"verify": "validate (where present) and build exit 0 for each of the six templates",
426+
"verify": "validate (where present) and build exit 0 for each template in variants — one, `blank`: the five remote content templates were retired from the catalog (revision 2), and the published scaffolder offers only blank",
427427
"evidence": "per-template exit codes"
428428
},
429429
{
@@ -461,7 +461,8 @@
461461
"history": [
462462
{ "revision": 1, "date": "2026-08-07", "change": "new item: the published first-run experience mirrored step-for-step from scaffold-e2e.yml, template matrix as variants, RC-window protocol refusal recorded as gate-working instead of failure", "ref": "claude/platform-test-checklist-ocwugl" },
463463
{ "revision": 2, "date": "2026-08-14", "change": "variants narrowed to [blank]: the five remote content templates were delisted from the marketplace and retired from the create-objectstack catalog, and the scaffold-e2e registry-canary matrix this item mirrors was trimmed with them", "ref": "claude/issue-8677-retire-remote-template-catalog" },
464-
{ "revision": 3, "date": "2026-10-05", "change": "three corrections from run #21845. (1) The separate `npm install` step is dropped: the scaffolder already installs (pnpm when found, npm otherwise), and a trailing npm install fails on the pnpm layout on 17.6.0 and 17.7 alike, so the step measured itself rather than the product. The scaffolder's own exit code is now the install evidence, which is also what the published canary job in scaffold-e2e.yml does. Of the card's three options this one was picked as the least ambiguous: it does not depend on which package manager the host has, as `pnpm install` would, and it does not change the published scaffold command, as `--skip-install` would. (2) fixtures.requires gains a pre-release variant: pack the workspace to a localhost registry with no upstream for @objectstack/* and create-objectstack, run the repo's bin against it, and prove the candidate via lockfile integrity. The published path measures only what is released. (3) The skills-boundary clause compares unique skill names, not a raw count (card #21851 entries 8 and 9)", "ref": "#21845" }
464+
{ "revision": 3, "date": "2026-10-05", "change": "three corrections from run #21845. (1) The separate `npm install` step is dropped: the scaffolder already installs (pnpm when found, npm otherwise), and a trailing npm install fails on the pnpm layout on 17.6.0 and 17.7 alike, so the step measured itself rather than the product. The scaffolder's own exit code is now the install evidence, which is also what the published canary job in scaffold-e2e.yml does. Of the card's three options this one was picked as the least ambiguous: it does not depend on which package manager the host has, as `pnpm install` would, and it does not change the published scaffold command, as `--skip-install` would. (2) fixtures.requires gains a pre-release variant: pack the workspace to a localhost registry with no upstream for @objectstack/* and create-objectstack, run the repo's bin against it, and prove the candidate via lockfile integrity. The published path measures only what is released. (3) The skills-boundary clause compares unique skill names, not a raw count (card #21851 entries 8 and 9)", "ref": "#21845" },
465+
{ "revision": 4, "date": "2026-10-13", "change": "acceptance[1].verify and steps[3] stop naming six templates (stale wording, #23166 C2; parked on #23121, carried by #23169). The variants have been [blank] since revision 2, when the five remote content templates were retired, and create-objectstack's template registry holds blank alone. QA run #23166 scored the published 17.7.0 path's one template. No clause's assertion changed", "ref": "#23169" }
465466
]
466467
},
467468
{

0 commit comments

Comments
 (0)