Repository navigation
Description
domain:devx#1 · os-warren · session_01JQwxbWT669ynWFKZjqFyNF
Part of #27377 (18.3.0 pre-cut re-check, wave 5, card W5-P0: the standing priority:P0 smoke at the wave-5 subject)
This run re-judges every P0 item at the wave-5 subject 589049b0, 463 commits after the wave-4 subject 7fa9873f, and compares each item with the wave-4 P0 record #28927.
Result: all 23 runnable items have a verdict: 20 PASS, 2 PARTIAL, 1 FAIL, 0 BLOCKED, 0 NOT-RUN.
Against #28927 (21 PASS / 2 PARTIAL / 0 FAIL), one verdict moved:
records-forms.crud-roundtripwent PASS → FAIL on acceptance[4]. On a packaged app's record page the Changes chip no longer shows the record's field-change history: the page request sendstimeline.fieldChanges:falseand never readssys_audit_log. Cause: a932270 (perf(app-shell): a packaged app's record route reads the objects pointing at the record through its package scope, not the registry #29846, merged 2026-11-03 07:40Z), which narrowed a packaged app's record route to its package scope, sosys_audit_logis no longer in the listRecordDetailView'shistoryEnabledreads. A second, independent agent re-derived the FAIL from a fresh boot (RUNNER rule 7) and agrees; the pin the clause cites,ui/e2e/live/record-history-display.spec.ts, fails the same way at this subject. Product defect, extracted (close-out comment).- The two PARTIALs are the same standing
blocked(dependency)clauses as at QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927:access-security.rls-both-sidesacceptance[5] (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) andaccess-security.crud-permission-matrixacceptance[5] (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). approvals.account-app-entrywas judged live in full again: PASS holds (non-admin approver, every decision server-side, non-participant refused on every door).
Today's breaking tightenings (clause that reached each):
- fix(plugin-security): a write refused for a caller who cannot read the object answers the same for a hidden row and a missing one #29845 (plugin-security, a write refused to a caller who cannot read the object answers the same for a hidden and a missing row): reached beside
access-security.crud-permission-matrixacceptance[1]. Its own cells sit in the unchanged arm and pass; the changed arm was driven off-clause onsys_user_permission_set/sys_user_position/showcase_contact/showcase_client_briefas member, contributor and delegate: existing and missing ids answer the identical 403, with and withoutIf-Match. Pinsupdate-by-id-refusal-order19/19 [HTTP] andby-id-write-unreadable-not-found23/23 [plugin unit]. - fix(rest,runtime)!: seeing a datasource's remote structure needs the read capability on every route, writes included #29812 (rest/runtime, a datasource's remote structure needs the read capability on every route): reached beside
integration-system.datasource-credential-refusal-matrixacceptance[1] and [7]. Amanage_metadata-only persona is refused 403 namingmanage_platform_settingson all 10 remote-structure routes, writes included (external/tables,…/draft,…/import,refresh-catalog,validate,remote-tables,test,object-draft,datasources/test,meta/external_catalog); amanage_platform_settings-only persona reads them and is refused the two writes namingmanage_metadata. - fix(plugin-sharing)!: a failed business-unit head or standalone manager read refuses instead of answering nobody #29787 / fix(plugin-sharing)!: a failed team-graph manager read refuses instead of answering no manager #29836 (plugin-sharing, a failed manager / business-unit head read refuses): not reached. No P0 clause performs a failed head or manager read; the only sharing expansions seen (
verify --rls, the boot'sshare_new_inquiries_with_field_ops) completed or expanded empty without a failed read.
Other findings: the off-clause probes produced four product cards and re-checked the five wave-4 probe cards, all of which no longer reproduce (below). No security finding.
Environment fingerprint
- Framework:
589049b023d82c94508bf9fce752ea19069279e5(main, merge of fix(metadata-protocol)!: an object saved back from a translated /meta read stores its source labels, and one the registry would refuse is refused at save and at publish #29790), a detached checkout includingui/.git statuswas clean before and after the run. - CI on the subject: push run 41600797636 re-read after testing:
completed, conclusionsuccess(every battery job and every shard). - Build (cold tree, in this checkout):
pnpm install --frozen-lockfile, exit 0 (27 s);pnpm exec turbo run build --concurrency=2, 119/119 tasks, exit 0, 15m04s (08:25:26Z–08:40:59Z);pnpm console:build --concurrency=2, exit 0:✓ @objectstack/console dist ready (83252 KB) from ui/apps/console, with the tracked sdui.manifest.json;node scripts/check-dev-prereqs.mjsgreen (106 artifacts).
- Stale console bundle, ruled out: every boot served
/_console/entryassets/index-DxniAR88.js, the same file aspackages/console/dist/assets; R5 and R6 compared the bytes withcmp, identical. The FAIL was also reproduced against the console from source through vite. - Toolchain: Node 22.23.4, pnpm 10.31.0. Playwright 1.63.0 resolves chromium build 1243, which
/opt/pw-browsersholds. - App:
examples/app-showcase. One dispatcher compile boot (port 44001) wrotedist/objectstack.jsonat 08:41Z; every later boot used--no-compile --no-watch(its mtime was unchanged at the end). Items that install, compile, write the external datasource, runverify --rls,os startor the ceremony, or touch a v17 / 18.0 pre-release DB booted from scratch copies (tar,node_modulessymlinked). After the runexamples/app-showcase/.objectstack/holds onlydata/(noinstalled-packages/). - Boot line:
OS_PORT=PORT OS_STORAGE_LOCAL_ROOT=RUN/uploads OS_HOME=RUN/home setsid pnpm -C … exec objectstack dev --ui --seed-admin --no-compile --no-watch -p PORT -d file:RUN/ITEM.db, with--log-level infowhere an item asks. Seed:Seeds: com.example.showcase 132 rows./api/v1/healthreports version 18.2.0, the unreleased line. - Ports: 44001 (dispatcher), 44101–44103 (R1), 44201–44203 (R2), 44301–44304 (R3), 44401–44419 (R4), 44501–44502 (R5), 44601–44602 (R6), 44701–44709 + 44719 PostgreSQL (R7), 44801–44803 (verifier). Each item ran on its own file DB. Every server was stopped by process group; every port was empty at the end.
- Walled leg:
os devwithOS_TENANCY_POSTURE=isolated,OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai,OS_AUTH_MEMBERSHIP_POLICY=invite-only: bannerTenancy: isolated,Organizationsmounted, no DEGRADED;/auth/configmultiOrgEnabled true, degradedTenancy false. - v17-shaped DB: npm
create-objectstack@17.7.0(--skip-install --skip-skills,npm install --legacy-peer-deps, cli/runtime 17.7.0), booted once by its ownos dev: 69 tables, 61 rows. 18.0 pre-release DB: thecli-18-prerelease-dbrestore (born under@objectstack/cli@18.0.0-next.5). Only copies were used, with a checksum or row diff around every step. - Scratch PostgreSQL 16: 127.0.0.1:44719, scram-sha-256, data dir under
/tmpper the item's knownGaps[2]. - Timestamps (2026-11-03): prep 08:25Z–08:42Z; runners 08:42Z–09:17Z; rule-7 verifier 09:09Z–09:17Z.
Execution
Parallel, per SKILL §2: seven runner subagents (R1–R7) plus one rule-7 verifier, each at effort high on the default tier (dispatch-gates --tier: 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 on R5, R6, R7, one browser each. Vitest pins ran under scripts/pm/os-verify-lock.sh at --maxWorkers=1. The dispatcher checked each runner's verdicts against the evidence it returned.
Scope: selector priority:P0, 23 runnable items
checklist-select.mjs priority:P0 reported 23 runnable items and 1 blocked item, hidden: access-security.no-active-org-session-semantics. No item is planned. Every revision at the subject equals the one in the wave-5 items file.
| item | revision | surface | runner | #28927 | 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 | 13 | api | R3 | PASS (r11) | PASS |
| approvals.account-app-entry | 8 | browser | R6 | PASS | PASS |
| automation.packaged-flow-disable-durable | 10 | api | R3 | PASS (r8) | 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 | FAIL |
| studio-authoring.first-run-loop | 11 | mixed | R7 | PASS (r10) | PASS |
Revisions moved since #28927: packaged-action-disabled-dispatch 11→13 (remedy sentence now names Setup › Packaged Actions; measured verbatim), packaged-flow-disable-durable 8→10 (refusal now points to the package's Automations in Studio; measured verbatim), first-run-loop 10→11 (both locale legs on-clause; the zh-CN leg now passes, see accuracy notes).
Per-clause verdicts
Layer note (RUNNER rule 6): 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. "live x2" = reproduced twice.
| item · clause | verdict | text oracle evidence |
|---|---|---|
| access-security.rls-both-sides · acceptance[0] | pass | live x2, members by invite + sign-up (sys_member member, 0 set grants): A's list n=2 both A, no B id; B n=1 only B. Pin showcase-private-owd 8/8 [HTTP] |
| access-security.rls-both-sides · acceptance[1] | pass | live x2: A GET /data/showcase_private_note/B_ID → 404 RECORD_NOT_FOUND, 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, same as unknown id; admin re-read identical (body, title, updated_at, owner_id) |
| access-security.rls-both-sides · acceptance[3] | pass | live x2: admin list holds every id the run created (3, then 6) |
| access-security.rls-both-sides · acceptance[4] | pass | objectstack verify --rls (scratch copy) x2 exit 0. 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. Bare-verify control 15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 8 skipped, no PROVEN line |
| access-security.rls-both-sides · acceptance[5] | blocked | {by: dependency, ref: knownGaps[0] / #22017 row 11}; public half holds x2: 3 benign skips; member spot-check project_membership 403/403/403, ext_* GET 403 / PATCH 403 EXTERNAL_WRITE_FORBIDDEN |
| access-security.rls-both-sides · negative[0]–[2] | pass | forged PATCH 404, re-read unchanged (x2 + pin); D11 verdict carried on acceptance[5] only |
| access-security.write-path-guards · acceptance[0] | pass | live x2: POST showcase_contact {lead_score:10} → 201, header X-ObjectStack-Dropped-Fields: lead_score;reason=readonly, body droppedFields, read-back null. Pin static-readonly 9/9 [HTTP] |
| access-security.write-path-guards · acceptance[1] | pass | live x2: PATCH {lead_score:99} → 200 with the same header; null before and after |
| access-security.write-path-guards · acceptance[2] | pass | live x2 member: POST note {owner_id:Bob} → 403 PERMISSION_DENIED (system-managed, needs transfer grant); 0 planted rows |
| access-security.write-path-guards · acceptance[3] | pass | live x2: self insert 201 owner Alice; PATCH owner_id=Bob and =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 [HTTP] |
| access-security.write-path-guards · acceptance[5] | pass | live x2: paid invoice PATCH tax_rate → 200, header tax_rate;reason=readonly_when, value unchanged; line qty/unit_price/product all readonly_when, unchanged; mixed updateMany: paid row droppedFields, open row moved 2→5. Pin readonly-when-parent 9/9 |
| access-security.write-path-guards · acceptance[6] | pass | live x2: continueOnError [3,-1,3] → 3/2/1, codes [ok, VALIDATION_FAILED, ok], re-read [3,2,3]; default stop → [ok, VALIDATION_FAILED, NOT_ATTEMPTED], re-read [4,2,2] |
| access-security.write-path-guards · negative[0] | pass | live x2 admin: forge-insert 201 owner Bob; transfer 200; disown 200 |
| access-security.write-path-guards · negative[1] | pass | engine layer: engine-insert-static-readonly-strip + engine-readonly-strip-caller-values 55/55 |
| access-security.crud-permission-matrix · acceptance[0] | pass | live REST sweep x2: all 87 allow cells of 164 answered <300, effect proven by admin re-read; pin crud-persona-matrix 49/49 [HTTP] |
| access-security.crud-permission-matrix · acceptance[1] | pass | live x2: all 77 deny cells → 403 PERMISSION_DENIED; delegate sys_user create/delete 405 with admin control 405/405. #29845 arm driven beside it (see top) |
| access-security.crud-permission-matrix · acceptance[2] | pass | live x2: admin marker scan after each of 17 denied creates → 0 rows |
| access-security.crud-permission-matrix · acceptance[3] | pass | live x2: auditor reads foreign note/inquiry/invoice/line 200 (by id and lists); contributor 404 by id, absent from lists |
| access-security.crud-permission-matrix · acceptance[4] | pass | live x2: ops PATCH admin's announcement 200, persisted; member_default 403, unchanged |
| access-security.crud-permission-matrix · acceptance[5] | blocked | {by: dependency, ref: #23267}: PUT /meta/position/guest naming showcase_guest_portal → 403 NOT_OVERRIDABLE; suggested-bindings lists only showcase_member_default@everyone; anonymous 401/401 |
| access-security.crud-permission-matrix · acceptance[6] | pass | 45 rows recounted; 164 cells + 16/16 delegate cells x2; rev-12 grant steps POST /data/sys_user_permission_set 201 ×7, sys_business_unit_member 201, delegate sys_user_position 201/200/200/200 |
| access-security.crud-permission-matrix · negative[0]–[1] | pass | first denied cell of each of 8 sets as admin → 2xx; 0 withheld cells answered 2xx |
| access-security.owd-sharing-matrix · acceptance[0] | pass | live x2: B list 0 rows, GET 404, PATCH 404, admin re-read "orig"; A GET 200, PATCH 200 persisted. Pin showcase-private-owd [HTTP] |
| access-security.owd-sharing-matrix · acceptance[1] | pass | live x2: B lists and GETs the announcement 200; forged PATCH 403 PERMISSION_DENIED, unchanged. Pin public-read-owd |
| access-security.owd-sharing-matrix · acceptance[2] | pass | live x2: ops PATCH 200, persisted. Pin crud-persona-matrix |
| access-security.owd-sharing-matrix · acceptance[3] | pass | live x2: project created with rev-9 body 201; contributor GET 200, PATCH 200 persisted; A's PATCH 403, unchanged |
| access-security.owd-sharing-matrix · acceptance[4] | pass | live x2: C1 invoice + line 201; C2 list 0 / GET 404 / PATCH 404, re-read unchanged; C1 200/200 (qty 1→2). Pins invoice-line-contributor-pair, controlled-by-parent, invoice-cbp |
| access-security.owd-sharing-matrix · acceptance[5] | pass | live x2: auditor lists and GETs C1's line 200 |
| access-security.owd-sharing-matrix · acceptance[6] | pass | procedural: all four models per persona and verb, two rounds |
| access-security.owd-sharing-matrix · negative[0]–[1] | pass | forged PATCH 403 unchanged x2; C1 controls contained/200/200 |
| access-security.anonymous-deny-surfaces · acceptance[0] | pass | live x2, no header or cookie: 401 from data, meta, actions, automation/_status, batch, security/explain, analytics query/sql/meta. Pin showcase-anonymous-deny-surfaces [HTTP] |
| access-security.anonymous-deny-surfaces · acceptance[1] | pass | live x2: anonymous POST /actions/showcase_task/showcase_mark_done/anon-probe-id → 401; member → 404 RECORD_NOT_FOUND |
| access-security.anonymous-deny-surfaces · acceptance[2] | pass | each body in exactly one family (pin predicates): rest-flat data/meta/batch/explain; dispatcher-wrapper actions/automation/analytics |
| access-security.anonymous-deny-surfaces · acceptance[3] | pass | live x2: anonymous analytics 401 incl. malformed; member query 200, sql 200, meta 200, malformed 400 VALIDATION_FAILED |
| access-security.anonymous-deny-surfaces · acceptance[4] | pass | live x2: member GET /data/showcase_private_note 200, GET /meta 200 |
| access-security.anonymous-deny-surfaces · acceptance[5] | pass | live x2: anonymous GET /api/v1/forms/contact-us → 200 serving showcase_inquiry |
| access-security.anonymous-deny-surfaces · acceptance[6] | pass | procedural: 7 families live, twice |
| access-security.anonymous-deny-surfaces · negative[0] | pass | live x2: anonymous DELETE /automation/showcase_reassign_wizard → 401; admin GET after → 200 |
| access-security.walled-environment-metadata-operator-only · acceptance[0] | pass | pins under the lock: rest meta-migrate-stored-walled-refusal 6/6 (unit); runtime packages-walled-write-refusal 32/32, automation-walled-definition-write 12/12, meta-walled-catalog-refusal 19/19 (dispatcher-domain); dogfood wall-* three files in a 10-file run 212/212 [HTTP] |
| access-security.walled-environment-metadata-operator-only · acceptance[1] | pass | live x2 isolated boot, org owner O (not platform admin, holds manage_metadata; pre-grant control answered the capability 403, post-grant the posture 403): object PUT 403 (read-back 404), permission PUT 403, view publish 403, package DELETE 403, set clone 403, _migrate-stored 403 ×2, POST /automation 403 (then 404); every message names the isolated posture |
| access-security.walled-environment-metadata-operator-only · acceptance[2] | pass | walled operator PUT/read/DELETE/read 200/200/200/404 x2; single admin same x2 |
| access-security.walled-environment-metadata-operator-only · negative[0] | pass | no org-owner environment-metadata write landed: 7 clause doors x2 + 12 probe doors, read-backs absent or unchanged |
| identity-auth.default-organization-boot-invariant · acceptance[0] | pass | plugin-auth ensure-default-organization 57/57 (plugin unit); runtime identity-objects-default-organization.pin 4/4 (engine) |
| identity-auth.default-organization-boot-invariant · acceptance[1] | pass | --log-level info: [default-org] created the Default Organization 08:43:42.453Z before Dev admin seeded 08:43:49Z; DB agrees (org 08:43:42.447Z, first user 08:43:48.831Z) |
| identity-auth.default-organization-boot-invariant · acceptance[2] | pass | live x2: sys_member admin owner, each created user member, in the default org; get-session activeOrganizationId = default org for admin and member |
| 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: 108 tables, 65 with organization_id, 165 rows, 0 NULL / 0 empty (166 after probes); stock.db 197 and walled.db 435 rows, 0 NULL |
| ai.mcp-stdio-fail-closed · acceptance[0] | pass | os start, stdio enabled, no key: exit 1, stdout 0 B, health 000, "[MCP] … OS_MCP_STDIO_API_KEY is not set … Refusing to start an unscoped stdio server (ADR-0101)". Pins plugin.test + plugin-execution-context 24/24 (plugin unit) |
| ai.mcp-stdio-fail-closed · acceptance[1] | pass | osk_unknown: exit 1, 0 B, "did not resolve to a valid identity …"; revoked key: exit 1, 0 B, "refused (API_KEY_REVOKED)" |
| ai.mcp-stdio-fail-closed · acceptance[2] | pass | info log "stdio transport principal-bound to OS_MCP_STDIO_API_KEY identity ID (RLS/FLS/tenant applied)" = the contributor's sys_user id; liaison boot printed the liaison's |
| ai.mcp-stdio-fail-closed · acceptance[3] | pass | contributor: MCP query_records 1 row = REST 1 row, same 19 fields; INV-1003 MCP "not found" / REST 404 (admin 13 rows, 200). Liaison project: budget/spent/budget_remaining absent on MCP and REST alike |
| ai.mcp-stdio-fail-closed · acceptance[4] | pass | member MCP count by status [{draft,1}] = REST POST /data/showcase_invoice/query [{draft,1}]; admin 3/5/5 |
| ai.mcp-stdio-fail-closed · acceptance[5] | pass | liaison sum/groupBy/count_distinct/min on budget, spent → isError 403 "Field read denied: not permitted to aggregate [budget]…", no number; REST same; controls equal |
| ai.mcp-stdio-fail-closed · acceptance[6] | pass | same stdio session: 1 row; admin-session revoke 200 (API-key PATCH 403 needs a session); next query_records/get_record/aggregate_records → API_KEY_REVOKED 403, 0 rows |
| ai.mcp-stdio-fail-closed · acceptance[7] | pass | os start, no stdio env: health 200, stdout 0 B, "[MCP] Transport not auto-started …" |
| ai.mcp-stdio-fail-closed · negative[0]–[4] | pass | unset, " ", osk_, unknown, revoked, Bearer osk_… never served; member 1 row vs admin 13; masked aggregates refused; post-revoke API_KEY_REVOKED |
| api-backend.query-contract-matrix · acceptance[0] | pass | live: 29 variants × 3 doors (POST $-body, POST AST, GET $filter) = 87 calls, every id set equals the set computed from the unfiltered baseline (0 diffs); all 22 operators; infix compound refused POST 400 / GET 400 |
| api-backend.query-contract-matrix · acceptance[1] | pass | $orderby=name&$top=3&$skip=2 → Fabrikam, Globex, Hooli; windows match local slices; POST limit/offset and top/skip agree |
| api-backend.query-contract-matrix · acceptance[2] | pass | $select=name,status and POST fields → 14 rows keys exactly {name,status}; fields:['account.name'] → 400 INVALID_FIELD naming expand |
| api-backend.query-contract-matrix · acceptance[3] | pass | annual_revenue asc/desc both doors = local order; no_such_field → 400 INVALID_SORT both doors |
| api-backend.query-contract-matrix · acceptance[4] | pass | recipe contributor (get-session proven): direct contact read 403; body/list/by-id expand leave contact raw; admin gets {name:"Prospect 18"}. Pin showcase-expand-crud-gate [HTTP] |
| api-backend.query-contract-matrix · acceptance[5] | pass | {status:{$nin:'done'}} → 400 VALIDATION_FAILED at query.where.status.$nin; AST twin 400; GET 400 INVALID_FILTER; no rows |
| api-backend.query-contract-matrix · acceptance[6] | pass | ?$pageSize=5 → 400 UNSUPPORTED_QUERY_PARAM listing 9 params; unknown field via GET/POST → 400 INVALID_FIELD |
| api-backend.query-contract-matrix · acceptance[7] | pass | $in:[] 0 of 10, $nin:[] 10 of 10, both 200; twins agree |
| api-backend.query-contract-matrix · acceptance[8] | pass | one row per variant; $count true/false, $search, $expand covered |
| api-backend.query-contract-matrix · negative[0]–[1] | pass | {limit:"ten"} 400; unknown key 400; blank/garbled $select/select/fields/$count/count all 400 naming the spelling; controls 200. Rest pins request-schema-gate + data-empty-projection-count-door 21 green (route-handler) |
| api-backend.packaged-action-disabled-dispatch · acceptance[0] | pass | flip 200, exactly 1 ledger row (no organization_id); mark_done bogus and real id → 409 ACTION_DISABLED with the rev-13 sentence "…Setup › Packaged Actions…"; tasks unchanged. Live dogfood pin green |
| api-backend.packaged-action-disabled-dispatch · acceptance[1] | pass | live x2: disabled gallery {bogus_key:1} → 409; re-enabled → 400 "Invalid action params" naming both keys |
| api-backend.packaged-action-disabled-dispatch · acceptance[2] | pass | disabled 409s with no-such-record-0000 read and wrote nothing; enabled controls 404 |
| api-backend.packaged-action-disabled-dispatch · acceptance[3] | pass | live x2: showcase_zoo_perm_missing 403 "requires capability [showcase.restricted_ops]" enabled and disabled, byte-identical |
| api-backend.packaged-action-disabled-dispatch · acceptance[4] | pass | live x2: POST /api/v1/mcp run_action on disabled portfolio_snapshot → isError {code:ACTION_DISABLED,status:409}, message string-equal to REST; re-enabled ok |
| api-backend.packaged-action-disabled-dispatch · acceptance[5] | pass | cold restart: info "Activation ledger: 3 packaged action(s) are switched off …"; still 409; re-enable 200, real id 200 done/100; same ledger row id, active true, updated_at moved |
| api-backend.packaged-action-disabled-dispatch · acceptance[6] | pass | live x2: disabled bulk_reassign 409 with or without recordId; reassign_wizard 0 runs before and after |
| api-backend.packaged-action-disabled-dispatch · negative[0]–[2] | pass | no disabled call got the param 400 or a record answer; stock answers with 0 rows; 403 wins over 409; anonymous 401 |
| automation.packaged-flow-disable-durable · acceptance[0] | pass | baseline urgent create 201, runs 0→1; toggle off 200; exactly 1 row (flow, showcase_urgent_task_alert, active false, no organization_id); no "IN PROCESS ONLY" warning |
| automation.packaged-flow-disable-durable · acceptance[1] | pass | trigger → 409 FLOW_DISABLED x2, message exactly the rev-10 sentence (package's Automations in Studio) |
| 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 … left unbound" |
| 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; bound true; create → runs 1→2 |
| automation.packaged-flow-disable-durable · negative[0]–[3] | pass | row written, restart did not re-arm, row kept on re-enable, refusal never the bare status sentence |
| cli.dev-boot-contract · acceptance[0] | pass | scratch copy default boot: health 200 after 10 s; /api/v1/ready 200 ready/running |
| cli.dev-boot-contract · acceptance[1] | pass | admin123 sign-in 200; restart with --admin-password changed99: admin123 200, changed99 401 |
| cli.dev-boot-contract · acceptance[2] | pass | Database line for -d file:, OS_DATABASE_URL, :memory:, nothing chosen (.objectstack/data/objectstack.db), config default datasource (qa_home.db, no objectstack.db), legacy dev.db with the one ⚠ migrate line |
| cli.dev-boot-contract · acceptance[3] | pass | --fresh: "🧪 Fresh OS_HOME: /tmp/objectstack-dev-…"; SIGINT 130 / SIGTERM 143, tempdir gone both times |
| cli.dev-boot-contract · acceptance[4] | pass | port held: "⚠ Port 44406 is in use — serving on 44407 instead." + "↪ server bound to port 44407"; health 200 |
| cli.dev-boot-contract · acceptance[5] | pass | touched src then --no-compile: "⚠ dist/objectstack.json is OLDER than your sources …"; no compile, ready, dist sha unchanged |
| cli.dev-boot-contract · acceptance[6] | pass | empty dir: exit 1 "✗ Config file not found …" + remedy line |
| cli.dev-boot-contract · acceptance[7] | pass | screenshot first: login page at /_console/login; form sign-in reached /_console/home, get-session 200 |
| cli.dev-boot-contract · negative[0]–[3] | pass | marker table survived reboot; --database-driver memory exit 2 INVOCATION ERROR; OS_DATABASE_DRIVER=memory/mingo/in-memory exit 1 naming --fresh/:memory:; memory:///mingo:// exit 1, not ready; legacy read created no objectstack.db |
| cli.organization-ownership-ceremony · acceptance[0] | pass | engine/SQLite integration: packages/cli 8 ceremony files 184/184; runtime boot-guard + kernel 32/32 |
| cli.organization-ownership-ceremony · acceptance[1] | pass | v17 copy production: plan exit 0 "no row or table … changed", sha unchanged, row diff 0, 144 table entries; --apply without plan exit 1 (apply_refused/plan-file-required); --dev copy same, telemetry unchanged |
| cli.organization-ownership-ceremony · acceptance[2] | pass | --apply --plan-file --backup-taken: exit 0, complete, blocking 0, 13/13 steps; marker shapeGeneration 1 |
| cli.organization-ownership-ceremony · acceptance[3] | pass | unmigrated production serve: exit 1, no ready line, marker sentence, 9 tables, commands without --dev, 0 "17.x release"/"fresh installs only"; migrated copy ready, health 200; --dev refusal spells --dev |
| cli.organization-ownership-ceremony · acceptance[4] | pass | comment-reactions without --yes exit 1, with --yes 0 twice; migrate apply --allow-destructive --yes --json exit 1 refused_organization_ownership_unmigrated naming 9 tables, applied []; sha unchanged |
| cli.organization-ownership-ceremony · acceptance[5] | pass | 18.0 pre-release restore: boot refused naming sys_flow_credential/sys_secret with --dev; reviewed apply exit 0 complete; boot 2 ready; identity mails in sys_identity_email (0 diffs over 24 cols at apply), global audit 8/8 moved, mail jobs re-pointed; old passwords 200, moved reset token resets; one task PATCH → 1 sys_http_delivery declared:showcase_task_changed |
| cli.organization-ownership-ceremony · negative[0] | pass | no refusing or plan arm changed a checksum or a pre-existing row |
| integration-system.datasource-credential-refusal-matrix · acceptance[0] | pass | build door os compile: 19 datasource probes + 5 connector probes exit 2 at their paths, naming external.credentialsRef / credentialRef and the OS_DATASOURCE_ route; controls exit 0. Runtime: POST /datasources 400 on all 19, PUT /meta/connector 422 on all connector doors; 0 cleartext |
| integration-system.datasource-credential-refusal-matrix · acceptance[1] | pass | PG16 POST /datasources with top-level secret 201 ok; /test ok, remote-tables lists r7_widgets; no-secret control 201 status error |
| integration-system.datasource-credential-refusal-matrix · acceptance[2] | pass | full-body grep of admin, meta and /data/sys_metadata?type=datasource: 0 planted values (only the ruled apiSecret); admin config = meta config on all 10 |
| integration-system.datasource-credential-refusal-matrix · acceptance[3] | pass | hasSecret true / false; legacy rows' redactedConfigKeys name each withheld key |
| integration-system.datasource-credential-refusal-matrix · acceptance[4] | pass | 7 rows planted with the server stopped; after re-boot listed with metadata_spec_invalid, each key in redactedConfigKeys, 0 values on any door or log |
| integration-system.datasource-credential-refusal-matrix · acceptance[5] | pass | acme-plugin-db 201; redactedConfigKeys authToken, passwd, password, url; url served acme://u@h/db; apiSecret as written |
| integration-system.datasource-credential-refusal-matrix · acceptance[6] | pass | PUT 405 Allow: DELETE, GET, HEAD, PATCH; echoed PATCH {config} 200, /test ok, credentialsRef unchanged |
| integration-system.datasource-credential-refusal-matrix · acceptance[7] | pass | auditor.demo, phone.demo, plain member, manage_metadata-only: 403 on all 24 read URLs; anonymous 401 on all; manage_platform_settings-only reads with 0 leaks |
| integration-system.datasource-credential-refusal-matrix · negative[0]–[6] | pass | no cleartext; build = runtime; PATCH password / userinfo / top-level 400; same keys redacted on both doors; no mask literal; every refusal names its replacement |
| platform-core.boot-health · acceptance[0] | pass | health 200 {status:ok, version 18.2.0} 15.1 s after launch |
| platform-core.boot-health · acceptance[1] | pass | /api/v1/ready 200 ready/running as the first non-health request |
| platform-core.boot-health · acceptance[2] | pass | boot window (51 lines): Flows: 32 flow(s) 19 bound … · 8 draft; two ℹ deployment-policy lines; 0 ⚠, 0 ERROR; Seeds: com.example.showcase 132 rows |
| platform-core.boot-health · acceptance[3] | pass | meta/app?id=showcase_app 200 {type,items}; unfiltered [showcase_app, setup, account]; _diagnostics.valid: true |
| platform-core.boot-health · acceptance[4] | pass | 51 authored nav_* ids = 51 served (diff empty); grp_data 12 objects |
| platform-core.boot-health · acceptance[5] | pass | /_console/ 200 text/html, entry byte-identical to dist |
| platform-core.boot-health · negative[0]–[1] | pass | no SeedLoader rejection, 0 ERROR lines |
| platform-core.console-login · acceptance[0] | pass | form sign-in 200 ×3 → /_console/home (screenshot: header + launcher); cookie and localStorage token both set |
| platform-core.console-login · acceptance[1] | pass | reload stays on /home; first authed calls all 200; in-page meta/app?id=showcase_app 200, 1 item |
| platform-core.console-login · acceptance[2] | pass | live x3: server sign-out 200, same bearer → 401 on meta/app, get-session, data |
| platform-core.console-login · acceptance[3] | pass | full nav → /_console/login?redirect=…showcase_task x3; client-side nav → "Sign in required" state, no stale rows |
| platform-core.console-login · acceptance[4] | pass | re-login returns to showcase_task (10 records); read 200, write 201 |
| platform-core.console-login · negative[0]–[1] | pass | wrong password 401 INVALID_EMAIL_OR_PASSWORD, no cookie or token; alert shown; 0 page errors |
| platform-core.nav-surfaces-render · acceptance[0] | pass | e2e/showcase-smoke.spec.ts against this boot (browser over live HTTP): 50 passed / 0 failed on the full re-run. The first run lost 3 to "Target crashed" at 13.6 GB used (browser process, environment); those 3 then passed alone and the full suite passed |
| platform-core.nav-surfaces-render · acceptance[1] | pass | 51 served entries = 50 leaves + 1 separator; diff with the 50 SURFACES empty both ways |
| platform-core.nav-surfaces-render · acceptance[2] | pass | bad route in 2 fresh contexts: header and 50 sidebar items stay; main "Object Not Found …"; 0 page errors |
| platform-core.nav-surfaces-render · acceptance[3] | pass | no render failure in the sweep; ErrorBoundary fallback unexercised (existing knownGap) |
| platform-core.nav-surfaces-render · negative[0]–[3] | pass | no blank main; splash wait held on 50; charts passed the boundingBox poll; shell kept on bad route |
| platform-core.builtin-apps-nav-render · acceptance[0] | pass | admin walk, screenshot first: Setup 46/46 and Account 8/8 render, 0 page errors; only "failed to load" is the knownGap marketplace (502 MARKETPLACE_PROXY_FAILED, egress); 11 settings namespaces render |
| platform-core.builtin-apps-nav-render · acceptance[1] | pass | setup requiredPermissions [setup.access], 9 groups, 46 leaves = source contributions minus nav_organizations / nav_sso_providers; account 8 leaves in 3 groups; ?id=studio {items:[]} |
| platform-core.builtin-apps-nav-render · acceptance[2] | pass | member phone.demo: Setup, sys_user route and settings/mail → "You don't have access to this app" without shell; Account Profile and My Sessions open |
| platform-core.builtin-apps-nav-render · acceptance[3] | pass | member ?id=setup {items:[]}, GET meta/app/setup 403; member list [showcase_app, account] |
| platform-core.builtin-apps-nav-render · acceptance[4] | pass | account nav 8 = 8 for admin and member |
| platform-core.builtin-apps-nav-render · acceptance[5] | pass | single posture: nav_organizations absent (multiOrgEnabled:false); nav_business_units present, object and data 200 (5 units) |
| platform-core.builtin-apps-nav-render · acceptance[6] | pass | no jwks/sso/verification/device_code entries; sso:false; sys_jwks 404 OBJECT_API_DISABLED, sys_verification / sys_device_code 405 |
| platform-core.builtin-apps-nav-render · negative[0]–[3] | pass | member /api/settings/NS 403 SETTINGS_FORBIDDEN for all 11 (admin 200); no "All reports" row |
| platform-core.seed-integrity · acceptance[0] | pass | expected counts re-derived through tsx from ShowcaseSeedData: 19 datasets, 132 rows; $top=1 totals and list lengths match 19/19 |
| platform-core.seed-integrity · acceptance[1] | pass | "Specimen — Full" 37/37 fields; lookups resolve; f_time '14:30:00'; f_password masked |
| platform-core.seed-integrity · acceptance[2] | pass | banner Seeds: com.example.showcase 132 rows plain; [Seeder] … {"inserted":132,…,"errored":0} |
| platform-core.seed-integrity · acceptance[3] | pass | restart on the same DB: sweep JSON byte-identical; {"inserted":0,"updated":0,"skipped":132,"errored":0} |
| platform-core.seed-integrity · acceptance[4] | pass | f_user, f_users, f_secret present and null; task.cover null on 10 |
| platform-core.seed-integrity · negative[0]–[1] | pass | no seeded object counts 0; no growth on restart |
| platform-core.v18-boot-refusals · acceptance[0] | pass | runtime boot-guard + kernel 32/32 (unit + kernel); plugin-security authz-identity-objects-boot-refusal 3/3 |
| platform-core.v18-boot-refusals · acceptance[1] | pass | production os serve over v17 copy: exit 1, no ready line, marker sentence, 9 tables, no --dev; --dev copy 13 tables, commands carry --dev |
| platform-core.v18-boot-refusals · acceptance[2] | pass | node:sqlite row diff: production 69 tables / 61 rows, 0 differences, created tables empty, 0 marker rows; dev copy 0 differences, telemetry unchanged |
| platform-core.v18-boot-refusals · acceptance[3] | pass | live rig (SecurityPlugin without auth, os serve --dev --no-server --preset minimal): exit 1 "✗ SecurityPlugin cannot boot: … mount AuthPlugin, or … createIdentityObjectsPlugin()"; never listened |
| platform-core.v18-boot-refusals · negative[0] | pass | every v18 boot over a v17 copy (production, --dev, os start) refused; rows unchanged |
| approvals.account-app-entry · acceptance[0] | pass | build layer: console:build at this subject; served entry byte-identical to dist; entry registers approvals:inbox "Approvals Inbox" (1 hit) |
| approvals.account-app-entry · acceptance[1] | pass | non-admin approver X: avatar › Profile › Inbox › Approvals → /_console/apps/com.objectstack.account/component/approvals/inbox; tabs My Pending 6 / Submitted by me / All, 6 rows |
| approvals.account-app-entry · acceptance[2] | pass | X meta/app [showcase_app, account] with nav_account_approvals; ?id=setup {items:[]}, meta/app/setup 403; same session renders the inbox |
| approvals.account-app-entry · acceptance[3] | pass | live x2 per decision: Approve → Confirm approval_approve 200, 0/2 → 1/2, X leaves pending; Reject 200, status rejected, invoice back to draft; Request info 200, row appended; Reply approval_comment 200. Non-participant N: every REST and action door 404 REQUEST_NOT_FOUND, forged actorId 403, request unchanged; X after acting 403 / 409 |
| approvals.account-app-entry · acceptance[4] | pass | cold load …/approvals/inbox?request=ID → the request's record page with the decision panel; history replaced; alias /apps/account/… lands on the same page |
| approvals.account-app-entry · acceptance[5] | pass | row link /_console/apps/com.objectstack.account/showcase_invoice/record/ID, renders; X GET /data/showcase_invoice/ID 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, no missing-component state; entry present for X, setup refused 403 |
| records-forms.crud-roundtrip · acceptance[0] | pass | UI Create → POST /data/showcase_account {"industry":"retail","status":"active","sales_region":"amer","name":"os-qa-r6w5"} 201; filtered GET equal on all keys, website null |
| records-forms.crud-roundtrip · acceptance[1] | pass | UI Update → PATCH …/ID {"annual_revenue":4321000} 200; only annual_revenue and updated_at differ over 24 keys |
| records-forms.crud-roundtrip · acceptance[2] | pass | record page ⋯ › Delete › confirm → DELETE 200; filtered GET 0, by id 404 |
| records-forms.crud-roundtrip · acceptance[3] | pass | reloaded list shows the row after create (15 records), absent after delete |
| records-forms.crud-roundtrip · acceptance[4] | fail | live x3 (R6) + x2 (verifier), fresh loads, 1440×900: Activity tab / ?related=timeline, Changes chip pressed → only the two sys_activity lines; page request timeline.fieldChanges:false, no GET sys_audit_log, while sys_audit_log holds 2 rows and the drawer (?recordId=) draws them. Pin ui/e2e/live/record-history-display.spec.ts (console from source via vite, own ports): 1 failed at L116 toContain(other.name). Reproduction rule below |
| records-forms.crud-roundtrip · acceptance[5] | pass | UI create os-qa-r6w5-华宁 201, re-read hex-identical; $search=华宁 2 rows; list quick-search 2 rows |
| records-forms.crud-roundtrip · acceptance[6] | pass | admin clone 201, diffs only id / timestamps / overridden name; member clone of admin zoo row: owner/created_by = member, autonumber 0001 → 0003, f_password not carried; planted lead_score 42 → clone header lead_score;reason=readonly, value null |
| records-forms.crud-roundtrip · acceptance[7] | pass | recipe search:qa-contributor-bound-member: member sees 0 of 12 seeded invoices; INV-1003 GET 404, clone 404 ×3, admin count 13 → 13; own-row clone 201 |
| records-forms.crud-roundtrip · negative[0]–[3] | pass | empty name: inline required, no POST; clone re-derives id/audit/autonumber, drops readonly; API missing name 400 required; tax_id 123456789 400 invalid_format, control 201 |
| studio-authoring.first-run-loop · acceptance[0] | pass | by hand, en and zh-CN legs: chip "New in Studio" / 在 Studio 中新建 → package com.example.repairs, namespace repairs; POST /api/v1/packages 201; switcher lists it Writable / 可写; in-page marker survived (no reload) |
| studio-authoring.first-run-loop · acceptance[1] | pass | Publish all → publish-drafts 200 outcome:published, publishedCount 1; GET /meta/object/repairs_repair_ticket 200 with the status options. Both legs |
| 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. Both legs (the zh-CN leg passes; knownGaps[3] is stale) |
| studio-authoring.first-run-loop · acceptance[3] | pass | /meta/app lists repair_center with its nav entry; Home tile "Repair Center"; end-user list row with chip "In Repair", raw wip 0 times. Both legs |
| studio-authoring.first-run-loop · acceptance[4] | pass | one Server is ready per leg; listener PIDs unchanged through each loop |
| studio-authoring.first-run-loop · acceptance[5] | pass | forged as admin x2 per leg: object into showcase 422 WRITABLE_PACKAGE_REQUIRED, field on showcase_account 403 ITEM_LOCKED, plain PUT 403 NOT_OVERRIDABLE, app 422, showcase publish nothing_to_publish; nothing landed |
| studio-authoring.first-run-loop · negative[0]–[2] | pass | no silent acceptance; label chip renders; every clause held on both legs |
Reproduction rule for the FAIL
records-forms.crud-roundtrip · acceptance[4] (P0; rule-7 verifier agreed; disposition: product defect, regression from a932270 / #29846, extracted)
- Boot the stock showcase; sign in as admin through the form at
/_console/login. - Accounts › New: Account Name
os-qa-x, Industry Retail, Lifecycle Active › Create →POST /api/v1/data/showcase_account201. - Record page › Edit › Annual Revenue 4321000 › Update →
PATCH200. Server truth:GET /api/v1/data/sys_audit_log?filter=[["record_id","=","ID"]]→ total 2. - Fresh load
/_console/apps/com.example.showcase/showcase_account/record/IDat 1440×900; click the Activity tab (URL gains?related=timeline), then the Changes chip (aria-pressed="true"). - Expected: the audit lines with display values, e.g.
Annual Revenue — → $4,321,000.00 · Dev AdminandOwner — → Dev Admin; Account Name — → os-qa-x; Industry — → Retail; Lifecycle — → Active; Sales Region — → AMER · Dev Admin(as at QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927, and as the drawer shows). - Actual: only
Updated Account "os-qa-x": Annual Revenue · Dev AdminandCreated Account "os-qa-x" · Dev Admin(sys_activity). Network: the record-page request carries"timeline":{"discussion":true,"activity":true,"fieldChanges":false}; noGET /api/v1/data/sys_audit_log; object reads areGET /api/v1/meta/object?package=com.example.showcaseplus by-name sys_organization, sys_user, sys_business_unit, sys_comment_reaction. - Control:
/_console/apps/com.example.showcase/showcase_account?recordId=IDsendsfieldChanges:true, readssys_audit_log200, draws both audit lines.
- Self-check: the decisive signal (
fieldChanges:false) is fixed when the page is composed, before any click; role-targeted clicks only; screenshot before every DOM read; served bundle byte-identical to dist and reproduced on the source console; traps hydration-race, automation-input, stale-console-bundle and wrong-panel ruled out.
Derived item verdicts and gaps
- 20 items PASS.
access-security.rls-both-sides: PARTIAL. acceptance[5] 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}. Unchanged from QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927.access-security.crud-permission-matrix: PARTIAL. acceptance[5] 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. Unchanged from QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927.records-forms.crud-roundtrip: FAIL (acceptance[4]).- Fixture gaps (unchanged): nav-surfaces-render ErrorBoundary fallback unexercised; marketplace catalog blocked by egress; the v17 fixture is a blank scaffold; the MCP
list_remote_tables/import_objectlegs of fix(rest,runtime)!: seeing a datasource's remote structure needs the read capability on every route, writes included #29812 need an OAuth grant (not part of any P0 clause).
Off-clause probes (RUNNER rule 8)
About 45 runner-minutes in total, after the clauses had verdicts, on the same boots and as the same personas: R1 7, R2 6, R3 6, R4 6, R5 6, R6 6, R7 8.
Doors: data by-id, list, query, bulk create/update/delete, clone; sys_user_permission_set, sys_user_position, ext_customer; analytics; walled /meta, /packages, /automation siblings; actions, _activation, automation toggle/trigger/runs/_status, MCP over HTTP and stdio; approvals list, request, actions and decision doors; datasource admin PATCH/GET and the federation routes; Studio metadata write and publish (incl. a zh-CN translated-read save-back); meta/app query and path forms, /api/settings/:ns, sign-in/out; the ceremony apply refusals, os dev flags, os start over a v17 DB.
Personas: admin, walled operator and org owner, plain members, contributor, auditor, ops, field_ops_delegate, liaison, a non-admin approver and a non-participant, demo personas, manage_metadata-only and manage_platform_settings-only personas, API keys, anonymous, bogus/empty bearer.
Boundary classes: hidden vs missing ids on by-id, bulk and clone doors (with and without If-Match); empty, whitespace, encoded (%2F, %00, %2e%2e), 300-char and unknown ids and names; blank and malformed query values; unknown enum values; owner forge through createMany/updateMany/clone overrides; FLS-masked fields in filter/sort/aggregate; empty/whitespace/wrong secrets; the opposite posture (walled vs single) and the opposite credential (API key vs session); missing flag values, foreign/missing plan files, no backup flag, re-apply on a certified DB.
Findings, each in its own card (listed in the close-out comment):
integration-system.datasource-credential-refusal-matrix· observed beside the clauses: a datasource PATCH whose new secret fails to connect (wrong, or whitespace-only) answers "the new configuration is NOT in force" but stores it, so the datasource fails at the next restart.approvals.account-app-entry· observed beside the clauses:GET /api/v1/approvals/requests?status=bogusanswers 200[]instead of refusing an unknown status value.api-backend.packaged-action-disabled-dispatch· observed beside the clauses: a per-record flow action with norecordIdruns the flow and answers 400 FLOW_FAILED naming an internal node, not a refusal namingrecordId.cli.organization-ownership-ceremony· observed beside the clauses: the v17 refusalos startprints leads to a ceremony that blocks (security plugin not composed) because it does not name the auth secretos startkeeps in its home.
Wave-4 probe cards re-checked — none reproduces at this subject: #28928 (PATCH {"secret":""} now 400, credential kept), #28930 (?id[]=setup now 400 VALIDATION_ERROR), #28931 (os dev -d now prints the INVOCATION ERROR banner, exit 2), #28932 (approval_approve with no recordId now 400 naming it; the flow-action twin is the new card above), #28933 (clone and createMany now send X-ObjectStack-Dropped-Fields).
Recorded, not filed:
- A blank GET
$filter=(also%20,filter=,where=) reads the whole table (200, 14 of 14), while POST{"where":""}is refused 400. Deliberate perpackages/metadata-protocol/src/protocol.ts(~L5926, "A blank?filter=is ABSENT, not malformed"), but data list door: a blank $select answers every column and an unrecognised $count value counts — malformed values are read as the absent default #26644 ruled the opposite for blank$select=/$count=; a contract question, reported to the PM, not a card. GET /api/v1/meta/appanswers its refusals in three envelope shapes (flat for?id[]=and?id=, nested for a repeatedidand an unknown name,success:falsenested for 403) — the flat-vs-nested convergence tracked on [tracking] Envelope-position convergence line for packages/rest's flat dialect — the live ratchet owner #9559.postgres://u@h/d?sslpassword=Xis accepted and served as written (pg-connection-string does not readsslpassword); a ledger question for the URL-query credential entry.share_new_inquiries_with_field_opsexpands to NO recipients on every boot (the showcase seeds no business-unit members), as at QA run · priority:P0 (23/23) · 7fa9873f · 2026-11-02 · 21 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #28927.- The showcase formula
showcase_invoice_line.amountwarns "No such key: unit_price" for lines created without the optional unit_price (the app's formula, reported as designed). - System Overview issues
GET meta/object/sys_package_installation→ 404 while rendering fully.
Time
- Environment prep: 17 min wall (08:25Z–08:42Z: protocol reading, install, full build 15m04s, console build, compile boot and bundle check), plus about 17 runner-minutes of per-runner prep (scratch copies, personas, the walled boot, the v17 and pre-release DBs, scratch PostgreSQL).
- Testing: 35 min wall (08:42Z–09:17Z), about 98 runner-minutes of clause work plus 45 of probes, and 8 verifier-minutes.
- Ratio: about 1 : 2 by wall clock (17 to 35 min), and about 1 : 4.5 by agent-minutes (34 to 151).
Checklist-accuracy findings from this run are reported to #27377; they are not repeated here.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 3, 2026
domain:devx#1 · os-warren · session_01JQwxbWT669ynWFKZjqFyNF
Close-out (W5-P0)
FAIL disposition (checklist-test SKILL §5):
records-forms.crud-roundtripacceptance[4] is a product defect (a regression from a932270 / #29846; the clause, its surface and its oracle are right at this subject, and the pin it cites goes red for the same reason). Extracted below. Off-clause probe findings, each extracted as its own card:Extracted: #29878 · records-forms.crud-roundtrip · acceptance[4]
Extracted: #29879 · integration-system.datasource-credential-refusal-matrix · observed beside the clauses
Extracted: #29880 · approvals.account-app-entry · observed beside the clauses
Extracted: #29881 · api-backend.packaged-action-disabled-dispatch · observed beside the clauses
Extracted: #29882 · cli.organization-ownership-ceremony · 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 #28927, so nothing is carried forward from it.
Generated by Claude Code