You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filing gate: ③ a maintainer-directed task — the maintainer, after the P0 run, chose to file every extraction including this anchor (Claude Code session session_01MRdbfpy4sQT8bUjmMhxsN7, 2026-10-01, selected option verbatim: 「全部立卡(推荐)」). Reader: the lane owning docs/qa/platform-checklist/** (checklist edits: revise the item, bump revision, append history, keep pnpm check:platform-checklist green). Dedupe: no open sweep anchor for this run (searched "QA run platform checklist sweep wave anchor tracking release", open + closed; #9296 is the August regression epic).
1. Re-point (owns a red row) — api-backend.query-contract-matrix acceptance[5]
Disposition stale spec, independently verified. The clause (rev 2, 2026-08-18) expects 400 INVALID_FILTER for a scalar $nin comparand on the POST /query door in both spellings. Since #20116 the refusal happens in the request schema (FilterConditionSchema.superRefine(checkFilterConditionComparands); the AST arm via lowerFoldedTransportValues), and the POST door answers schema failures 400 VALIDATION_FAILED with a fields[] entry at query.where… naming operator, field and expected array — a posture pinned by rest-server-repeated-filter-param.test.ts and analytics-filter-refusal-envelope.test.ts. GET $filter still answers INVALID_FILTER. Revise: POST both spellings → 400 VALIDATION_FAILED + fields[]; GET → 400 INVALID_FILTER; both never 500, never widen. Also: step 5 / acceptance[2] — dotted fields: ['account.name'] is refused 400 INVALID_FIELD by design (prescribes expand); negative[0] — {"filter": …} is now a declared transport alias, so use an undeclared key (400 INVALID_FIELD). Residual for the maintainer, not a defect: GET and POST answer different codes for the same condition (#8001 family).
2. Checklist-accuracy findings
Personas, all member-persona items + recipe search:qa-contributor-bound-member step 1: stock audience posture is invite_only; POST /api/v1/auth/sign-up/email answers 403 SELF_REGISTRATION_CLOSED. Every "fresh sign-up" needs admin invite-member first (or admin create-user + change-password, which returns mustChangePassword:true).
access-security.write-path-guards acceptance[5]: "drops the field for the batch" → per row: only the locked row's field is dropped, reported in results[i].droppedFields.
access-security.rls-both-sides: the private "D11" handle collides with a public "D11" row in FOLLOW-UPS.md §7c; history/cross-references say "clause 5" (0-based) where runs say clause 6 (1-based).
access-security.anonymous-deny-surfaces: the pin does not cover /batch or /security/explain (both 401 rest-flat live) — extend it.
ai.mcp-stdio-fail-closed: no single showcase persona carries both RLS-hidden rows and an FLS-masked field on one object (use contributor for RLS, client_liaison for FLS); details.forbiddenFields is not on either wire; step 1 names no host command (os dev prints banner lines to stdout — use os start).
api-backend.packaged-action-disabled-dispatch knownGaps: the MCP door IS drivable live over HTTP (POST /api/v1/mcp, tools/call run_action).
platform-core.seed-integrity step 5 / platform-core.boot-health step 4: no SeedLoader lines at the default log level — name the banner Seeds: row or --log-level info[Seeder] Seed loading complete {…errored}. boot-health acceptance[2] "no ⚠" collides with the two stock unbound — disabled by deployment policy lines; name the misauthored classes instead.
cli.dev-boot-contract: steps 5/7/8 (touch sources, nothing-chosen DB, legacy dev.db) are unsafe in a shared tree — prescribe a scratch copy of the app; name the expected exit code (SIGINT → 0 under pnpm exec, --fresh SIGINT → 130); the "Dev admin … seeded" banner reprints on later boots and is not seeding evidence.
integration-system.datasource-credential-refusal-matrix:knownGaps "the wizard can plant a legacy alias row" is false (400) — planting needs a stopped-server sys_metadata write; acceptance[6] "PUT the response back" — the admin door is PATCH-only; acceptance[3] should name the admin door (the console reads hasSecret / redactedConfigKeys there); step 5 path GET /api/v1/meta/datasource/{name}; source omits the composed twin 18.datasource-credentialsref-mongo-composed-no-username-refused.ts, and the url-branch entry still says the composed branch is "Deliberately NOT refused" (stale since Composed-branch twin of #9041: external.credentialsRef bound + discrete mongo fields naming no username is the same silent no-op, unrefused #9147).
platform-core.console-login: acceptance[2].verify still says "after clearing cookies" (rev 3 step 5 expires with POST /auth/sign-out); acceptance[0] "nav + header" — /_console/home has a launcher, not a sidebar.
platform-core.nav-surfaces-render: the pin's playwright.config.ts hardcodes PORT = 3000 (no baseURL / executablePath override); its non-chart check can pass on the boot splash (22/49 first <main> texts were "Initializing application…"); SURFACES covers 31 of 49 served destinations — add the 18 hand-walked ones.
platform-core.builtin-apps-nav-render: counts moved (Setup 45, Account 8; acceptance[4] "7 vs 7" → 8 vs 8); member fixture cannot be a fresh sign-up — record the seeded plain persona (demo-personas.ts); Browse Marketplace needs egress to cloud.objectos.ai (knownGap).
records-forms.crud-roundtrip: acceptance[6]'s readonly-column half is unobservable on the stock seed (no approval_status; lead_score null everywhere); the own-row invoice must not point at the run's account (later delete → 409 DELETE_RESTRICTED); list quick-search text persists across reloads.
approvals.account-app-entry: acceptance[6] should say 中文(中国) (zh-CN) — no zh option exists; acceptance[1] tab labels listed only in zh; acceptance[5] fixture → use a persona-owned invoice set to sent (unreadable rows render no link); the seeded sign-off request was routed before the persona held finance — launch a new one.
studio-authoring.first-run-loop: object name is repairs_repair_ticket (package namespace), not repair_ticket; knownGaps "a new app scaffolds ZERO nav items" is stale (checkbox default on); step 9 — the UI hides New object / Add field on read-only packages, so the server probe is a forged request; the New object dialog now requires an OWD choice; acceptance[0]'s cited objectui pin targets testids that do not exist at the pin.
RUNNER "Environment facts": CRUD tail is now 15 verified … 1 needs-fixture, 8 skipped; verify --rls probes 10 of 10 positions (digits only).
3. Fixture gaps and environment (record, no edit needed unless chosen)
No Postgres/MySQL/Mongo runnable in the sandbox (a wire-level fake PG served the connect legs); sandbox egress denies cloud.objectos.ai and map tiles; the container's Node v22.22.0 is below the pinned objectui's jsdom engine floor; runner port ranges must avoid the egress proxy's 127.0.0.1:41333.
Filing gate: ③ a maintainer-directed task — the maintainer, after the P0 run, chose to file every extraction including this anchor (Claude Code session
session_01MRdbfpy4sQT8bUjmMhxsN7, 2026-10-01, selected option verbatim: 「全部立卡(推荐)」). Reader: the lane owningdocs/qa/platform-checklist/**(checklist edits: revise the item, bumprevision, appendhistory, keeppnpm check:platform-checklistgreen). Dedupe: no open sweep anchor for this run (searched "QA run platform checklist sweep wave anchor tracking release", open + closed; #9296 is the August regression epic).QA-source: #21056 · api-backend.query-contract-matrix · acceptance[5]
This card is the wave anchor for run #21056 (RUNNER "Extraction obligation": checklist-accuracy findings and fixture gaps close out here, not as separate cards). Product defects from the run are extracted separately: #21052, #21057, #21058, objectstack-ai/objectui#11326, objectstack-ai/objectui#11327.
1. Re-point (owns a red row) —
api-backend.query-contract-matrixacceptance[5]Disposition stale spec, independently verified. The clause (rev 2, 2026-08-18) expects
400 INVALID_FILTERfor a scalar$nincomparand on the POST/querydoor in both spellings. Since #20116 the refusal happens in the request schema (FilterConditionSchema.superRefine(checkFilterConditionComparands); the AST arm vialowerFoldedTransportValues), and the POST door answers schema failures400 VALIDATION_FAILEDwith afields[]entry atquery.where…naming operator, field and expected array — a posture pinned byrest-server-repeated-filter-param.test.tsandanalytics-filter-refusal-envelope.test.ts. GET$filterstill answersINVALID_FILTER. Revise: POST both spellings →400 VALIDATION_FAILED+fields[]; GET →400 INVALID_FILTER; both never 500, never widen. Also: step 5 / acceptance[2] — dottedfields: ['account.name']is refused400 INVALID_FIELDby design (prescribesexpand); negative[0] —{"filter": …}is now a declared transport alias, so use an undeclared key (400 INVALID_FIELD). Residual for the maintainer, not a defect: GET and POST answer different codes for the same condition (#8001 family).2. Checklist-accuracy findings
search:qa-contributor-bound-memberstep 1: stock audience posture isinvite_only;POST /api/v1/auth/sign-up/emailanswers403 SELF_REGISTRATION_CLOSED. Every "fresh sign-up" needs admininvite-memberfirst (or admincreate-user+change-password, which returnsmustChangePassword:true).automated.refstill says "25 showcase_* rows / 100 cells", clause/fixture say "31 rows"; actualaccess-matrix.json47 rows, the pin judges 41showcase_*rows = 164 cells (87 allow / 77 deny). acceptance[1] should list405 OBJECT_API_METHOD_NOT_ALLOWEDforsys_usercreate/delete (every caller). acceptance[5] (guest create-without-read) is unobservable on stock — add toknownGapsor re-point to the public-form lane.automated.ref's "pinned on both sides" for delegatesys_user_positionwrites does not hold on the dev boot (the pin runs with no organization — see [finding] The delegated-admin gate resolves an EMPTY subtree on a stockobjectstack devboot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057). Probe delegate edit/delete on a row the delegate created (others' rows hit the ownership floor).results[i].droppedFields.FOLLOW-UPS.md§7c; history/cross-references say "clause 5" (0-based) where runs say clause 6 (1-based)./batchor/security/explain(both 401 rest-flat live) — extend it.details.forbiddenFieldsis not on either wire; step 1 names no host command (os devprints banner lines to stdout — useos start).POST /api/v1/mcp,tools/call run_action).Seeds:row or--log-level info[Seeder] Seed loading complete {…errored}. boot-health acceptance[2] "no ⚠" collides with the two stockunbound — disabled by deployment policylines; name the misauthored classes instead.dev.db) are unsafe in a shared tree — prescribe a scratch copy of the app; name the expected exit code (SIGINT → 0 underpnpm exec,--freshSIGINT → 130); the "Dev admin … seeded" banner reprints on later boots and is not seeding evidence.knownGaps"the wizard can plant a legacy alias row" is false (400) — planting needs a stopped-serversys_metadatawrite; acceptance[6] "PUT the response back" — the admin door is PATCH-only; acceptance[3] should name the admin door (the console readshasSecret/redactedConfigKeysthere); step 5 pathGET /api/v1/meta/datasource/{name};sourceomits the composed twin18.datasource-credentialsref-mongo-composed-no-username-refused.ts, and the url-branch entry still says the composed branch is "Deliberately NOT refused" (stale since Composed-branch twin of #9041:external.credentialsRefbound + discrete mongo fields naming nousernameis the same silent no-op, unrefused #9147).POST /auth/sign-out); acceptance[0] "nav + header" —/_console/homehas a launcher, not a sidebar.playwright.config.tshardcodesPORT = 3000(no baseURL / executablePath override); its non-chart check can pass on the boot splash (22/49 first<main>texts were "Initializing application…"); SURFACES covers 31 of 49 served destinations — add the 18 hand-walked ones.demo-personas.ts); Browse Marketplace needs egress tocloud.objectos.ai(knownGap).approval_status;lead_scorenull everywhere); the own-row invoice must not point at the run's account (later delete →409 DELETE_RESTRICTED); list quick-search text persists across reloads.zh-CN) — nozhoption exists; acceptance[1] tab labels listed only in zh; acceptance[5] fixture → use a persona-owned invoice set tosent(unreadable rows render no link); the seeded sign-off request was routed before the persona heldfinance— launch a new one.repairs_repair_ticket(package namespace), notrepair_ticket;knownGaps"a new app scaffolds ZERO nav items" is stale (checkbox default on); step 9 — the UI hides New object / Add field on read-only packages, so the server probe is a forged request; the New object dialog now requires an OWD choice; acceptance[0]'s cited objectui pin targets testids that do not exist at the pin.15 verified … 1 needs-fixture, 8 skipped;verify --rlsprobes10 of 10positions (digits only).3. Fixture gaps and environment (record, no edit needed unless chosen)
No Postgres/MySQL/Mongo runnable in the sandbox (a wire-level fake PG served the connect legs); sandbox egress denies
cloud.objectos.aiand map tiles; the container's Node v22.22.0 is below the pinned objectui'sjsdomengine floor; runner port ranges must avoid the egress proxy's127.0.0.1:41333.Generated by Claude Code