Skip to content

QA run · surface:api (89/89) · 251a7dd4 · 2026-10-04 · 68 PASS / 7 PARTIAL / 14 FAIL / 0 BLOCKED / 0 NOT-RUN #21720

Description

@objectstack-fleet

17.7 pre-release verification, non-browser half: every runnable surface:api item against origin/main as it stood when the run started, the base 17.7 will be cut from (not yet cut; packages still read 17.6.0 with the pending changesets). The browser half waits for the Console pin bump (#21696). Text only; the durable truth stays in docs/qa/platform-checklist/areas/.

Environment fingerprint

  • Framework (subject): objectstack-ai/objectstack 251a7dd4 (fix(organizations)!: a create naming an organization_id meets the Layer 0 write wall, as the update does (#21666) (#21680)), in a dedicated detached worktree: pnpm install --frozen-lockfile && pnpm build → exit 0 (6m07s).
  • Console: not built for this run. .objectui-sha = ab187972 (chore(objectui): bump the console pin to ab1879721595 (carries objectui f624f278, b0bf413c and ab187972) #21625). Every clause that can only be judged in the browser is recorded not-run (frontend deferred, #21696).
  • Checklist: items, RUNNER.md and scripts/checklist-select.mjs from the subject tree; the revision of every item is in the table.
  • App / boots: examples/app-showcase, OS_PORT={p} objectstack dev --seed-admin -p {p} -d file:/tmp/qa1770/{lane}/{item}.db, one file DB and one port per item on disjoint lane ranges 42101–43959 (egress proxy port 41333 excluded). Two lanes deviated under load and say so: L1 drove its eight access-security items on one boot with fresh personas and probe rows per item (plus an independent fresh-DB reproduction for [finding] The delegated-admin gate resolves an EMPTY subtree on a stock objectstack dev boot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057), and L6 shared one DB per item group. Members minted by admin invite-member + sign-up/email; identity proved by GET /auth/get-session before each persona cell. Scratch apps and packages lived under /tmp, never in a checkout.
  • Execution: 13 parallel runner subagents (L1–L13) + 6 independent verifiers (V1–V6, RUNNER rule 7), Claude Code session session_018zT8d8NpiQ1ExhuNd5TxY6, 2026-10-04 08:10–11:10Z. The box (4 CPUs, 15 GB) was badly oversubscribed in the first wave (load 60–110): some boots took 10+ min and several hit plugin-start timeouts and were re-booted on fresh DBs; batched vitest runs were SIGKILLed or timed out and every affected pin was re-run alone — every verdict rests on the clean re-run. Environment / waiting ≈ 40–55 % of runner time.

Scope

node scripts/checklist-select.mjs surface:api --json → 89 runnable items. Hidden as blocked (not run): access-security.no-active-org-session-semantics, approvals.sla-escalation. This record is one of three for the same subject; the CLI and build selectors are separate records.

item rev verdict evidence (server truth / pin)
access-security.rls-both-sides 5 PARTIAL A6 blocked(dependency: the private D11 write-up the clause requires); verify --rls 38 PROVEN · 0 HOLES · 226 NOT PROVEN, 10/10 positions; private-owd 5/5
access-security.write-path-guards 3 PARTIAL N2 not-run (needs an in-process isSystem write; no REST door, no pin); owner-anchor 9/9 · static-readonly 3/3 · readonly-when-parent 5/5
access-security.crud-permission-matrix 4 FAIL A1 fails — #21057 still reproduces (3 loads); A6 blocked(fixture); persona-matrix 46/46 · permission-zoo 13/13
access-security.owd-sharing-matrix 3 PASS public-read-owd 3 · controlled-by-parent 4 · invoice-cbp 4 · private-owd 5
access-security.scope-depth-asymmetry 2 PASS scope-depth 7/7 · scope-depth-write 9/9 · scope-depth-fallback 4/4
access-security.anonymous-deny-surfaces 3 PASS anonymous-deny-surfaces 61/61
access-security.sharing-rules-widen 1 PASS unit_and_subordinates variant; rule share source rule, survives restart
access-security.record-share-grant-revoke 4 PASS grant 201 / revoke 204 / cross-record DELETE 404; evaluate source_id = row id
access-security.share-link-capability-tokens 3 FAIL A5 record-gone leg: 404 INVALID_OR_EXPIRED, not 410 RECORD_GONE (fail-closed by design, #5190) — stale clause; client-liaison-fixtures 5/5
access-security.suggested-binding-loop 2 PASS stock boot reconciles one confirmed row; confirm writes the binding under the caller
access-security.activation-write-operator-gate 2 PASS runtime posture-gate pins 46/46; tier gate 403 at both doors, manage_metadata holder 200
access-security.packaged-flow-write-door-parity 2 PASS all three doors 403 NOT_OVERRIDABLE / ITEM_LOCKED; write-door-parity dogfood 5/5
access-security.platform-owner-email-anchor 2 PASS core pins 65/65; unset / unverified / non-match / malformed refused; verified match → platform admin
access-security.me-permissions-aggregation-parity 2 PASS hono 38/38 · plugin-security 64/64 · me-apps-baseline 6/6
access-security.record-view-read-audit 1 PASS plugin-audit 43/43; stock audits nothing, opt-in records one read row per detail view
ai.agent-tool-skill-metadata-roundtrip 3 FAIL A4: draft PUT on a package-shipped skill → 403 NOT_OVERRIDABLE by design (ee58392, #6608) — assertion defect
ai.mcp-http-surface 2 PASS showcase-mcp-http-identity 6/6; config-off 404, anonymous 401 + WWW-Authenticate, scope narrowing
ai.mcp-run-action-exposure-gate 2 PASS unexposed action refused with the opt-in sentence, no side effect
ai.mcp-validate-expression 2 PASS mcp 37/37 batch; ok / bare-reference / unknown-field match a real build
ai.skill-instructions-mcp-prompts 1 PASS skill-prompts 12/12; prompts/list and prompts/get round-trip
ai.open-edition-honest-degradation 1 PASS /ai/agents 200 empty; models/chat 501 with the remedy; anonymous 401
ai.mcp-oauth-private-host-transport 2 PASS plugin-auth 89/89; private origin served, public plain HTTP withheld, notices exactly once
api-backend.batch-transactional-discovery 3 FAIL A5: default continueOnError:false stops at the first failure (NOT_ATTEMPTED tail, batch.zod.ts:81-84) — assertion defect
api-backend.server-timing-admin-gated 2 FAIL A2/A3: the item inverts global mode vs per-request admin-gated mode (hono-plugin.ts:83-104) — assertion defect; server-timing pin 24/24
api-backend.query-contract-matrix 3 PASS objectql 208/208 · rest request-schema-gate 16/16; 16 operators × 3 spellings
api-backend.error-envelope-ledger 3 PASS 7 code families, fields[] with label, no fieldErrors
api-backend.bulk-write-contract 1 PASS owner-anchor-and-bulk-writes 9/9
api-backend.route-ledger-live-parity 3 PARTIAL A10 console-static family not-run (frontend deferred); 18 REST families answer
api-backend.declarative-endpoint-execution 1 PARTIAL A3 blocked(fixture: no live script/proxy endpoint without source edits); declarative-endpoints 17/17 · policy 8/8
api-backend.package-rest-lifecycle 2 PASS create 201 / dup 409 / PATCH / overwrite; one row per id
api-backend.filter-comparand-conformance 3 PASS engine door + 5 driver suites; #21333 no longer reproduces (fixed by 9f13c94, #21372)
api-backend.date-range-preset-matrix 2 PASS 13 presets, all answer-discriminating, against a known clock
api-backend.packaged-action-disabled-dispatch 3 PASS dogfood + runtime pins green; 409 ACTION_DISABLED on REST, MCP and after restart
api-backend.action-activation-door-contract 2 PASS posture-gate 38/38; body/path/404 refusals write no row
api-backend.aggregate-contract-matrix 1 PASS 6 functions × 5 granularities, secured leg via search:qa-contributor-bound-member
api-backend.api-methods-verb-gate 1 PASS allowed sets equal spec-dist derivation; batch refusal leaves no sibling row
api-backend.rest-crud-config-contract 2 PASS rest pins 57/57 (parse-not-cast + mount table)
api-backend.rest-batch-config-contract 2 PASS BATCH_TOO_LARGE on all five doors; tombstones throw
api-backend.rest-metadata-config-contract 3 FAIL A4 fails — authorization class, detail withheld pending maintainer (RUNNER rule 2)
approvals.decision-only-via-service 1 PASS resume-authority-gate 22/22; forged resumes 403, service approve completes the run
approvals.email-action-token-door 1 PASS five refusal shapes, replay refused, token not a bearer credential
approvals.approver-resolution-matrix 2 PASS all resolver types, subtree units, empty-approver policies
approvals.status-mirror-field 1 PASS status-mirror-cascade 2/2; six mirror values observed
attachments-storage.presigned-upload-roundtrip 1 PASS pending → committed, bytes round-trip, anonymous 401
attachments-storage.read-inherits-parent-rls 3 PASS count-parity 7/7 · scan-cap 3/3
attachments-storage.attach-requires-parent-edit 5 PASS unscoped-delete-gate 10/10 · capability-gate 12/12
attachments-storage.sys-file-status-pipeline 2 PASS full pending → committed → deleted → revived cycle
attachments-storage.orphan-tombstone-reap 1 PASS attachment-lifecycle 47/47; sweep reaps T1/P1, keeps T2/T3/K1
attachments-storage.upload-session-abort 3 PASS abandoned and completed sessions reaped; 410 on an expired session
attachments-storage.field-accept-maxsize-server-enforced 1 PASS accept/maxSize refused, no row (the 500 status is the known gap, extracted below)
automation.durable-suspend-restart 1 PASS flow-durable-suspend 11/11; three paused runs survive a cold restart and resume
automation.flow-toggle-kill-switch 2 PASS OFF → no run, ON → one run; /_status tracks
automation.trigger-status-contract 1 FAIL A5/A6/A7: resume refusals carry status-derived codes (VALIDATION_ERROR / RESOURCE_NOT_FOUND) — product defect
automation.packaged-flow-disable-durable 2 PASS one ledger row, 409 FLOW_DISABLED, survives restart, re-enable in place
automation.packaged-flow-subflow-disable-refusal 2 PASS flow-activation-ledger 47/47; 409 DELETE_RESTRICTED naming the caller
automation.packaged-flow-clone-contract 2 PARTIAL A7 Studio-reach half not-run (frontend deferred); durability half and A1–A6 pass
dashboards.cube-query 3 PASS counts and sums equal /data group-by exactly
identity-auth.self-service-password-reset 1 PASS reset, single-use token, no enumeration
identity-auth.two-factor-enrollment-reveal 1 FAIL A6: sys_user.enable_two_factor now declares a resultDialog (266654d, #11110) — stale clause
identity-auth.two-factor-verify-to-activate 1 PASS unverified factor cannot complete a sign-in; verify activates
identity-auth.two-factor-backup-codes 1 FAIL A6: generate_backup_codes now declares a resultDialog (266654d, #11110) — stale clause
identity-auth.two-factor-disable-lifecycle 1 PASS disable removes the factor; old secret and codes dead after re-enroll
integration-system.connector-declarative-boot 2 PASS showcase-declarative-mcp + two-factor-lockout 7/7; build refusals verbatim
integration-system.connector-degraded-recovery 2 PASS connector pins 59/59; backoff 5/10/20/40 s, recovers without restart
integration-system.external-datasource-federated-read 2 PASS federated reads; writes 403 EXTERNAL_WRITE_FORBIDDEN
integration-system.datasource-admin-lifecycle 3 PASS service-datasource pins 86/86
integration-system.external-schema-introspection 2 FAIL A1 columnCount 7 not 5 (assertion defect); A3 PK as comment, value import (4257e4e, #11073 — stale clause)
integration-system.connector-auth-kind-application 1 PASS rest-connector 10/10; five auth kinds on the wire, secrets never served
platform-core.seed-integrity 3 PASS 19 datasets / 132 rows match; restart idempotent
platform-core.metadata-registry-serving 2 PARTIAL A7 console half not-run (frontend deferred); meta-types-create-seed 6/6
platform-core.docs-audience-gate 1 PASS book.test 40/40; org / permissionSet / public gates
platform-core.manifest-install-contract 2 FAIL A2: protocol-incompatible refusal answers 500 without its structured diagnostic — product defect
platform-core.activation-ledger-registration-home 2 FAIL A5: "41 names" — the array holds 46 (46 already at 17.6.0) — assertion defect; pins 11 + 49 + 22 green
platform-core.activation-ledger-row-contract 2 PASS action-activation 18/18; 405 on writes, no organization_id column
platform-core.packaged-object-extend-only 1 PASS both doors 403; object byte-identical
platform-core.marketplace-install-local-lifecycle 1 FAIL A5 purge-sample-data 500 DRIVER_UNAVAILABLE (product defect); A7 hot withdrawal since 901e7cf (#21581, stale clause)
platform-core.runtime-config-boot-read 1 PASS anonymous 200, both spellings byte-identical, no secrets
platform-core.seed-mode-matrix 1 PASS upsert / update / ignore / insert / replace postures
records-forms.validation-rule-type-matrix 2 PASS all six codes, warning/info severities non-blocking
records-forms.named-import-mapping 1 PASS mapping applied, re-import upserts, unknown name 404
records-forms.field-unique-enforcement 1 FAIL A1: SQL-family refusal names the object, not the field, by design; memory boot store retired by 9a4182a (#21598) — stale clause; pins 26/26 + 65/65
records-forms.delete-behavior-matrix 1 PASS engine-cascade-delete ×4 59/59
records-forms.record-clone-contract 1 PASS search-clone pins 26/26 + 6/6
records-forms.import-transform-matrix 2 PASS five transforms; javascript refused without a tracker number
records-forms.predicate-relationship-traversal 1 PARTIAL A4 blocked(fixture: no stock persona with invoice CRUD and no account read); A1–A3 pass
search.cross-field-object-search 3 PASS showcase-search 5/5
search.field-scoped-narrowing 1 PASS unknown / non-searchable / hidden fields refused 400 INVALID_FIELD
search.rls-both-personas 6 PASS member search never surfaces the hidden invoice; totals do not leak the population
studio-authoring.org-override-registry-gate 2 PASS overlay-precedence 26/26; view overlay 200, object 403, reset

Totals: 68 PASS / 7 PARTIAL / 14 FAIL / 0 BLOCKED / 0 NOT-RUN. Of the 14 fails, 5 carry a product defect (one known, four new) and 9 are checklist clauses whose assertion is wrong or that a deliberate change made stale. Every fail was re-derived by an independent verifier from a fresh reproduction; where a verifier changed a disposition, the verifier's is recorded.

Fails — reproduction rules and dispositions

Product defects

access-security.crud-permission-matrix A1 — known #21057, still reproduces at 251a7dd4 (fails closed). Fresh boot; admin invites + signs up D and T; admin POST /api/v1/data/sys_user_permission_set {"user_id":D,"permission_set_id":{showcase_field_ops_delegate}} → 201 and POST /api/v1/data/sys_business_unit_member {"business_unit_id":"bu_field_ops","user_id":D} → 201; as D POST /api/v1/data/sys_user_position {"user_id":T,"position":"contributor","business_unit_id":"bu_west_coast"}. Expected 2xx; actual 403 PERMISSION_DENIED "… outside the delegated subtree". Seeded sys_business_unit rows still read organization_id: null; stamping the org onto them flips D's create to 201.

api-backend.rest-metadata-config-contract A4 — authorization class. Detail withheld pending maintainer (RUNNER rule 2). Verifier V1: CONFIRMED (narrower: no data values cross the boundary).

automation.trigger-status-contract A5 / A6 / A7 — resume refusals put status-derived codes on the wire. Admin POST /api/v1/automation/showcase_reassign_wizard/trigger {"recordId":{a task id}} → 200 runId; then on POST /api/v1/automation/showcase_reassign_wizard/runs/{runId}/resume: {"inputs":{}} → 400 VALIDATION_ERROR (expected INVALID_SCREEN_INPUT); {"inputs":{"new_assignee":"x"},"output":{"$User":{}}} → 400 VALIDATION_ERROR (expected INVALID_SIGNAL); …/runs/run_nope/resume → 404 RESOURCE_NOT_FOUND (expected RUN_NOT_FOUND); resuming a run whose flow was deleted → 404 RESOURCE_NOT_FOUND. The run stays paused and statuses are right; the SDK's err.code therefore never carries the documented codes (A7). Verifier V3: CONFIRMED.

platform-core.manifest-install-contract A2 — admin POST /api/v1/packages {"manifest":{"id":"com.example.qa-old","name":"Old","version":"1.0.0","scope":"project","type":"app","engines":{"protocol":"^16"}}}. Expected a 4xx carrying requiredRange, rangeSource, protocolVersion, targetMajor, migrateCommand; actual 500 {code:"OS_PROTOCOL_INCOMPATIBLE", message, httpStatus:500} with the fields only inside the prose. The refusal itself holds (nothing installed, A1 passes). Verifier V4: CONFIRMED.

platform-core.marketplace-install-local-lifecycle A5 — boot with OS_CLOUD_URL=off from a scratch copy of the showcase; os package install {examples/app-crm/dist/objectstack.json} -r http://localhost:{p}; admin POST /api/v1/marketplace/install-local/com.example.crm/purge-sample-data {}. Expected {deleted, skipped, errors}; actual 500 DRIVER_UNAVAILABLE "driver service unavailable — cannot purge.", nothing deleted. Verifier V4: CONFIRMED, and found a second fault behind it (below).

Checklist clauses (no product defect)

item · clause disposition what holds instead source
access-security.share-link-capability-tokens A5 (record-gone leg) stale clause a deleted record's link answers 404 INVALID_OR_EXPIRED, byte-identical to an unknown token (the delete cascades the link row; fail-closed so "record gone" is not readable); 410 RECORD_GONE is race-only share-link-service (#5190)
ai.agent-tool-skill-metadata-roundtrip A4 assertion defect a draft PUT on a package-shipped skill/tool is 403 NOT_OVERRIDABLE; a runtime-created name drafts 200 ee58392e1 (#6608), predates the clause's rev 3
api-backend.batch-transactional-discovery A5 assertion defect a per-object batch stops at the first failure by default (NOT_ATTEMPTED tail); options.continueOnError:true gives "neither blocks the other" batch.zod.ts continueOnError default, 744b8f5f5 (#7581)
api-backend.server-timing-admin-gated A2 / A3 assertion defect the item inverts the modes: OS_SERVER_TIMING=true sends spans to every caller; env off + X-OS-Debug-Timing is admin-only; the SQL-shape detail header is admin-only in both (verified) hono-plugin.ts:83-104,300-353, #3163 / #3169
identity-auth.two-factor-enrollment-reveal A6 stale clause sys_user.enable_two_factor declares a resultDialog (QR + code list), no successMessage 266654d82e (#11110, fixes #10681)
identity-auth.two-factor-backup-codes A6 stale clause generate_backup_codes declares a resultDialog 266654d82e (#11110)
integration-system.external-schema-introspection A1 assertion defect columnCount is 7 per table (the fixture's initObjects adds created_at / updated_at) fixture external-fixture.ts:36-45
integration-system.external-schema-introspection A3 stale clause the remote PK is rendered as a comment, not fields.{f}.primaryKey; ObjectSchema is a value import for ObjectSchema.create 4257e4e4e3 (#11073, ruling D of #11000)
platform-core.activation-ledger-registration-home A5 assertion defect the platform-objects array holds 46 names (46 at 17.6.0 too); the one-owner assertion holds platform-object-names.ts
platform-core.marketplace-install-local-lifecycle A7 stale clause uninstall hot-withdraws the package from the running kernel, no restart 901e7cf13 (#21581)
records-forms.field-unique-enforcement A1 stale clause the memory driver is no longer a boot store; on SQL a bare unique:true is the composite (organization_id, field) and the 409 names the object, never a guessed column 9a4182a75 (#21598); duplicate-record-error.ts

Partial-coverage gaps (named, not dropped)

Fixed since the last run

Close-out (extracted cards, checklist-accuracy findings) follows in a comment.


Generated by Claude Code

Activity

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