Skip to content

QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927

Closed as not planned

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbZpHPpovxXPremPLtv
Part of #27377 (wave 4, W4-C1: the standing priority:P0 smoke for the 18.3.0 release candidate)

This run re-judges every P0 item at the wave-4 subject 7fa9873f. It compares each item against the wave-3 P0 record #28545 (at eeec88d1) and the wave-3 retest #28656 (at 6e11a929).

Result: all 23 runnable items have a verdict: 21 PASS, 2 PARTIAL, 0 FAIL, 0 BLOCKED, 0 NOT-RUN.

Against #28545 (20 PASS / 2 PARTIAL / 1 FAIL), one verdict moved:

Other findings:

Environment fingerprint

  • Framework: 7fa9873f38f7a0158e3ce17338dcc0f446b113e3 (main, 2026-11-02 02:44Z), a detached checkout including ui/. git status was clean before and after the run.
  • Build (cold tree, in this checkout):
    • pnpm install --frozen-lockfile, exit 0 (24 s);
    • pnpm build --concurrency=2 under scripts/pm/os-verify-lock.sh, 117/117 tasks, exit 0, 03:34:39Z–03:47:26Z (12m47s);
    • pnpm console:build --concurrency=2, exit 0: ✓ @objectstack/console dist ready (82304 KB) from ui/apps/console, with the tracked sdui.manifest.json;
    • node scripts/check-dev-prereqs.mjs green (106 artifacts).
  • Stale console bundle, ruled out: the dispatcher boot and every browser runner's boot served /_console/ entry assets/index-DqtqClJh.js, the same file as packages/console/dist/assets; R5 and R6 compared the bytes (sha256 prefix 44a80d196d2562bc), identical.
  • Toolchain: Node 22.23.4, pnpm 10.31.0. Playwright 1.63.0 resolves chromium build 1243, which /opt/pw-browsers holds, so no executablePath override was needed.
  • App: examples/app-showcase.
    • One dispatcher os dev compile boot (port 43001) wrote dist/objectstack.json at 03:47:53Z; every later tree boot used --no-compile --no-watch.
    • Items that compile, install a package, write the external datasource or touch a v17/18.0 DB booted from scratch copies (tar, node_modules symlinked): verify --rls, the datasource matrix, Studio first-run, the MCP os start legs, the dev-boot contract, the ceremony and the boot-refusal legs.
    • After the run examples/app-showcase/.objectstack/ holds only data/ (no installed-packages/).
  • 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 info where an item asks for them.
    • Seed: --seed-admin plus the showcase seed, Seeds: com.example.showcase 132 rows. /api/v1/health reports version 18.2.0, the unreleased line.
  • Ports: 43001 (dispatcher), 43101–43103 (R1), 43201–43205 (R2), 43301–43304 (R3), 43401–43413 (R4), 43501–43504 (R5), 43601–43602 (R6), 43701–43702 + 43719 PostgreSQL (R7). 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 dev with OS_TENANCY_POSTURE=isolated, OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai, OS_AUTH_MEMBERSHIP_POLICY=invite-only. Banner Tenancy: isolated, Organizations mounted, 0 DEGRADED lines; /auth/config multiOrgEnabled true, degradedTenancy false.
  • v17-shaped DB: from npm create-objectstack@17.7.0 (--skip-install --skip-skills, then npm install --legacy-peer-deps, cli/runtime/spec 17.7.0), a blank scaffold booted once by its own os dev: 69 tables, 61 rows. 18.0 pre-release DB: the cli-18-prerelease-db restore (born under @objectstack/cli@18.0.0-next.5), 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 port 43719, scram-sha-256, data dir under /tmp per the item's knownGaps[2].
  • Timestamps (2026-11-02): prep 03:33Z–03:49Z; runners 03:49Z–04:21Z.

Execution

Parallel, per SKILL §2: seven runner subagents (R1–R7), each at effort high on the default tier (dispatch-gates: no path-derived mandate), each with its own port range and file DBs.

  • API and CLI items fanned out (R1–R4).
  • Browser and mixed items ran on three runners (R5, R6, R7), one browser each.
  • Vitest pins ran under the shared heavy-verify lock at --maxWorkers=1.

The dispatcher checked each runner's verdicts against the evidence it returned: pin outputs, HTTP traces, boot logs and response bodies. No P0 fail was recorded, so no rule-7 verifier was owed.

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 #28545 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 12 api R1 PARTIAL PARTIAL
access-security.owd-sharing-matrix 9 api R2 PASS PASS
access-security.anonymous-deny-surfaces 5 api R2 PASS PASS
access-security.walled-environment-metadata-operator-only 8 api R2 PASS PASS
ai.mcp-stdio-fail-closed 9 cli R4 PASS PASS
api-backend.query-contract-matrix 9 api R3 PASS PASS
api-backend.packaged-action-disabled-dispatch 11 api R3 PASS PASS
approvals.account-app-entry 8 browser R6 FAIL PASS
automation.packaged-flow-disable-durable 8 api R3 PASS PASS
cli.dev-boot-contract 9 cli R4 PASS PASS
cli.organization-ownership-ceremony 8 cli R4 PASS PASS
identity-auth.default-organization-boot-invariant 4 api R2 PASS PASS
integration-system.datasource-credential-refusal-matrix 8 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 10 browser R5 PASS PASS
platform-core.builtin-apps-nav-render 12 browser R5 PASS PASS
platform-core.v18-boot-refusals 9 cli R4 PASS PASS
records-forms.crud-roundtrip 17 browser R6 PASS PASS
studio-authoring.first-run-loop 10 mixed R7 PASS PASS

Items whose revision moved since #28545: crud-permission-matrix 11→12, owd-sharing-matrix 8→9, walled 7→8, mcp-stdio 8→9, query-contract-matrix 8→9, packaged-action-disabled-dispatch 10→11, account-app-entry 7→8, ceremony 7→8, datasource matrix 7→8, nav-surfaces-render 8→10, builtin-apps-nav-render 11→12, crud-roundtrip 16→17, first-run-loop 8→10. Each was scored at its current revision, and each runner read the new history entry.

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 and dispatcher-domain 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, members minted by invite + sign-up (sys_member role member, 0 set grants): A's list n=2 both A notes, no B id; B's list n=1 only B. Pin showcase-private-owd green [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 (n=3, then 6); 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 line 21 PROVEN (21 consistent, 0 HOLES) · 3 NOT PROVEN (0 member-visible, 0 probe-blocked, 3 skipped). Total line all personas: 38 PROVEN (38 consistent, 0 HOLES) · 226 NOT PROVEN (131 member-visible, 62 probe-blocked, 33 skipped) [unit: one object × persona probe]. 10 of 10 positions. Adopted-row proof on showcase_account only. Bare-verify control (own invocation) tail 15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped (0 mismatches), 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 skips (project_membership no plain-text probe field; ext_customer / ext_order external read-only); member spot-check project_membership GET/PATCH 403/403, ext_* GET 403 and PATCH 403 EXTERNAL_WRITE_FORBIDDEN, admin re-reads identical
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]–[2] pass procedural: the D11 verdict is carried on acceptance[5] only; the record 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 green [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 ("owner_id … is system-managed"); 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 green
access-security.write-path-guards · acceptance[5] pass live x2: paid invoice PATCH tax_rate:20 → 200, header tax_rate;reason=readonly_when, re-reads 5; line quantity/unit_price/product dropped readonly_when; mixed updateMany: paid line droppedFields quantity readonly_when (re-reads 2), open line lands (7). Pin readonly-when-parent green
access-security.write-path-guards · acceptance[6] pass live x2: continueOnError [3,-1,3] → total 3 / succeeded 2 / failed 1, codes [ok, VALIDATION_FAILED, ok], re-read [3,2,3]; default stop [4,-1,4] → [ok, VALIDATION_FAILED, NOT_ATTEMPTED], re-read [4,2,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): 2 files 55/55
access-security.crud-permission-matrix · acceptance[0] pass live REST sweep x2: 164 showcase_* cells, all 87 effective-allow cells < 300 (max 201) with the effect proven by admin re-read, bad=[]. Pin crud-persona-matrix green [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: admin marker scan after every denied create finds 0 rows
access-security.crud-permission-matrix · acceptance[3] pass live x2: auditor by-id 200 and in both lists on foreign private_note, inquiry, invoice, line; contributor by-id 404 and absent
access-security.crud-permission-matrix · acceptance[4] pass live x2: ops PATCHes admin's announcement → 200, persisted; member_default → 403, unchanged
access-security.crud-permission-matrix · acceptance[5] blocked blocked{by: dependency, ref: #23267} per knownGaps[2]: GET /meta/position/guest 200 with no permissionSets; PUT naming showcase_guest_portal → 403 NOT_OVERRIDABLE, re-read identical; suggested-bindings lists only showcase_member_default@everyone:confirmed; anonymous inquiry POST/GET → 401
access-security.crud-permission-matrix · acceptance[6] pass 45 rows recounted (41 showcase_* + 4 delegate × sys_*); live 164 cells (87/77/9 baseline flips, all 9 2xx) + 16/16 delegate cells. Rev-12 steps driven: POST /data/sys_user_permission_set 201 for all 7 sets x2; POST /data/sys_business_unit_member 201
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, two rounds with fresh personas (get-session proven, isPlatformAdmin false): A POST 201; B list(filter id) n=0, list(all) n=0, GET 404, PATCH 404; A GET/PATCH 200; admin re-read shows A's edit. Pin private-owd 8/8
access-security.owd-sharing-matrix · acceptance[1] pass 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 ops PATCH of admin's announcement 200, re-read edited. Pin crud-persona-matrix 49/49
access-security.owd-sharing-matrix · acceptance[3] pass admin project {name, status:'planned', account} 201 (the rev-9 body); C1 GET 200, PATCH 200 persisted; A's identical PATCH 403, row unchanged
access-security.owd-sharing-matrix · acceptance[4] pass C1 invoice + line 201; C2 excluded (list n=0, GET 404, PATCH 404, quantity unchanged); C1 contains / 200 / 200. Pin invoice-line-contributor-pair 5/5; controlled-by-parent 4/4 and invoice-cbp 4/4 beneath
access-security.owd-sharing-matrix · acceptance[5] pass auditor list(filter id) contains C1's line, by-id GET 200
access-security.owd-sharing-matrix · acceptance[6] pass procedural: all four models driven per persona and verb, two rounds
access-security.owd-sharing-matrix · negative[0]–[1] pass B's direct forged PATCH on the public_read announcement → 403, unchanged; 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 UNAUTHENTICATED. 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 with httpStatus 401 (/actions /automation, analytics x5)
access-security.anonymous-deny-surfaces · acceptance[3] pass anonymous analytics → 401 incl. malformed bodies; member query 200 (count 10), 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, twice
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 7fa9873, maxWorkers=1: rest meta-migrate-stored-walled-refusal 6/6 (unit, vi.fn transport); runtime packages-walled-write-refusal 32/32, automation-walled-definition-write 12/12, meta-walled-catalog-refusal 19/19 (dispatcher-domain units); 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; pre-grant control: the same PUT answered the capability 403 before the grant, the posture 403 after): PUT /meta/object → 403 FORBIDDEN, read-back 404; PUT /meta/permission/showcase_member_default → 403, sha unchanged; view publish → 403; DELETE /packages/com.example.showcase → 403 PERMISSION_DENIED, still installed; set clone → 403, clone 404; _migrate-stored preview and apply → 403 FORBIDDEN; POST /automation → 403, flow absent. Messages name the 'isolated' posture
access-security.walled-environment-metadata-operator-only · acceptance[2] pass walled operator PUT 200 "Saved object 'qa_walled_probe' (env-wide)", 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 clause doors x2 + 22 probe doors; every read-back absent or unchanged
identity-auth.default-organization-boot-invariant · acceptance[0] pass plugin-auth ensure-default-organization 57/57 (plugin unit, fake ql); 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: 04:00:14.830Z INFO [default-org] created the Default Organization before 04:00:18.043Z Dev admin seeded; DB created_at order agrees (org 04:00:14.827Z, first sys_user 04:00:17.833Z)
identity-auth.default-organization-boot-invariant · acceptance[2] pass sys_member: admin owner, created user member; get-session activeOrganizationId = the 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 node:sqlite scan: 106 tables, 64 carry organization_id, 165 rows, 0 NULL / 0 empty; re-scanned after probes, 167 rows, 0 NULL
ai.mcp-stdio-fail-closed · acceptance[0] pass live os start stdio (OS_MCP_STDIO_ENABLED=true), 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)"; health 000 both
ai.mcp-stdio-fail-closed · acceptance[2] pass --log-level info: "[MCP] stdio transport principal-bound to OS_MCP_STDIO_API_KEY identity … (RLS/FLS/tenant applied)", the contributor's user id (liaison boot printed the liaison's)
ai.mcp-stdio-fail-closed · acceptance[3] pass contributor MCP == REST (1 own invoice, identical 19-field set; INV-1003 not found / 404; admin 13 both doors); liaison project rows lack budget/spent/budget_remaining on MCP and REST lists and gets; admin REST 23 fields
ai.mcp-stdio-fail-closed · acceptance[4] pass count by status: member MCP [{draft:1}] == member REST; admin 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; REST same 403; controls equal on both doors
ai.mcp-stdio-fail-closed · acceptance[6] pass same stdio session: pre-revoke 1 row; revoke via admin API key → 403 "requires a signed-in session" (rev-9 note), via admin session → 200; next call isError API_KEY_REVOKED 403, no rows
ai.mcp-stdio-fail-closed · acceptance[7] pass --log-level info, no stdio env, health 200: "[MCP] Transport not auto-started (HTTP is served per-request at /api/v1/mcp regardless)…"
ai.mcp-stdio-fail-closed · negative[0]–[4] pass unset, whitespace, osk_, unknown, revoked and "Bearer osk_…" keys never serve (exit 1, health 000); member 1 vs admin 13; masked aggregates refused; post-revoke API_KEY_REVOKED
api-backend.query-contract-matrix · acceptance[0] pass HTTP live: 38 variant rows × 3 doors (POST $-body, POST AST, GET $filter) = 114 calls, id sets equal to the unfiltered local baseline, 0 diffs; $contains:'ORTH' / $startsWith:'con' case-exact (0); infix compound → POST 400 VALIDATION_FAILED, GET 400 INVALID_FILTER
api-backend.query-contract-matrix · acceptance[1] pass $top=3&$skip=2 = Fabrikam, Globex, Hooli; $top=4&$skip=9 and $top=5&$skip=12 equal the local slices; POST {limit,offset} and {top,skip} identical
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 annual_revenue asc/desc on both doors equal the local order; no_such_field → 400 INVALID_SORT on both
api-backend.query-contract-matrix · acceptance[4] pass contributor (recipe search:qa-contributor-bound-member, get-session proven): contact direct 403; expand via body, $expand, by-id expand → contact stays the raw id, no name/email; admin materialised. Pin showcase-expand-crud-gate green [HTTP]
api-backend.query-contract-matrix · acceptance[5] pass {status:{$nin:'done'}} → 400 VALIDATION_FAILED at query.where.status.$nin; AST → 400 at query.where; 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 ($eq, $ne, AST, GET !=) → 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; $count true (total 14) / false (omitted), $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; control 200
api-backend.query-contract-matrix · negative[1] pass new at rev 9 (#26644): empty $select / select / fields, $select=%20, $select=,, bad $count, by-id ?select= → 400 VALIDATION_ERROR naming the spelling; POST {fields:[]}, {select:""}, {count:"maybe"} → 400 VALIDATION_FAILED; no rows; 4 controls 200. rest pins request-schema-gate + data-empty-projection-count-door 21 green (route-handler layer)
api-backend.packaged-action-disabled-dispatch · acceptance[0] pass flip 200, exactly 1 ledger row (keys without organization_id); mark_done bogus and real id → 409 ACTION_DISABLED "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 POST /api/v1/mcp tools/call run_action showcase_portfolio_snapshot disabled → isError ACTION_DISABLED 409, message string-equal to REST; 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 true, progress 100); same ledger row id
api-backend.packaged-action-disabled-dispatch · acceptance[6] pass showcase_bulk_reassign disabled → 409 ACTION_DISABLED with the turned-off sentence (rev 11); showcase_reassign_wizard no ledger row, 0 runs before and after
api-backend.packaged-action-disabled-dispatch · negative[0]–[2] pass disabled calls never got the param 400 or a record answer; 0 rows = stock answers; the 403 wins; anonymous 401
automation.packaged-flow-disable-durable · acceptance[0] pass baseline urgent create runs 0→1 (completed); toggle off 200; exactly 1 row (flow, active false, no organization_id key); no "IN PROCESS ONLY" log
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 "[Automation] 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 8 s; trigger still 409
automation.packaged-flow-disable-durable · acceptance[4] pass toggle on 200; same row id, active true, updated_at moved; _status bound true; 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 derived from ShowcaseSeedData source (19 datasets / 132 rows); $top=1 totals and full list lengths match 19/19
platform-core.seed-integrity · acceptance[1] pass Specimen — Full: 37/37 fields match; lookups resolve; f_time '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":132,…,"errored":0}; no dropped-record line
platform-core.seed-integrity · acceptance[3] pass restart over the same DB: identical sweep; {"inserted":0,"updated":0,"skipped":132,"errored":0}
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 17 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: / OS_DATABASE_URL / :memory: / nothing chosen → .objectstack/data/objectstack.db / config qa_home (no objectstack.db) / legacy dev.db with notice
cli.dev-boot-contract · acceptance[3] pass "🧪 Fresh OS_HOME: /tmp/objectstack-dev-…"; SIGINT EXIT=130 and SIGTERM EXIT=143, tempdir gone both times
cli.dev-boot-contract · acceptance[4] pass "⚠ Port 43407 is in use — serving on 43408 instead." + "↪ server bound to port 43408 (requested 43407)"; health 200
cli.dev-boot-contract · acceptance[5] pass --no-compile after a source touch: "⚠ dist/objectstack.json is OLDER than your sources …", no compile, 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" at /_console/login; served entry equals dist; form sign-in reaches /_console/home, get-session 200
cli.dev-boot-contract · negative[0]–[3] pass marker survives reboot; --database-driver memory exit 2 with INVOCATION ERROR, OS_DATABASE_DRIVER=memory/mingo/in-memory and memory:// / mingo:// exit 1 naming --fresh and :memory:; legacy read creates no objectstack.db; shifted port reported
cli.organization-ownership-ceremony · acceptance[0] pass unit/integration over SQLite, no HTTP: cli 8 ceremony 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", primary sha and telemetry rows unchanged; --apply without plan 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 == ORGANIZATION_OWNERSHIP_SHAPE_GENERATION
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", health 200
cli.organization-ownership-ceremony · acceptance[4] pass raw v17 copy: reactions conversion refused without --yes, exit 0 twice with it; migrate apply --allow-destructive --yes exit 1 refused_organization_ownership_unmigrated, sha unchanged, row diff 0
cli.organization-ownership-ceremony · acceptance[5] pass cli-18-prerelease-db restore, all --dev: boot 1 refused (row diff 0); plan exit 0; apply complete / blocking 0 (sibling-moves 10 / jobs 2 / activity 14, column-drops 2, not-null 66); boot 2 ready; moved identity mails 0 diffs, 8 audit rows moved, 2 mail jobs re-pointed; 3 sign-ins 200 / wrong password 401; reset with the moved mail's token → 200; 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 authz-identity-objects-boot-refusal 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; 0 hits "17.x release"; --dev copy spells --dev
platform-core.v18-boot-refusals · acceptance[2] pass row diff: production copy 69 tables / 61 rows 0 differences, 53 created tables empty; dev copy 0 differences, telemetry sibling unchanged
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}, 37.6 s from pnpm launch on a loaded shared box
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 boot window captured to its own file: Flows: 32 flow(s) 19 bound … · 8 draft; two ℹ deployment-policy lines; 0 ⚠, 0 ERROR
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 59 authored nav ids vs 59 served: diff empty; grp_data 12 objects
platform-core.boot-health · acceptance[5] pass /_console/ 200 text/html, entry index-DqtqClJh.js (byte-identical to dist)
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; cookie and localStorage token both set
platform-core.console-login · acceptance[1] pass reload stays on /home; get-session, discovery, i18n, meta/app 200
platform-core.console-login · acceptance[2] pass sign-out 200; same bearer: meta/app, get-session, data → 401 UNAUTHENTICATED (both runs)
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 showcase_task (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; 0 page errors
platform-core.nav-surfaces-render · acceptance[0] pass browser over live HTTP (port 43503): examples/app-showcase/e2e/showcase-smoke.spec.ts 50 passed, 0 failed (2.1 min), incl. the new /reports entry
platform-core.nav-surfaces-render · acceptance[1] pass 51 served leaves = 50 + nav_sep_reports separator (25 page / 17 object / 5 report / 3 dashboard) vs 50 SURFACES: diff empty, nothing hand-walked (rev 10)
platform-core.nav-surfaces-render · acceptance[2] pass bad route on 2 fresh contexts: shell alive, "Object Not Found — The object …", 0 page errors
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 50; 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 47/47, Account 8/8, 0 pageerror; only "failed to load" is the knownGap marketplace (wire 502 MARKETPLACE_PROXY_FAILED); 11 settings namespaces render
platform-core.builtin-apps-nav-render · acceptance[1] pass setup: requiredPermissions [setup.access], 9 groups, 47 leaves = source minus gated organizations / sso_providers; account 8 leaves / 3 groups; ?id=studio 200 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 PERMISSION_DENIED; 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 meta and data 200
platform-core.builtin-apps-nav-render · acceptance[6] pass no jwks / sso / verification / device_code entries; auth config sso false; data/sys_jwks 404 even for admin
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 7fa9873 printed ✓ @objectstack/console dist ready (82304 KB) from ui/apps/console; the served entry (byte-identical to dist) registers approvals:inbox
approvals.account-app-entry · acceptance[1] pass avatar › Profile › Inbox › Approvals → /_console/apps/com.objectstack.account/component/approvals/inbox; screenshot: My Pending 4 / Submitted by me / All, 4 Pending rows
approvals.account-app-entry · acceptance[2] pass non-admin X (invite + sign-up, positions contributor + finance, isPlatformAdmin false) GET /meta/app → [showcase_app, account] with nav_account_approvals; ?id=setup empty, GET /meta/app/setup 403
approvals.account-app-entry · acceptance[3] pass row click → …/sys_approval_request/record/AREQ renders the decision panel (Approve, Reject, Reassign, Send back, Request info, Send reminder, Recall, Reply); Approve → Confirm → POST /api/v1/actions/sys_approval_request/approval_approve 200; GET /approvals/requests/AREQ got 0/2 → 1/2, X leaves pending, can_act false; /actions gains the approve row; reproduced on a 2nd request on a fresh load. As X also: reject 200 (status rejected, invoice back to draft), request_info 200, comment 200
approvals.account-app-entry · acceptance[4] pass cold load …/component/approvals/inbox?request=AREQ replaces itself with that request's record page showing the decision panel (history.back() skips it); alias /apps/account/…?request= lands the same
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]–[1] pass full inbox rendered from the nav entry, no missing-component state; Approvals present for the persona, setup absent
records-forms.crud-roundtrip · acceptance[0] pass UI Create → POST showcase_account {industry:'retail',status:'active',sales_region:'amer',name:'os-qa-r6w4'} 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-r6w4"? → 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 after a reload, Activity tab (?related=timeline, 1440×900), Changes: Annual Revenue — → $4,321,000.00 · Dev Admin; create line lists owner, name, industry, lifecycle, region; sys_audit_log exactly create + update, no phantom rows. Driven by hand (the live spec needs ports 3000/5180)
records-forms.crud-roundtrip · acceptance[5] pass UI create os-qa-r6w4-华宁 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 three times; admin count 13→13; own-row clone control 201
records-forms.crud-roundtrip · negative[0] pass empty Account Name: inline "Account Name is required", dialog stays, no POST, 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 build door (os compile, scratch copy): 22 probes exit 2 at their paths (pg/mysql/mongodb password, turso authToken, passwd alias, URL userinfo incl. turso syncUrl, ?password= / ?authToken=, mongodb options.auth.password, nested pool.token, placeholder host, mongo credentialsRef without user, unparseable url, turso encryptionKey remote/local, top-level password, connector authentication / auth.token); each names external.credentialsRef (connectors credentialRef) and the env-route sentence; controls exit 0. Runtime: POST /api/v1/datasources 400 DATASOURCE_ADMIN_ERROR on all 20 datasource doors; PUT /meta/connector 422 on both connector doors
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 + 11), meta (list + 11) and /data/sys_metadata?type=datasource: only cleartext hit is the ruled apiSecret; admin and meta config identical
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 7 rows planted with the server stopped (passwd/pwd, token/jwt/auth_token/authtoken, turso encryptionKey, mysql password, pg userinfo, pg ?password=, mongodb options.auth.password + pool.jwt): all listed after reboot, each key in redactedConfigKeys, 0 planted values on any door or log
integration-system.datasource-credential-refusal-matrix · acceptance[5] pass unknown driver acme-plugin-db 201 (ruled boundary); password, authToken, passwd, userinfo withheld; apiSecret served as ruled
integration-system.datasource-credential-refusal-matrix · acceptance[6] pass echoed PATCH {config} 200; PUT 405 Allow: DELETE, GET, HEAD, PATCH; /test still ok, credentialsRef unchanged; echoed PATCH kept the withheld keys
integration-system.datasource-credential-refusal-matrix · acceptance[7] pass auditor.demo and phone.demo (get-session proven) 403 PERMISSION_DENIED on all 25 read URLs; anonymous 401
integration-system.datasource-credential-refusal-matrix · negative[0]–[6] pass no cleartext, no two-door disagreement incl. the update door (PATCH with password / userinfo / top-level password → 400), consistent redaction, all aliases redacted, plugin canonical keys withheld, mask literal in 0 bodies, every refusal names its replacement
studio-authoring.first-run-loop · acceptance[0] pass by hand (F1 live spec not run: it needs a console origin and writes ui/e2e/live/.auth into the shared tree): Home chip "New in Studio" → New package 维修中心 / com.example.repairs; POST /api/v1/packages 201; switcher "Writable"; no reload (in-page marker survived)
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 {name:"Broken pump",status:"wip"} 201; GET /data/repairs_repair_ticket total 1, status wip
studio-authoring.first-run-loop · acceptance[3] pass /meta/app includes repair_center with nav_repairs_repair_ticket; screenshots: Home "Repair Center" tile; 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 04:00:15Z–04:09Z
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; app into showcase → 422; nothing landed
studio-authoring.first-run-loop · negative[0]–[1] pass no silent acceptance; the label chip renders

Reproduction rules for fails

None: this run recorded no fail.

Pins and the Playwright smoke

  • Playwright smoke: examples/app-showcase/e2e/showcase-smoke.spec.ts gave 50 passed, 0 failed (2.1 min) against a live boot on port 43503, from a scratch copy (webServer reused the boot).
  • objectstack verify --rls and bare verify, separate invocations on a scratch copy: 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; bare tail 15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped.
  • Dogfood pins (in-process HTTP, --maxWorkers=1, under the lock), all green:
    • R1: private-owd, rls-fixture, owner-anchor-and-bulk-writes, static-readonly, readonly-when-parent, crud-persona-matrix, permission-zoo, guest-grants-channel: 8 files 121/121.
    • R2: private-owd 8, public-read-owd 4, invoice-line-contributor-pair 5, crud-persona-matrix 49, controlled-by-parent 4, invoice-cbp 4, anonymous-deny-surfaces 75, wall-environment-metadata-refusal 23, wall-catalog-refusal 17, wall-package-doors-refusal 23: 212/212 (twice).
    • R3: showcase-expand-crud-gate, packaged-activation-ledger-reach, packaged-action-disabled-dispatch-live: 29/29.
  • 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 32, automation-walled 12, meta-walled-catalog 19; identity-objects-default-organization pin 4; boot-guard 22 + kernel 10.
    • service-automation flow-activation-ledger 49 (corroboration; the flow item carries no automated).
    • plugin-auth ensure-default-organization 57; plugin-security boot refusal 3.
    • cli ceremony: 8 files 179 (+ unified-db-resolution.pin 7, corroborating).
    • mcp plugin.test.ts 17: plugin unit over a mocked ctx, corroborates only; every ai.mcp-stdio-fail-closed clause was scored on live os start stdio legs.
    • approvals: a non-admin approver's decision from the request page answers 404 RECORD_NOT_FOUND — the action door loads sys_approval_request in the caller's data scope #28657 fix pins, corroboration only: runtime api-action-forward 68; verify action-door-api-forward-denied-subject 3 (HTTP, booted stack).
  • Not run, scored by hand instead: ui/e2e/live/record-history-display.spec.ts and the Studio F1 live spec need the console dev server on fixed ports (3000/5180) or write into the shared tree.

Derived item verdicts and fixture gaps

Retest of earlier QA cards met in passing

Observed on this run's boots as off-clause controls; they are not clause verdicts.

Off-clause probes (RUNNER rule 8)

About 48 runner-minutes in total, after the clauses had verdicts, on the same boots and as the same personas: R1 5, R2 8, R3 5, R4 7, R5 8, R6 9, R7 6.

Doors:

  • data CRUD, list, query, by-id, bulk create/update/delete, clone, export, search, analytics, batch;
  • sys_user_permission_set, sys_business_unit_member, sys_user_position, sys_metadata, sys_secret;
  • meta/app (list, ?id= variants, by name), /api/settings/:ns, /meta writes on the walled boot;
  • sign-in, sign-out, get-session, set-active, organization create;
  • actions and activation, MCP run_action / query_records / get_record / aggregate_records over HTTP and stdio; automation toggle, trigger, runs and _status;
  • approvals request, actions and decisions through the action door and the approvals routes;
  • the datasource admin, test, remote-tables and meta doors; packages, metadata draft PUT and publish-drafts;
  • os start stdio admission, the ceremony arms, the os serve boot guard, os dev flag parsing; console bad routes.

Personas: admin, walled operator, walled org owner and a non-holder, plain member, contributor, client_liaison, auditor, ops, field_ops_delegate, a non-admin approver and a non-participant, demo personas auditor.demo and phone.demo, API keys (admin, contributor, liaison, revoked), anonymous, and a bogus or empty bearer.

Boundary classes:

  • empty, whitespace, unknown, encoded and trailing-slash ids and values; repeated and bracketed (id[]) parameters;
  • forged owner, id, credentialsRef and overrides; self-escalation of grants and positions;
  • foreign rows through the bulk doors; FLS-hidden predicates in where, orderBy and aggregation filters;
  • the opposite posture (walled against single) and the opposite credential (API key against session);
  • an empty or null secret; a missing recordId; a missing flag value;
  • a wrong or missing plan file, no backup flag, an already-certified DB, a planted-shape DB.

Findings, each in its own card (listed in the close-out comment):

  • integration-system.datasource-credential-refusal-matrix · observed beside the clauses: PATCH /api/v1/datasources/:name {"secret":""} replaces the stored credential with an empty secret, and the status reason then misreports the cause.
  • platform-core.builtin-apps-nav-render · observed beside the clauses: meta/app?id[]=setup (bracketed array spelling) ignores the filter and serves the caller's unfiltered app list.
  • cli.dev-boot-contract · observed beside the clauses: a flag missing its value (os dev -d) exits 2 without the INVOCATION ERROR banner.
  • approvals.account-app-entry · observed beside the clauses: an api action called with no recordId answers 404 ENDPOINT_NOT_FOUND instead of naming the missing record id.
  • access-security.write-path-guards · observed beside the clauses: the clone and createMany doors report a readonly strip in the body's droppedFields but send no X-ObjectStack-Dropped-Fields header.

Security findings:

  • approvals.account-app-entry · observed beside the clauses · security finding — detail withheld, reported to PM

Recorded, not filed:

  • showcase_portfolio_snapshot answers a plain member invoices: 12 over REST and MCP: action bodies run elevated by design (buildActionExecutionContext), so this is the specimen app disclosing an aggregate, not a platform hole.
  • GET /automation/_status lists every flow's name and binding state to a plain member, who can read /meta anyway.
  • The enabled refusal for null / 0 on the toggle door says "not a string".
  • A member gets 404 UNKNOWN_NAMESPACE for an unregistered settings namespace and 403 for a registered one; the names are public in the manifests.
  • PUT /meta/object/X?mode=draft&package= (empty) saves an env-wide draft; an unknown package is refused 422.
  • An unprefixed object draft is accepted at draft time and refused at publish, which blocks the package's later publishes until it is removed.
  • A clone re-applies a current_user default to a field that was null on the source.
  • The [sharing-rule] share_new_inquiries_with_field_ops expands to NO recipients warning prints on every boot (as at QA run · priority:P0 (23/23) · eeec88d1 · 2026-11-01 · 20 PASS / 2 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #28545).
  • An unknown view in the URL silently renders the default view (as at QA run · priority:P0 (23/23) · eeec88d1 · 2026-11-01 · 20 PASS / 2 PARTIAL / 1 FAIL / 0 BLOCKED / 0 NOT-RUN #28545).

Time

  • Environment prep: 16 min wall (03:33Z–03:49Z: protocol reading, install, full build 12m47s, console build, compile boot and bundle check), plus about 46 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 (03:49Z–04:21Z), or about 71 runner-minutes of clause work plus 48 of probes.
  • Ratio: about 1 : 2 by wall clock (16 to 32 min), and about 1 : 1.9 by agent-minutes (62 to 119).

Checklist-accuracy findings from this run are reported to #27377 for the devx lane; they are not repeated here.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-warren · session_01JQwxbZpHPpovxXPremPLtv

    Close-out (W4-C1)

    No clause fail this run, so no FAIL disposition is owed. Off-clause probe findings, each extracted as its own card:

    Extracted: #28928 · integration-system.datasource-credential-refusal-matrix · observed beside the clauses
    Extracted: #28930 · platform-core.builtin-apps-nav-render · observed beside the clauses
    Extracted: #28931 · cli.dev-boot-contract · observed beside the clauses
    Extracted: #28932 · approvals.account-app-entry · observed beside the clauses
    Extracted: #28933 · access-security.write-path-guards · observed beside the clauses
    Parked-on: #27377 · access-security.rls-both-sides acceptance[5] D11 spot-check (knownGaps[0], #22017 row 11), unchanged
    Parked-on: #27377 · access-security.crud-permission-matrix acceptance[5] guest anchor (#23267), unchanged

    This record re-judges all 23 items of #28545, so nothing is carried forward from it.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#1 · os-warren · session_01JQwxbWT669ynWFKZjqFyNF

    Superseded-by: #29877

    The wave-5 P0 run re-judged all 23 items at 589049b0 (2026-11-03T09:29Z), so no verdict of this record is left uncovered (nothing carried forward). records-forms.crud-roundtrip moved PASS → FAIL there (acceptance[4], extracted as #29878). Your five probe cards (#28928, #28930, #28931, #28932, #28933) were re-checked there and none reproduces.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions