Repository navigation
Description
domain:devx#1 · sunhaolin · session_017xRBcUWM7N73xRVd64cyAE
Part of #27377 (wave 3, W3-C1R — P0 re-run requested by triage 6553144940)
This is the re-run of the standing smoke (priority:P0) for the 18.3.0 release candidate, at the main head at dispatch. Wave 3's P0 evidence at c4c515ad (#27481) was stale.
Result: all 23 runnable items have a verdict — 20 PASS, 2 PARTIAL, 1 FAIL, 0 BLOCKED, 0 NOT-RUN.
Against #27481 (20 PASS / 3 PARTIAL / 0 FAIL), two verdicts moved:
approvals.account-app-entrywent PASS → FAIL. A non-admin approver's request page now shows the access-denied screen. It is a regression from feat(rest,console): one request opens a record page #27713, extracted as a product defect.cli.organization-ownership-ceremonywent PARTIAL → PASS. Its reset-token fixture gap is closed by the rev-7 recipe.
Other findings:
- The off-clause probes produced four low-severity product cards.
- Two security findings were reported privately to the PM; their detail is withheld here. As at QA run · priority:P0 (23/23) · c4c515ad · 2026-10-29 · 20 PASS / 3 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27481, off-clause rows score nothing (RUNNER rule 8), so these move no item verdict.
Environment fingerprint
- Framework:
eeec88d141cb2d303cb1b55b20b897c52ad86751, a detached checkout includingui/.git statuswas clean before and after the run. - Build (cold tree, in this checkout):
pnpm install --frozen-lockfile;pnpm build --concurrency=2, exit 0, 04:51Z–05:00Z;pnpm console:build --concurrency=2, exit 0;node scripts/check-dev-prereqs.mjsgreen (106 artifacts).
- Stale console bundle, ruled out:
- the dispatcher boot served
/_console/entryassets/index-RFCp05oY.js, the same file aspackages/console/dist/assets; - each browser runner re-checked it on its own boot; R5 and the verifier compared the bytes, which were identical.
- the dispatcher boot served
- Toolchain: Node 22.23.4, pnpm 10.31.0. Playwright chromium build 1243 matches
/opt/pw-browsers, so noexecutablePathoverride was needed. - App:
examples/app-showcase.- One dispatcher
os devcompile boot (port 42001) wrotedist/objectstack.jsonat 05:00Z. - Every later boot used
--no-compile --no-watch, from the tree or from a scratch copy withnode_modulessymlinked. cli.dev-boot-contractcompiled inside its own scratch copy.
- One dispatcher
- Boot line:
OS_PORT=PORT OS_STORAGE_LOCAL_ROOT=RUN/uploads setsid pnpm -C … exec objectstack dev --ui --seed-admin --no-compile --no-watch -p PORT -d file:RUN/ITEM.db, with--fresh/--log-level infowhere an item asks for them.- Seed:
--seed-adminplus the showcase seed,Seeds: com.example.showcase 132 rows. /api/v1/healthreports version 18.2.0, the unreleased line.
- Seed:
- Ports: 42101–42119 (R1), 42201–42219 (R2), 42301–42319 (R3), 42401–42419 (R4), 42501–42519 (R5), 42601–42619 (R6), 42701–42719 (R7), 42801 (rule-7 verifier). Each item ran on its own file DB under its runner's scratch dir. Every server was stopped by process group, and every port was empty at the end.
- Walled leg:
os devwithOS_TENANCY_POSTURE=isolated,OS_PLATFORM_OWNER_EMAIL, andOS_AUTH_MEMBERSHIP_POLICY=invite-only. The banner readTenancy: isolatedwithOrganizationsmounted, not DEGRADED. - v17-shaped DB: from npm
create-objectstack@17.7.0, a blank scaffold installed with--legacy-peer-depsand booted once by its ownos dev. 18.0 pre-release DB: thecli-18-prerelease-dbrestore, with recipe step 3 re-dating the token. Only copies were used, with a checksum or row diff around every step. - Scratch PostgreSQL 16: 127.0.0.1:42703, scram-sha-256.
- Timestamps (2026-11-01): prep 04:50Z–05:01Z; runners 05:01Z–05:33Z.
Execution
Parallel, per SKILL §2: seven runner subagents (R1–R7), each at effort high, with its own port range and file DBs.
- API and CLI items fanned out.
- Browser items ran on three runners at most (R5, R6, R7), one browser each.
The dispatcher checked every runner's verdicts against the raw evidence it captured: pin outputs, HTTP traces, boot logs and response bodies.
The one P0 fail was re-derived by an independent verifier (RUNNER rule 7). It used its own boot, port 42801, and was given the reproduction rule alone. It reproduced the fail on two fresh loads.
Scope: selector priority:P0, 23 runnable items
checklist-select.mjs reported 23 runnable items and 1 blocked item, hidden: access-security.no-active-org-session-semantics. No item is planned.
| item | revision | surface | runner | #27481 | now |
|---|---|---|---|---|---|
| access-security.rls-both-sides | 10 | api | R1 | PARTIAL | PARTIAL |
| access-security.write-path-guards | 8 | api | R1 | PASS | PASS |
| access-security.crud-permission-matrix | 11 | api | R1 | PARTIAL | PARTIAL |
| access-security.owd-sharing-matrix | 8 | api | R2 | PASS | PASS |
| access-security.anonymous-deny-surfaces | 5 | api | R2 | PASS | PASS |
| access-security.walled-environment-metadata-operator-only | 7 | api | R2 | PASS | PASS |
| ai.mcp-stdio-fail-closed | 8 | cli | R4 | PASS | PASS |
| api-backend.query-contract-matrix | 8 | api | R3 | PASS | PASS |
| api-backend.packaged-action-disabled-dispatch | 10 | api | R3 | PASS | PASS |
| approvals.account-app-entry | 7 | browser | R6 + verifier | PASS | FAIL |
| automation.packaged-flow-disable-durable | 8 | api | R3 | PASS | PASS |
| cli.dev-boot-contract | 9 | cli | R4 | PASS | PASS |
| cli.organization-ownership-ceremony | 7 | cli | R4 | PARTIAL | PASS |
| identity-auth.default-organization-boot-invariant | 4 | api | R2 | PASS | PASS |
| integration-system.datasource-credential-refusal-matrix | 7 | mixed | R7 | PASS | PASS |
| platform-core.boot-health | 13 | mixed | R5 | PASS | PASS |
| platform-core.seed-integrity | 6 | api | R3 | PASS | PASS |
| platform-core.console-login | 4 | browser | R5 | PASS | PASS |
| platform-core.nav-surfaces-render | 8 | browser | R5 | PASS | PASS |
| platform-core.builtin-apps-nav-render | 11 | browser | R5 | PASS | PASS |
| platform-core.v18-boot-refusals | 9 | cli | R4 | PASS | PASS |
| records-forms.crud-roundtrip | 16 | browser | R6 | PASS | PASS |
| studio-authoring.first-run-loop | 8 | mixed | R7 | PASS | PASS |
Per-clause verdicts
Layer note (RUNNER rule 6). A clause scored from a pin names the pin's layer:
- dogfood pins are in-process HTTP over a real engine and sqlite;
- objectql pins are the engine over a mock or recording driver;
- plugin-unit pins over stubs only corroborate.
Every clause whose oracle is a public door's answer was also driven on a live boot.
| item · clause | verdict | text oracle evidence |
|---|---|---|
| access-security.rls-both-sides · acceptance[0] | pass | live x2: A's list holds both of A's notes and not B's id; B's list holds only B's note (200). Pin showcase-private-owd 8/8 [HTTP in-process] |
| access-security.rls-both-sides · acceptance[1] | pass | live x2: A GET /data/showcase_private_note/B_ID → 404 RECORD_NOT_FOUND, the same envelope as an unknown id; B→A symmetric |
| access-security.rls-both-sides · acceptance[2] | pass | live x2: A PATCH B_ID {body:'forged'} → 404; admin pre/post re-read byte-identical (body, updated_at); pin case ✓ |
| access-security.rls-both-sides · acceptance[3] | pass | live x2: admin list holds every id the run created; pin 'the admin (platform posture) lists every note' ✓ |
| access-security.rls-both-sides · acceptance[4] | pass | objectstack verify --rls on a scratch copy, exit 0. Per-persona 21 PROVEN (21 consistent, 0 HOLES) · 3 NOT PROVEN. Total all personas: 38 PROVEN (38 consistent, 0 HOLES) · 226 NOT PROVEN [unit: one object × persona probe]. 10 of 10 positions. Adopted-row proof on showcase_account only. Bare-verify control tail 15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped, no PROVEN line |
| access-security.rls-both-sides · acceptance[5] | blocked | blocked{by: dependency, ref: knownGaps[0] / #22017 row 11}: the D11 spot-check needs the private write-up. Public half holds: 3 benign skip reasons; member spot-check on project_membership and ext_* answers 403, rows unchanged |
| access-security.rls-both-sides · negative[0] | pass | forged PATCH 404, admin re-read unchanged (live x2 + pin) |
| access-security.rls-both-sides · negative[1] | pass | procedural: the private-defect verdict is carried on acceptance[5] only |
| access-security.rls-both-sides · negative[2] | pass | procedural: cites item and clause, never the bare handle |
| access-security.write-path-guards · acceptance[0] | pass | live x2 (admin): POST showcase_contact {lead_score:10} → 201, header X-ObjectStack-Dropped-Fields: lead_score;reason=readonly, body droppedFields, read-back null. Pin static-readonly 4/4 [HTTP] |
| access-security.write-path-guards · acceptance[1] | pass | live x2: PATCH {lead_score:99} → 200 with the dropped header; null before and after |
| access-security.write-path-guards · acceptance[2] | pass | live x2 as member Alice: POST note {owner_id:Bob} → 403 PERMISSION_DENIED (transfer grant); 0 planted rows |
| access-security.write-path-guards · acceptance[3] | pass | live x2: self-owner 201; PATCH owner_id=Bob and owner_id=null → 403; owner re-reads Alice |
| access-security.write-path-guards · acceptance[4] | pass | live x2: bare-array createMany of 3 → 201, all owner Alice; {records:[…]} → 400 VALIDATION_FAILED. Pin owner-anchor-and-bulk-writes 12/12 |
| access-security.write-path-guards · acceptance[5] | pass | live x2: paid invoice tax_rate PATCH → 200 dropped readonly_when, re-reads 5; line quantity/unit_price/product dropped; mixed updateMany per-row droppedFields. Pin readonly-when-parent 9/9 |
| access-security.write-path-guards · acceptance[6] | pass | live x2: continueOnError [3,-1,3] → 2 succeeded / 1 failed VALIDATION_FAILED, re-read [3,1,3]; default-stop [4,-1,4] → row 2 NOT_ATTEMPTED, re-read [4,1,3] |
| access-security.write-path-guards · negative[0] | pass | live x2 admin: forge-insert 201 owner Bob; transfer 200; disown 200 owner null; pin cases ✓ |
| access-security.write-path-guards · negative[1] | pass | engine layer (real ObjectQL over recording/fake driver, own test objects): isSystem cases ✓, 2 files 55/55 |
| access-security.crud-permission-matrix · acceptance[0] | pass | live REST sweep x2: 164 showcase_* cells, all 87 effective-allow cells answered under 300 with the effect proven, bad=[]. Pin crud-persona-matrix 49/49 [HTTP] |
| access-security.crud-permission-matrix · acceptance[1] | pass | live x2: all 77 deny cells 403 with top-level code PERMISSION_DENIED; delegate sys_user create/delete 405 OBJECT_API_METHOD_NOT_ALLOWED (admin control 405 too) |
| access-security.crud-permission-matrix · acceptance[2] | pass | live x2: an admin marker scan after all 17 denied creates finds 0 rows |
| access-security.crud-permission-matrix · acceptance[3] | pass | live x2: auditor by-id 200 and in-list on foreign private_note, inquiry, invoice, line; contributor by-id 404 and excluded |
| access-security.crud-permission-matrix · acceptance[4] | pass | live x2: ops PATCHes admin's announcement → 200, persisted; plain member → 403, unchanged |
| access-security.crud-permission-matrix · acceptance[5] | blocked | blocked{by: dependency, ref: #23267} per knownGaps[2]: PUT /meta/position/guest naming a set → 403 NOT_OVERRIDABLE, re-read unchanged; anonymous → 401. Pin guest-grants-channel 21/21 on an inline fixture scores nothing here |
| access-security.crud-permission-matrix · acceptance[6] | pass | 45 rows recounted (41 showcase_* + 4 delegate × sys_*); live 164 cells (87/77/9 flips) + 16/16 delegate cells |
| access-security.crud-permission-matrix · negative[0] | pass | live x2: first denied cell of each of 8 sets re-run as admin → 2xx |
| access-security.crud-permission-matrix · negative[1] | pass | no withheld cell answered 2xx (0 over 164 + 16) |
| access-security.owd-sharing-matrix · acceptance[0] | pass | HTTP live x3: A POST 201; B list(filter id)=[], list(all) n=0, GET 404, PATCH 404; admin re-read shows only A's edit. Pin private-owd 8/8 |
| access-security.owd-sharing-matrix · acceptance[1] | pass | x3: admin-owned announcement; B GET 200 and in list; B forged PATCH 403 PERMISSION_DENIED, unchanged. Pin public-read-owd 4/4 |
| access-security.owd-sharing-matrix · acceptance[2] | pass | x3: ops PATCH of admin's announcement 200, re-read edited |
| access-security.owd-sharing-matrix · acceptance[3] | pass | rounds b and c: admin project 201; C1 GET 200, PATCH 200 persisted; A's identical PATCH 403, row unchanged |
| access-security.owd-sharing-matrix · acceptance[4] | pass | x3: C1 invoice + line 201; C2 excluded (list n=0, GET 404, PATCH 404, unchanged); C1 contains/200/200. Pin invoice-line-contributor-pair 5/5 |
| access-security.owd-sharing-matrix · acceptance[5] | pass | x3: auditor list(filter id) contains C1's line, GET 200 |
| access-security.owd-sharing-matrix · acceptance[6] | pass | procedural: all four models driven per persona and verb |
| access-security.owd-sharing-matrix · negative[0] | pass | direct forged PATCH by B on the public_read announcement → 403, unchanged (x3) |
| access-security.owd-sharing-matrix · negative[1] | pass | C2's line probes repeated as C1: contains / 200 / 200 |
| access-security.anonymous-deny-surfaces · acceptance[0] | pass | HTTP live x2, no header or cookie (anonymous get-session 401): data, meta, actions, automation/_status, batch, security/explain, analytics query/sql (valid and malformed)/meta → 401. Pin showcase-anonymous-deny-surfaces 75/75 |
| access-security.anonymous-deny-surfaces · acceptance[1] | pass | anonymous POST /actions/showcase_task/showcase_mark_done/anon-probe-id → 401; member same call → 404 RECORD_NOT_FOUND |
| access-security.anonymous-deny-surfaces · acceptance[2] | pass | each 401 body matched exactly one family: rest-flat (/data /meta /batch /security/explain), dispatcher-wrapper (/actions /automation, analytics x5) |
| access-security.anonymous-deny-surfaces · acceptance[3] | pass | anonymous analytics → 401 (malformed too, not 400); member query 200, sql 200, meta 200, malformed 400 VALIDATION_FAILED |
| access-security.anonymous-deny-surfaces · acceptance[4] | pass | member (not platform admin) GET /data/showcase_private_note 200, GET /meta 200 |
| access-security.anonymous-deny-surfaces · acceptance[5] | pass | anonymous GET /api/v1/forms/contact-us → 200, serving the showcase_inquiry form |
| access-security.anonymous-deny-surfaces · acceptance[6] | pass | procedural: all 7 families driven live |
| access-security.anonymous-deny-surfaces · negative[0] | pass | anonymous DELETE /automation/showcase_reassign_wizard → 401; admin GET afterwards 200 (x2) |
| access-security.walled-environment-metadata-operator-only · acceptance[0] | pass | pins at eeec88d, maxWorkers=1: rest meta-migrate-stored-walled-refusal 6/6 (unit, vi.fn transport); runtime packages-walled 30/30, automation-walled 12/12, meta-walled-catalog 19/19 (unit); dogfood wall-environment-metadata-refusal 23/23, wall-catalog-refusal 17/17, wall-package-doors-refusal 23/23 (in-process HTTP, CRM example) |
| access-security.walled-environment-metadata-operator-only · acceptance[1] | pass | HTTP live on the isolated boot, x2, as org owner O (isPlatformAdmin false, holds manage_metadata): PUT /meta/object → 403 FORBIDDEN, read-back 404; PUT /meta/permission/showcase_member_default → 403, unchanged; view publish → 403; DELETE /packages/com.example.showcase → 403 PERMISSION_DENIED, still installed; set clone → 403; _migrate-stored → 403 FORBIDDEN; POST /automation → 403. Messages name 'isolated' and ADR-0131 D3/D12 |
| access-security.walled-environment-metadata-operator-only · acceptance[2] | pass | walled operator PUT → 200, read-back, DELETE 200, read-back 404 (x2); single fresh boot admin same (x2) |
| access-security.walled-environment-metadata-operator-only · negative[0] | pass | no org-owner environment-metadata write succeeded: 7 doors x2 + 20 probe doors; nothing stored |
| identity-auth.default-organization-boot-invariant · acceptance[0] | pass | plugin-auth ensure-default-organization 57/57 (plugin unit, fake driver); runtime identity-objects-default-organization.pin 4/4 (engine, reduced kernel) |
| identity-auth.default-organization-boot-invariant · acceptance[1] | pass | fresh boot --log-level info: [default-org] created the Default Organization at 05:07:09.994Z before Dev admin seeded 05:07:12.081Z; DB created_at order agrees |
| identity-auth.default-organization-boot-invariant · acceptance[2] | pass | sys_member: admin owner, created user member; get-session activeOrganizationId = default org for both |
| identity-auth.default-organization-boot-invariant · acceptance[3] | pass | sys_business_unit 5 rows, all organization_id = default org |
| identity-auth.default-organization-boot-invariant · negative[0] | pass | DB scan of 64 tables carrying organization_id: 0 NULL rows |
| ai.mcp-stdio-fail-closed · acceptance[0] | pass | live os start stdio, key unset: exit 1, stdout 0 bytes, health 000, "…OS_MCP_STDIO_API_KEY is not set … Refusing to start an unscoped stdio server (ADR-0101)" |
| ai.mcp-stdio-fail-closed · acceptance[1] | pass | osk_unknown exit 1 "did not resolve to a valid identity"; revoked key exit 1 "is refused (API_KEY_REVOKED)" |
| ai.mcp-stdio-fail-closed · acceptance[2] | pass | INFO "[MCP] stdio transport principal-bound to OS_MCP_STDIO_API_KEY identity … (RLS/FLS/tenant applied)", the member's user id |
| ai.mcp-stdio-fail-closed · acceptance[3] | pass | member MCP == member REST (own invoice, identical 19-field set; INV-1003 not found / 404); liaison project rows lack budget/spent/budget_remaining on both; admin sees them |
| ai.mcp-stdio-fail-closed · acceptance[4] | pass | count by status: member MCP [{draft:1}] == member REST; admin REST draft 3 / paid 5 / sent 5 |
| ai.mcp-stdio-fail-closed · acceptance[5] | pass | liaison sum(budget), groupBy budget, count_distinct(spent) → isError PERMISSION_DENIED 403 "[Security] Field read denied …", no number; controls ok |
| ai.mcp-stdio-fail-closed · acceptance[6] | pass | same stdio session: pre-revoke 1 row; revoke (admin session) 200; next call isError code API_KEY_REVOKED status 403, no rows |
| ai.mcp-stdio-fail-closed · acceptance[7] | pass | --log-level info, health 200: "INFO [MCP] Transport not auto-started (HTTP is served per-request …)" |
| ai.mcp-stdio-fail-closed · negative[0]–[4] | pass | empty, whitespace, osk_, unknown and revoked keys never serve; member 1 vs admin 13; masked aggregates refused; post-revoke API_KEY_REVOKED |
| api-backend.query-contract-matrix · acceptance[0] | pass | HTTP live: 32 variant rows × 3 doors (POST $-body, POST AST, GET $filter) = 96 calls, id-set equal to local baseline, 0 diffs; $contains/$startsWith case-exact; infix compound → 400 VALIDATION_FAILED |
| api-backend.query-contract-matrix · acceptance[1] | pass | $orderby=name&$top=3&$skip=2 = sorted rows 3–5; $top=4&$skip=9 = rows 10–13; POST {limit,offset} and {top,skip} equal |
| api-backend.query-contract-matrix · acceptance[2] | pass | $select=name,status and POST fields → 14 rows, keys exactly {name,status}; POST fields:['account.name'] → 400 INVALID_FIELD naming expand |
| api-backend.query-contract-matrix · acceptance[3] | pass | asc/desc on both doors equal the local sort; no_such_field → 400 INVALID_SORT |
| api-backend.query-contract-matrix · acceptance[4] | pass | contributor (get-session proven): contact direct 403; expand via body, $expand, by-id expand → contact left as raw id, no name/email; admin materialised. Pin showcase-expand-crud-gate 10/10 [HTTP] |
| api-backend.query-contract-matrix · acceptance[5] | pass | {status:{$nin:'done'}} → 400 VALIDATION_FAILED at query.where.status.$nin; AST → 400; GET $filter → 400 INVALID_FILTER; no rows |
| api-backend.query-contract-matrix · acceptance[6] | pass | ?$pageSize=5 → 400 UNSUPPORTED_QUERY_PARAM listing 9 params; ?not_a_field=x and where on it (3 doors, = and !=) → 400 INVALID_FIELD |
| api-backend.query-contract-matrix · acceptance[7] | pass | $in:[] → 0/10; $nin:[] → 10/10; AST twins equal on POST and GET |
| api-backend.query-contract-matrix · acceptance[8] | pass | one recorded row per variant (30); $count true/false, $search, $expand=account rows recorded |
| api-backend.query-contract-matrix · negative[0] | pass | {limit:"ten"} → 400 at query.limit; {not_a_query_key:…} → 400 INVALID_FIELD; no rows |
| api-backend.packaged-action-disabled-dispatch · acceptance[0] | pass | flip 200 (ledger row, no organization_id key); mark_done bogus id → 409 {code: ACTION_DISABLED, message: "This action is turned off for this deployment. An administrator can turn it on again under Setup › Packaged automation, or you can use another action."}; 10 tasks unchanged |
| api-backend.packaged-action-disabled-dispatch · acceptance[1] | pass | gallery disabled + garbage params → 409; re-enabled identical → 400 VALIDATION_ERROR naming p_text and bogus_key |
| api-backend.packaged-action-disabled-dispatch · acceptance[2] | pass | every disabled 409 had the bogus recordId in play and wrote nothing; enabled control 404 RECORD_NOT_FOUND |
| api-backend.packaged-action-disabled-dispatch · acceptance[3] | pass | showcase_zoo_perm_missing → 403 PERMISSION_DENIED "requires capability [showcase.restricted_ops]", enabled and disabled, byte-identical |
| api-backend.packaged-action-disabled-dispatch · acceptance[4] | pass | live MCP: run_action portfolio_snapshot disabled → isError ACTION_DISABLED 409, same sentence; re-enabled ok |
| api-backend.packaged-action-disabled-dispatch · acceptance[5] | pass | cold restart: INFO "Activation ledger: 1 packaged action(s) are switched off … 'showcase_mark_done'"; still 409; re-enable 200; real id 200 (done, progress 100); same row id |
| api-backend.packaged-action-disabled-dispatch · acceptance[6] | pass | flow-type showcase_bulk_reassign disabled → 409 ACTION_DISABLED; showcase_reassign_wizard no ledger row, no run (see accuracy line: the message no longer names the action) |
| api-backend.packaged-action-disabled-dispatch · negative[0]–[2] | pass | disabled calls never got the 400 param shape or a record answer; absence means active; the 403 capability gate wins; anonymous 401 |
| automation.packaged-flow-disable-durable · acceptance[0] | pass | baseline urgent create runs 0→1; toggle off 200; exactly 1 sys_metadata_activation row, active false, no organization_id key |
| automation.packaged-flow-disable-durable · acceptance[1] | pass | trigger → 409 FLOW_DISABLED "This flow is turned off for this deployment. An administrator can turn it on again under Setup › Packaged automation, or copy it there under a new name." |
| automation.packaged-flow-disable-durable · acceptance[2] | pass | cold restart: _status enabled false, bound false; INFO "Activation ledger: 1 packaged flow(s) are switched off … 'showcase_urgent_task_alert'" |
| automation.packaged-flow-disable-durable · acceptance[3] | pass | new process: urgent create 201, runs stay 1 after 4 s; trigger still 409 |
| automation.packaged-flow-disable-durable · acceptance[4] | pass | toggle on 200; same row id, active true, updated_at moved; final create runs 1→2 |
| automation.packaged-flow-disable-durable · negative[0]–[3] | pass | row written; restart did not re-arm; row kept; never the bare status sentence |
| platform-core.seed-integrity · acceptance[0] | pass | expected counts from ShowcaseSeedData (19 datasets / 132 rows); $count totals match 19/19 |
| platform-core.seed-integrity · acceptance[1] | pass | Specimen — Full: 37 fields match; lookups resolve; f_time canonical '14:30:00'; f_password masked as declared |
| platform-core.seed-integrity · acceptance[2] | pass | banner Seeds: com.example.showcase 132 rows plain; [Seeder] … {"inserted":0,"updated":0,"skipped":132,"errored":0} |
| platform-core.seed-integrity · acceptance[3] | pass | restart over the same DB: second sweep identical |
| platform-core.seed-integrity · acceptance[4] | pass | f_user, f_users, f_secret null; task.cover null on all 10 |
| platform-core.seed-integrity · negative[0]–[1] | pass | no seeded object counts 0; counts did not grow |
| cli.dev-boot-contract · acceptance[0] | pass | scratch copy with no dist (first boot compiled): health 200 after 11 s, /ready 200 {status:ready,state:running} |
| cli.dev-boot-contract · acceptance[1] | pass | admin123 sign-in 200; restart with --admin-password changed99 on the same DB: admin123 200, changed99 401 |
| cli.dev-boot-contract · acceptance[2] | pass | Database lines: -d file: / env URL / :memory: / nothing chosen → .objectstack/data/objectstack.db / config qa_home / legacy dev.db with notice |
| cli.dev-boot-contract · acceptance[3] | pass | "🧪 Fresh OS_HOME: /tmp/objectstack-dev-…"; SIGINT 130 and SIGTERM 143, tempdir gone both times |
| cli.dev-boot-contract · acceptance[4] | pass | "⚠ Port 42406 is in use — serving on 42407 instead." + "↪ server bound to port 42407 (requested 42406)" |
| cli.dev-boot-contract · acceptance[5] | pass | --no-compile: "⚠ dist/objectstack.json is OLDER than your sources …", boots |
| cli.dev-boot-contract · acceptance[6] | pass | empty dir: exit 1 with the remedy line |
| cli.dev-boot-contract · acceptance[7] | pass | screenshot first: ObjectOS "Welcome back" login at /_console/login; entry equals dist; form sign-in reaches /_console/home |
| cli.dev-boot-contract · negative[0]–[3] | pass | marker survives reboot; retired engine spellings refused (exit 2 / 1); legacy read creates no objectstack.db; shifted port reported |
| cli.organization-ownership-ceremony · acceptance[0] | pass | unit/integration over SQLite, no HTTP: cli 8 files 179/179; runtime boot-guard 22/22 |
| cli.organization-ownership-ceremony · acceptance[1] | pass | refused boot, then plan exit 0 "no row or table … changed", copy sha unchanged, row diff 0; --apply without plan file exit 1 (--json reason plan-file-required) |
| cli.organization-ownership-ceremony · acceptance[2] | pass | apply: exit 0, complete true, blocking 0, 13 steps done; marker shapeGeneration 1 |
| cli.organization-ownership-ceremony · acceptance[3] | pass | unmigrated copy: exit 1, 0 ready lines, names 9 tables and the ceremony commands; migrated copy "✓ Server is ready" |
| cli.organization-ownership-ceremony · acceptance[4] | pass | reactions conversion refused without --yes, exit 0 twice with it; migrate apply --allow-destructive exit 1 refused_organization_ownership_unmigrated, sha unchanged |
| cli.organization-ownership-ceremony · acceptance[5] | pass | cli-18-prerelease-db restore, all --dev: boot 1 refused, apply complete / blocking 0, boot 2 ready; moved rows 0 diffs (2 identity mails, 8 audit rows, 2 job payloads re-pointed); 3 sign-ins 200 / wrong password 401; reset with the moved mail's token → 200 (was blocked at #27481); one task PATCH → exactly 1 sys_http_delivery row |
| cli.organization-ownership-ceremony · negative[0] | pass | no refusing or plan arm changed any checksum or row |
| platform-core.v18-boot-refusals · acceptance[0] | pass | runtime boot-guard 22/22 + kernel 10/10 (unit + kernel, no HTTP); plugin-security 3/3 |
| platform-core.v18-boot-refusals · acceptance[1] | pass | production os serve over a v17 copy (secret + key set): exit 1, 0 listening lines, names 9 tables and the commands without --dev; --dev spells --dev |
| platform-core.v18-boot-refusals · acceptance[2] | pass | row diff: production copy 69 tables / 62 rows 0 differences, 53 created tables empty; dev copy 0 differences |
| platform-core.v18-boot-refusals · acceptance[3] | pass | live rig (serve --dev --no-server --preset minimal, SecurityPlugin + one object): exit 1 "✗ SecurityPlugin cannot boot … mount createIdentityObjectsPlugin()" |
| platform-core.v18-boot-refusals · negative[0] | pass | every v18 boot over a v17 copy refused and left pre-existing rows unchanged |
| platform-core.boot-health · acceptance[0] | pass | health 200 {status:ok, version 18.2.0}, time-to-healthy 16.5 s |
| platform-core.boot-health · acceptance[1] | pass | /api/v1/ready 200 {status:ready,state:running}, the first non-health request |
| platform-core.boot-health · acceptance[2] | pass | Flows: 32 flow(s) 19 bound … · 8 draft; two ℹ deployment-policy lines; 0 ⚠, 0 ERROR in the boot window |
| platform-core.boot-health · acceptance[3] | pass | GET meta/app?id=showcase_app 200 {type,items}; app list [showcase_app, setup, account] |
| platform-core.boot-health · acceptance[4] | pass | 51 authored nav ids (incl. separator) vs 51 served: diff empty; grp_data 12 objects |
| platform-core.boot-health · acceptance[5] | pass | /_console/ 200 text/html, entry index-RFCp05oY.js |
| platform-core.boot-health · negative[0]–[1] | pass | no seed rejection; 0 ERROR lines in the boot window |
| platform-core.console-login · acceptance[0] | pass | form sign-in 200, landed /_console/home; screenshot: header + launcher |
| platform-core.console-login · acceptance[1] | pass | reload stays on /home; get-session, discovery, i18n 200; meta/app?id=showcase_app 200 |
| platform-core.console-login · acceptance[2] | pass | sign-out 200; same bearer: meta/app 401 UNAUTHENTICATED, get-session 401 |
| platform-core.console-login · acceptance[3] | pass | full navigation → /_console/login?redirect=%2Fapps%2Fcom.example.showcase%2Fshowcase_task; client nav shows the named "Sign in required" state |
| platform-core.console-login · acceptance[4] | pass | re-login 200 returns to the showcase_task route (10 rows); fresh reads 200, write 201 |
| platform-core.console-login · negative[0]–[1] | pass | wrong password 401 INVALID_EMAIL_OR_PASSWORD, no cookie, no token, alert shown; no stale data after expiry |
| platform-core.nav-surfaces-render · acceptance[0] | pass | browser over live HTTP (:42502): examples/app-showcase/e2e/showcase-smoke.spec.ts 49 passed, 0 failed (1.6 min) |
| platform-core.nav-surfaces-render · acceptance[1] | pass | 50 served leaves vs 49 SURFACES: the only unlisted leaf, nav_report_index (/reports), was hand-walked twice: "Reports — All reports / Recent", 4 reports, 0 pageerror; sidebar 50 links, no injected row |
| platform-core.nav-surfaces-render · acceptance[2] | pass | bad route on 2 fresh loads: shell alive, "Object Not Found — The object …" |
| platform-core.nav-surfaces-render · acceptance[3] | pass | no render failure met; the boundary fallback is unexercised (existing knownGap) |
| platform-core.nav-surfaces-render · negative[0]–[3] | pass | suite: no blank main; splash wait held on 49; bad route kept the shell; charts passed the polled boundingBox check |
| platform-core.builtin-apps-nav-render · acceptance[0] | pass | admin, every group expanded, screenshot-first walk: Setup 50/50, Account 8/8, 0 pageerror; only "failed to load" is the knownGap marketplace (wire 502) |
| platform-core.builtin-apps-nav-render · acceptance[1] | pass | setup: requiredPermissions [setup.access], 9 groups, 50 leaves; the only unserved source ids are gated (organizations, sso_providers); account 8 leaves / 3 groups; ?id=studio empty |
| platform-core.builtin-apps-nav-render · acceptance[2] | pass | member Mei (get-session phone.demo, positions [org_member, everyone]): setup routes show "You don't have access to this app" |
| platform-core.builtin-apps-nav-render · acceptance[3] | pass | member ?id=setup → 200 {items:[]}; GET meta/app/setup → 403; member list [showcase_app, account] |
| platform-core.builtin-apps-nav-render · acceptance[4] | pass | setup unobtainable for the member; account nav admin 8 = member 8 (control) |
| platform-core.builtin-apps-nav-render · acceptance[5] | pass | nav_organizations absent (single); nav_business_units present, sys_business_unit 200 |
| platform-core.builtin-apps-nav-render · acceptance[6] | pass | no jwks / sso / verification / device_code entries; auth config sso false |
| platform-core.builtin-apps-nav-render · negative[0]–[3] | pass | no blank pages beyond the marketplace knownGap; member denied on the wire and in the UI; member /api/settings/NS → 403 SETTINGS_FORBIDDEN for all 11 namespaces (admin 200) |
| approvals.account-app-entry · acceptance[0] | pass | layer build: the dispatcher's pnpm console:build at eeec88d printed ✓ @objectstack/console dist ready (82052 KB) from ui/apps/console; the served entry contains approvals:inbox |
| approvals.account-app-entry · acceptance[1] | pass | avatar › Profile › Inbox › Approvals → /_console/apps/com.objectstack.account/component/approvals/inbox; screenshot: My Pending 1 / Submitted by me / All, one Pending row |
| approvals.account-app-entry · acceptance[2] | pass | non-admin persona GET /meta/app → [showcase_app, account] with nav_account_approvals; ?id=setup empty, GET /meta/app/setup 403 |
| approvals.account-app-entry · acceptance[3] | fail | row click → …/sys_approval_request/record/AREQ_ID renders record-access-denied "You don't have access to Approval Request records", no decision panel; its only record read POST /api/v1/data/sys_approval_request/AREQ_ID/page → 403 PERMISSION_DENIED, while GET /api/v1/approvals/requests/AREQ_ID → 200 viewer.can_act: true. R6 3x + verifier 2x on fresh loads |
| approvals.account-app-entry · acceptance[4] | fail | cold load …/component/approvals/inbox?request=AREQ_ID replaces itself with the record route (routing half holds), which then shows the same access-denied screen from the same 403. R6 + verifier, 2x each |
| approvals.account-app-entry · acceptance[5] | pass | inbox row record link href /_console/apps/com.objectstack.account/showcase_invoice/record/ID (current app segment); lands and renders; persona GET 200 |
| approvals.account-app-entry · acceptance[6] | pass | Preferences › Language 中文(中国), html lang zh-CN; nav 待我审批, tabs 待我审批 / 我发起的 / 全部, badge 待审批 |
| approvals.account-app-entry · negative[0] | pass | full inbox rendered from the nav entry, no missing-component state |
| approvals.account-app-entry · negative[1] | pass | Approvals entry present for the persona; setup absent (see acceptance[2]) |
| records-forms.crud-roundtrip · acceptance[0] | pass | UI Create → POST showcase_account {industry:'retail',status:'active',sales_region:'amer',name:'os-qa-r6w3c1r'} 201; filtered GET total 1, 4 keys equal |
| records-forms.crud-roundtrip · acceptance[1] | pass | Update → PATCH {annual_revenue:4321000} 200; across 24 keys only annual_revenue and updated_at differ |
| records-forms.crud-roundtrip · acceptance[2] | pass | ⋯ › Delete › confirm Delete Account "os-qa-r6w3c1r"? → DELETE 200; filtered GET total 0; by id 404 |
| records-forms.crud-roundtrip · acceptance[3] | pass | post-reload list at create: row shown, 15 records; at delete: absent |
| records-forms.crud-roundtrip · acceptance[4] | pass | record page v3 Activity (?related=timeline), Changes selected: update line Annual Revenue — → $4,321,000.00 · Dev Admin; create line lists owner, name, industry, lifecycle, region; sys_audit_log holds create + update, no phantom rows. Driven by hand (the live spec needs ports 3000/5180) |
| records-forms.crud-roundtrip · acceptance[5] | pass | UI create of os-qa-r6w3c1r-华宁 201, hex-identical re-read; $search=华宁 → 2 rows; list quick-search 2 |
| records-forms.crud-roundtrip · acceptance[6] | pass | admin clone 201 (new id, sourceId); contributor-bound member clone of an admin-owned zoo row → owner/created_by/updated_by the member, autonumber 0001→0003; planted readonly lead_score=42 dropped on clone (droppedFields … readonly), clone reads null |
| records-forms.crud-roundtrip · acceptance[7] | pass | recipe search:qa-contributor-bound-member; member sees 0 of 12 foreign invoices; clone of INV-1003 → 404 RECORD_NOT_FOUND twice; admin count 13→13 |
| records-forms.crud-roundtrip · negative[0] | pass | empty Account Name: inline "Account Name is required", dialog stays, no write, count unchanged |
| records-forms.crud-roundtrip · negative[1] | pass | id/audit/autonumber re-derived; readonly dropped; RLS-invisible clone 404 |
| records-forms.crud-roundtrip · negative[2] | pass | no name and name:"" → 400 VALIDATION_FAILED fields[{field:name,code:required}] |
| records-forms.crud-roundtrip · negative[3] | pass | tax_id 123456789 and AB-CDEFGHI → 400 code:invalid_format; control 12-3456789 201 |
| integration-system.datasource-credential-refusal-matrix · acceptance[0] | pass | every enumerated door refused at both doors: os compile exit 2 at the path; POST /api/v1/datasources 400 DATASOURCE_ADMIN_ERROR (pg/mysql/mongodb password, turso authToken, passwd alias, URL userinfo and ?password=, mongodb options.auth.password, nested pool.token, ${PG_PASSWORD}, driver:'mongo', credentialsRef twins, turso encryptionKey); connector authentication build path + PUT /meta/connector 422; every refusal names external.credentialsRef; pg-paved control exit 0 |
| integration-system.datasource-credential-refusal-matrix · acceptance[1] | pass | scratch PG16: POST r7pg with a bound secret → 201 status ok; /test ok, tableCount 1; remote-tables lists the out-of-band table; no-secret control fails SASL |
| integration-system.datasource-credential-refusal-matrix · acceptance[2] | pass | full-body grep of admin (list + 8), meta (list + 8) and /data/sys_metadata?type=datasource: only cleartext hit is the ruled apiSecret |
| integration-system.datasource-credential-refusal-matrix · acceptance[3] | pass | r7pg hasSecret:true; no-secret hasSecret:false; inline legacy redactedConfigKeys:["password"] |
| integration-system.datasource-credential-refusal-matrix · acceptance[4] | pass | 5 rows planted with the server stopped (passwd/pwd, token/jwt/auth_token/authtoken, encryptionKey, mysql password, pg userinfo): all listed after reboot, redacted on all three doors, 0 planted values on any door or log |
| integration-system.datasource-credential-refusal-matrix · acceptance[5] | pass | unknown driver acme-plugin-db 201 / exit 0 (ruled boundary); password, authToken, passwd, userinfo withheld; apiSecret served as ruled |
| integration-system.datasource-credential-refusal-matrix · acceptance[6] | pass | echoed PATCH {config} 200, full-object PATCH 200, PUT 405; /test still ok, credentialsRef unchanged |
| integration-system.datasource-credential-refusal-matrix · acceptance[7] | pass | auditor.demo and phone.demo (get-session proven) 403 PERMISSION_DENIED on every admin and meta datasource read and /data/sys_metadata; anonymous 401 |
| integration-system.datasource-credential-refusal-matrix · negative[0]–[6] | pass | no cleartext, no two-door disagreement on any enumerated door, consistent redaction, all aliases redacted, plugin canonical keys withheld, no mask served, every refusal names its replacement |
| studio-authoring.first-run-loop · acceptance[0] | pass | by hand (F1 pin not run): Home chip "New in Studio" → New package 维修中心 / com.example.repairs; POST /api/v1/packages 201; switcher "Writable"; navigation entries only navigate (no reload) |
| studio-authoring.first-run-loop · acceptance[1] | pass | Publish all → publish-drafts 200 publishedCount 1; GET /meta/object/repairs_repair_ticket 200 with options open / wip "In Repair" / closed |
| studio-authoring.first-run-loop · acceptance[2] | pass | Studio Add record → POST 201; GET /data/repairs_repair_ticket → {name:"Broken pump",status:"wip"} |
| studio-authoring.first-run-loop · acceptance[3] | pass | /meta/app includes repair_center with nav_repairs_repair_ticket; screenshots: Home launcher "Repair Center"; end-user list chip "In Repair", raw "wip" 0 times |
| studio-authoring.first-run-loop · acceptance[4] | pass | one Server is ready; listener PID unchanged from 05:13:03 to 05:23:04 |
| studio-authoring.first-run-loop · acceptance[5] | pass | forged as admin x2: object into com.example.showcase → 422 WRITABLE_PACKAGE_REQUIRED; field on showcase_account → 403 ITEM_LOCKED; plain PUT → 403 NOT_OVERRIDABLE; nothing landed |
| studio-authoring.first-run-loop · negative[0]–[1] | pass | no silent acceptance; the label chip renders |
Reproduction rules for fails
approvals.account-app-entry · acceptance[3] and acceptance[4] have one root cause. The rule was reproduced 3 times by R6 and twice by the independent verifier, on fresh loads.
Steps:
- Boot the stock showcase:
objectstack dev --ui --seed-admin --no-compile -p PORT -d file:RUN/appr.db. - As admin,
POST /api/v1/auth/organization/invite-member{"email":"x@example.test","role":"member"}. X then callsPOST /api/v1/auth/sign-up/email. - As admin,
POST /api/v1/data/sys_user_position{"user_id": X_ID, "position": "contributor", "organization_id": ORG}, and the same with"finance". - As X,
POST /api/v1/data/showcase_invoice{"name":"INV-1","account": ACTIVE_ACCOUNT_ID,"owner":"x@example.test"}→ 201. - As X,
PATCHthe invoice{"status":"sent","issued_on":"2026-11-01"}. An approval request opens with X amongpending_approvers. - Sign X in through the Console form and open avatar › Profile › Inbox › Approvals. Then:
- click the row;
- separately, cold-load
/_console/apps/com.objectstack.account/sys_approval_request/record/AREQ_ID; - separately, cold-load
/_console/apps/com.objectstack.account/component/approvals/inbox?request=AREQ_ID.
Expected: the request page with Approve / Reject / Reassign (acceptance[3]), and that exact request after the deep link (acceptance[4]).
Actual:
POST /api/v1/data/sys_approval_request/AREQ_ID/page→ 403{"code":"PERMISSION_DENIED","object":"sys_approval_request"}.- The page draws
[data-testid=record-access-denied]. GET /api/v1/approvals/requests/AREQ_IDis never called; called directly, it answers 200 withviewer.can_act: true.
Ruled out:
- a stale bundle: the served entry is byte-identical to dist;
- a hydration race: screenshots at 3 s and 8 s are identical, and the state is terminal;
- the wrong persona: get-session shows the invitee,
isPlatformAdmin: false; - the automation input: cold loads involve no click.
Mechanism:
- feat(rest,console): one request opens a record page #27713 made
RecordDetailViewread the opened record fromgetRecordPage. - The console's approvals routing (
routeApprovalRecordReads,ui/apps/console/src/services/approvalRequestsDataSource.ts) overrides onlyfindandfindOne, so that read goes to the generic data door, which has no object read for these positions.
Disposition: product defect, extracted (see the close-out comment).
Retest of earlier QA cards met in passing
These were observed on this run's boots as off-clause controls. They are not clause verdicts.
- data: a blank or comma-only
$searchFieldsis read as absent, so a search the caller narrowed runs over the default search fields instead of being refused #27484: a blank$searchFieldsis now refused. The card is closed. - console: the record history "Changes" entry shows a currency (and number) field as its raw stored value, e.g. 4321000, where the record shows $4,321,000.00 #27486: the Changes line now formats currency,
$4,321,000.00. - data: POST /api/v1/data/:object/:id/clone accepts an
overridesthat is not an object (a string) and answers 201 with the overrides silently ignored #27489: a clone withoverrides:"x"now answers 400. - approvals: GET /api/v1/approvals/requests/:id/actions answers 200 {"data":[]} for an unknown request id, where GET /api/v1/approvals/requests/:id answers 404 #27493:
/approvals/requests/UNKNOWN/actionsnow answers 404 REQUEST_NOT_FOUND. - data list door: a blank $select answers every column and an unrecognised $count value counts — malformed values are read as the absent default #26644: an empty
$select/select/fieldsand a bad$countanswer 400 VALIDATION_ERROR, and the POST door answers 400 VALIDATION_FAILED; the controls answer 200.
Pins and the Playwright smoke
- Playwright smoke:
examples/app-showcase/e2e/showcase-smoke.spec.tsgave 49 passed, 0 failed (1.6 min), against a live boot on 42502, from a scratch copy. objectstack verify --rls, run separately from bareverify, on a scratch copy:- per-persona line:
21 PROVEN (21 consistent, 0 HOLES) · 3 NOT PROVEN; - total line:
all personas: 38 PROVEN (38 consistent, 0 HOLES) · 226 NOT PROVEN [unit: one object × persona probe]; - 10 of 10 positions probed;
- bare control tail
15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped.
- per-persona line:
- Dogfood pins (in-process HTTP,
--maxWorkers=1), all green:- R1: private-owd 8, rls-fixture 6, owner-anchor-and-bulk-writes 12, static-readonly 4, readonly-when-parent 9, crud-persona-matrix 49, permission-zoo 12, guest-grants-channel 21.
- R2: wall-environment-metadata-refusal 23, wall-catalog-refusal 17, wall-package-doors-refusal 23, anonymous-deny-surfaces 75, public-read-owd 4, invoice-line-contributor-pair 5, controlled-by-parent 4, invoice-cbp 4, plus private-owd 8 and crud-persona-matrix 49 again.
- R3: showcase-expand-crud-gate 10, packaged-activation-ledger-reach 11, packaged-action-disabled-dispatch-live 8 (HTTP + MCP transport + cold boot).
- Engine and unit pins, all green:
- objectql: engine.test + filter-array-lowering 196, readonly strip 55.
- rest: request-schema-gate + data-empty-projection-count-door 21; meta-migrate-stored-walled-refusal 6.
- runtime:
- action-activation-dispatch + data-empty-projection-count 26;
- packages-walled 30, automation-walled 12, meta-walled-catalog 19;
- identity-objects-default-organization pin 4;
- boot-guard 22 + kernel 10.
- plugin-auth ensure-default-organization 57; plugin-security boot refusal 3.
- cli ceremony: 8 files, 179.
- mcp
plugin.test.ts17. It is a plugin unit over a mocked ctx and corroborates only; everyai.mcp-stdio-fail-closedclause was scored on liveos startstdio legs.
- Not run, scored by hand instead:
ui/e2e/live/record-history-display.spec.tsand the Studio F1 live spec need the console dev server on fixed ports (3000/5180) outside the runner ranges.
Derived item verdicts and fixture gaps
approvals.account-app-entry: FAIL. acceptance[3] and acceptance[4] fail; the other 7 clauses pass.access-security.rls-both-sides: PARTIAL. acceptance[5] is blocked{by: dependency, ref: knownGaps[0] / qa(checklist): park the blocked partial-coverage gaps of the 17.7 pre-release runs (#21720, #21721, #21782, #21784) — each gets a fixture recipe, a pin, a re-pointed clause or a recorded knownGap #22017 row 11}, the D11 spot-check. The gap still stands from QA run · priority:P0 (23/23) · c4c515ad · 2026-10-29 · 20 PASS / 3 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27481; the public half holds.access-security.crud-permission-matrix: PARTIAL. acceptance[5] is blocked{by: dependency, ref: security: no door can bind a permission set to theguestanchor — ADR-0138 D3 item 5 has no enforcer (PUT /meta/position/guestanswers 403 NOT_OVERRIDABLE; guest suggestions are refused) #23267}: no door binds a set to the guest anchor. The gap still stands from QA run · priority:P0 (23/23) · c4c515ad · 2026-10-29 · 20 PASS / 3 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27481.cli.organization-ownership-ceremony: PASS (was PARTIAL). The QA run · priority:P0 (23/23) · c4c515ad · 2026-10-29 · 20 PASS / 3 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27481 reset-token gap, parked on [sweep] v18.3.0 release test sweep #27377, is closed by rev 7's recipe step 3, which re-dates the token; the reset answers 200.- Coverage notes on passing items:
- The walled item's install-local leg rests on its pins (knownGaps[1]).
platform-core.nav-surfaces-render's ErrorBoundary fallback is still unexercised.- The marketplace catalog content stays blocked by egress (knownGap).
- The v17 fixture is a blank-scaffold DB, not a showcase DB.
- The walled grant was a recorded fixture write outside HTTP, the item's own documented recipe.
Off-clause probes (RUNNER rule 8)
About 65 runner-minutes in total, after the clauses had verdicts, on the same boots and as the same personas: R1 6, R2 10, R3 9, R4 12, R5 7, R6 9, R7 12.
Doors:
- data CRUD, list, query, by-id, bulk create/update/delete, clone, export, analytics, batch;
/data/:object/:id/page;meta/app(list,?id=, by name),meta/connector,/api/settings/:ns;- sign-in, sign-out and get-session;
- actions and activation; automation toggle, trigger, runs and
_status; - approvals request, actions and approve;
- MCP over HTTP and stdio;
- the datasource admin, test and meta doors;
- the walled
/meta,/packages, catalog and side channels; - packages and publish-drafts;
- the ownership-ceremony arms.
Personas: admin, operator, plain member, contributor, client_liaison, auditor, ops, field_ops_delegate, a non-admin approver, the walled org owner and a non-holder, API keys (admin, member, revoked), anonymous, and a bogus or empty bearer.
Boundary classes:
- empty, whitespace, unknown, encoded and trailing-slash ids and values; repeated parameters;
- forged owner, actor and overrides;
- foreign rows through the bulk doors;
- FLS-hidden predicates;
- unknown nested keys;
- the opposite posture (walled against single);
- the opposite credential (API key against session);
- a wrong plan file, and an already-certified DB.
Findings, each in its own card (listed in the close-out comment):
api-backend.query-contract-matrix· observed beside the clauses: with$skipand no$top,totalis the match count minus the offset.platform-core.builtin-apps-nav-render· observed beside the clauses:meta/app?id=with an empty value serves the unfiltered list.integration-system.datasource-credential-refusal-matrix· observed beside the clauses: the runtime datasource door silently drops a top-levelpasswordthatos compilerefuses.ai.mcp-stdio-fail-closed· observed beside the clauses: MCPaggregate_recordsdrops an aggregation'sfilter.- The approvals extraction also covers a second symptom, seen as admin: no decision actions, and the "Waiting on" chips split per character.
Security findings:
- access-security.rls-both-sides · observed beside the clauses · security finding — detail withheld, reported to PM
- integration-system.datasource-credential-refusal-matrix · observed beside the clauses · security finding — detail withheld, reported to PM
Recorded, not filed:
- An empty
$filter/$orderby/$expand/$searchreads as absent, by design. - An absent
enabledon a toggle reads as true, by design. [tenant-audit]seed warnings print on an isolated boot only.- The
[sharing-rule] share_new_inquiries_with_field_ops expands to NO recipientswarning prints on every boot. - The showcase follow-up flow's notify fails on an unassigned task.
- An unknown view in the URL silently renders the default view, logging only a
console.warn.
Time
- Environment prep: 11 min wall (cold install and full build 04:50Z–05:01Z, including the compile boot and bundle check), plus 61 runner-minutes of per-runner prep: protocol reading, scratch copies, persona minting, the walled boot, the v17 and pre-release DBs, scratch Postgres.
- Testing: 32 min wall (05:01Z–05:33Z), or about 115 runner-minutes of clause work plus 65 of probes, plus 5 for the rule-7 verifier.
- Ratio: about 1 : 2.9 by wall clock (11 to 32 min), and about 1 : 2.6 by agent-minutes (72 to 185).
Checklist-accuracy findings from this run are parked on #27377 as ledger edits for the devx lane; they are not repeated here.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 1, 2026
domain:devx#1 · sunhaolin · session_017xRBcUWM7N73xRVd64cyAE
Close-out for this run (SKILL §5), 2026-11-01T05:41Z.
Extracted: #28546 · approvals.account-app-entry · acceptance[3]
Extracted: #28547 · api-backend.query-contract-matrix · observed beside the clauses
Extracted: #28548 · platform-core.builtin-apps-nav-render · observed beside the clauses
Extracted: #28549 · integration-system.datasource-credential-refusal-matrix · observed beside the clauses
Extracted: #28550 · ai.mcp-stdio-fail-closed · observed beside the clauses
Parked-on: #27377 · access-security.rls-both-sides · acceptance[5] D11 spot-check blocked(dependency), knownGaps[0] — gap unchanged since #27481
Parked-on: #27377 · access-security.crud-permission-matrix · acceptance[5] blocked(dependency, #23267), knownGaps[2] — gap unchanged since #27481
Parked-on: #27377 · checklist-accuracy findings from this run (20 lines, listed on the anchor)
Four-way disposition of every
fail:approvals.account-app-entry· acceptance[3] — product defect. The capability breaks its own contract: the inbox → request page path passed atc4c515adand is a regression from feat(rest,console): one request opens a record page #27713. Extracted as Approvals: a non-admin approver who opens an approval request from the Approvals inbox sees "You don't have access to Approval Request records" instead of the decision panel (regression from #27713) #28546.approvals.account-app-entry· acceptance[4] — product defect, with the same root cause; also covered by Approvals: a non-admin approver who opens an approval request from the Approvals inbox sees "You don't have access to Approval Request records" instead of the decision panel (regression from #27713) #28546. Its routing half holds.No verdict is carried forward: every one of the 23 items was re-judged at
eeec88d1. This record covers the ground of #27481 (c4c515ad). Its supersede line and closure are left to the dispatching PM session.Two security findings (off-clause): detail withheld and reported to PM. No card is filed for them, per the maintainer ruling of 2026-10-29.
Generated by Claude Code
docs(qa): wave-3 checklist accuracy slice S9 — the 20 W3-C1R findings
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbZpHPpovxXPremPLtv
Superseded-by: #28927
The wave-4 P0 run re-judged all 23 items at
7fa9873f, so no verdict of this record is left uncovered (nothing carried forward).approvals.account-app-entrymoved FAIL → PASS there.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
Closed 2026-11-02T07:08Z as superseded per the Superseded-by line above: the wave-4 P0 record #28927 re-judged all 23 items at 7fa9873.
Provenance (closing on the maintainer's instruction): Warren, in the project thread "Plan the release checklist run" at 2026-11-02T07:06Z, answered the pending list that named this close with 「待定全部同意」. The W4-C1 runner session (
session_01JQwxbZpHPpovxXPremPLtv) staged this close; its own close was refused by its session permissions, so the dispatching PM seat session posts it.Generated by Claude Code