Skip to content

QA run · api-backend (22/27) · 5b14b7f3 · 2026-10-19 · 20 PASS / 1 PARTIAL / 1 FAIL / 0 BLOCKED / 5 NOT-RUN #24541

Closed as not planned

Description

@objectstack-fleet

Run record for the 18.0 release QA wave (dispatch session session_01CfRDy7SuTfUqaTu2AEH2Hi; maintainer-approved plan B: Tier 1 + Tier 2, Tier 3 deferred). Runner session session_016CErRJhdMYZdRg4pe8iQfD. Protocol: .claude/skills/checklist-test/SKILL.md + docs/qa/platform-checklist/RUNNER.md.

Environment fingerprint

  • framework: 5b14b7f3ad8e2e0786d228772f473d07b36b2477 (pinned; pnpm install --frozen-lockfile + pnpm build, 76/76 tasks green)
  • .objectui-sha: 4016370af3c9c9dafec2bc5299afd8e8079701b8; console built with pnpm objectui:build (shallow clone into .cache/objectui-4016370af3c9), packages/console/dist/.objectui-sha matches, pnpm check:console-sha green
  • resolver: node scripts/checklist-select.mjs area:api-backend --json → 27 runnable · 0 blocked hidden · 0 planned
  • app: showcase · boot OS_PORT=P objectstack dev --ui --seed-admin -p P -d file:…/ITEM.db · per-runner port range and per-item file DB · seeded admin + demo personas; staged configs only in scratch copies of the app
  • browser: Playwright on /opt/pw-browsers/chromium, headless, one context per persona
  • timestamp: 2026-10-19 (UTC) · execution: parallel fan-out, one sub-agent runner per item group:
    • A1: ports [41300,41301,41302] · env 3 min / test 12 min
    • A2: ports [41310] · env 3 min / test 9 min
    • A3: ports [41360,41361] · env 3 min / test 13 min
    • A4: ports [41370,41371,41372] · env 9 min / test 15 min

Scope

Selector area:api-backend · 27 runnable item(s) (revision = the one each verdict is valid for):

  • api-backend.batch-transactional-discovery r5 · P1 · api · Tier 2 → pass (runner A1)
  • api-backend.formula-gates r2 · P1 · build · Tier 2 → pass (runner A2)
  • api-backend.enforce-or-remove-authoring-gates r4 · P1 · build · Tier 2 → pass (runner A2)
  • api-backend.server-timing-admin-gated r4 · P2 · api · Tier 3 → not-run
  • api-backend.query-contract-matrix r3 · P0 · api · Tier 1 → pass (runner A3)
  • api-backend.error-envelope-ledger r4 · P1 · api · Tier 2 → pass (runner A1)
  • api-backend.bulk-write-contract r2 · P1 · api · Tier 1 → pass (runner A3)
  • api-backend.route-ledger-live-parity r4 · P2 · api · Tier 3 → not-run
  • api-backend.declarative-endpoint-execution r3 · P1 · api · Tier 1 → pass (runner A3)
  • api-backend.package-rest-lifecycle r3 · P2 · api · Tier 3 → not-run
  • api-backend.api-console-discovery-execute r2 · P2 · browser · Tier 3 → not-run
  • api-backend.filter-comparand-conformance r3 · P1 · api · Tier 2 → pass (runner A1)
  • api-backend.date-range-preset-matrix r2 · P2 · api · Tier 3 → not-run
  • api-backend.retired-def-refusal r2 · P1 · build · Tier 2 → pass (runner A2)
  • api-backend.packaged-action-disabled-dispatch r3 · P0 · api · Tier 1 → pass (runner A3)
  • api-backend.action-activation-door-contract r2 · P2 · api · Tier 1 → pass (runner A4)
  • api-backend.aggregate-contract-matrix r2 · P1 · api · Tier 2 → partial (runner A1)
  • api-backend.formula-stdlib-matrix r2 · P1 · mixed · Tier 2 → pass (runner A2)
  • api-backend.api-methods-verb-gate r1 · P1 · api · Tier 2 → pass (runner A1)
  • api-backend.rest-crud-config-contract r2 · P2 · api · Tier 1 → pass (runner A4)
  • api-backend.rest-batch-config-contract r2 · P2 · api · Tier 1 → pass (runner A4)
  • api-backend.rest-metadata-config-contract r4 · P1 · api · Tier 1 → pass (runner A4)
  • api-backend.rest-route-generation-tombstones r1 · P2 · build · Tier 1 → pass (runner A4)
  • api-backend.second-object-exposure-and-internal-fields r1 · P1 · api · Tier 1 → pass (runner A3)
  • api-backend.data-request-shape-and-query-arity r1 · P1 · api · Tier 1 → pass (runner A3)
  • api-backend.meta-read-doors-v18 r1 · P2 · api · Tier 1 → pass (runner A4)
  • api-backend.error-sentences-and-unique-violation-wire-code r1 · P2 · api · Tier 1 → fail (runner A4)

Per-clause verdicts

item clause short verdict evidence
api-backend.batch-transactional-discovery acc[0] discovery capability agrees with live atomic batch pass GET /discovery capabilities.transactionalBatch = {enabled:true, description:'Atomic cross-object batch endpoint ...'}; atomic batch [create note qa-b…
api-backend.batch-transactional-discovery acc[1] top-level atomic:false -› 400 BATCH_NOT_ATOMIC pass 400 {code:BATCH_NOT_ATOMIC, error:'Cross-object batch is always atomic; use POST /data/:object/batch for non-atomic per-object batches'}; neither qa-…
api-backend.batch-transactional-discovery acc[2] failing member rolls whole batch back pass [note, invoice missing name, task] -› 400 VALIDATION_FAILED, re-reads qa-b4-note/qa-b4-task count=0; runtime-failure variant [create note, update tas…
api-backend.batch-transactional-discovery acc[3] oversize batch 400 BATCH_TOO_LARGE, nothing created pass 201 ops -› 400 {code:BATCH_TOO_LARGE, count:201, max:200}; qa-b5-over count=0
api-backend.batch-transactional-discovery acc[4] per-object door non-atomic, continueOnError semantics pass continueOnError:true -› total 3 succeeded 2 failed 1, row1 VALIDATION_FAILED 'Title is required', rows 0 and 2 persisted; default options -› succeede…
api-backend.batch-transactional-discovery neg[0] doors not conflated pass atomic:false refused on /batch (not accepted-and-ignored); per-object door kept valid row 0 (no silent rollback)
api-backend.formula-gates acc[0] runtime shapes correct against BUILT package pass harness resolved @objectstack/formula -› packages/formula/dist/index.js (dist mtime 12:30 › src 12:24); record.due_date('2026-10-19')==today()@2026-1…
api-backend.formula-gates acc[1] date arithmetic is build-time error pass scratch showcase copy + showcase_project.qa_duration_days = celrecord.end_date - record.start_date + 1: os build EXIT 1, '✗ Author-time rules faile…
api-backend.formula-gates acc[2] build error located at object/field pass "object 'showcase_project' · field 'qa_duration_days' expression: date arithmetic ... Use daysBetween(a, b) ... — source: `record.end_date - record…
api-backend.formula-gates acc[3] untouched showcase builds exit 0 pass byte-identical scratch copy of examples/app-showcase (uses record.f_date ‹ today() etc.): os build EXIT 0, 'Build complete', 24 Objects 210 Fields,…
api-backend.formula-gates neg[0] harness must not load src pass RESOLVED /home/user/objectstack/packages/formula/dist/index.js (realpath identical) — no src/ path
api-backend.enforce-or-remove-authoring-gates acc[0] tombstoned keys rejected; filter op runtime-refused pass built @objectstack/spec dist: QuerySchema cursor/joins/distinct/windowFunctions all success=false (baseline {object} true); EnhancedApiError fieldErr…
api-backend.enforce-or-remove-authoring-gates acc[1] each rejection names replacement pass cursor: 'Express the keyset as an ordinary where predicate on your sort key'; joins: 'Related records are read through expand'; fieldErrors: 'ren…
api-backend.enforce-or-remove-authoring-gates acc[2] documented-strip control strips; includeObjects refused pass RestServerConfigSchema.safeParse({routes:{someUnknownKey:1}}) success data {"routes":{}}; RouteGenerationConfigSchema docblock rest-server.zod.ts:648…
api-backend.enforce-or-remove-authoring-gates acc[3] ≥3 registries sampled pass query schema (data/query.zod.ts retiredKey x4), error envelope (api/errors.zod.ts fieldErrors), RETIRED_FILTER_OPERATORS (data/filter.zod.ts $regex,$…
api-backend.enforce-or-remove-authoring-gates neg[0] strip deliberate; no tombstone parses clean pass every sampled tombstone failed parse; only the documented non-strict routes unknown key stripped
api-backend.query-contract-matrix acc[0] every operator: exact id set, both spellings pass live, baseline GET showcase_account 14 rows; 21 variants × 3 doors (POST $-object, POST AST array, GET $filter AST) all set-equal on ids: eq 9, ne 5,…
api-backend.query-contract-matrix acc[1] pagination windowed slices pass GET $orderby=name&$top=3&$skip=2 → [Fabrikam,Globex,Hooli] = baseline[2:5]; $top=4&$skip=9 → [Umbrella Health,Vandelay Industries,Wayne Enterprises,W…
api-backend.query-contract-matrix acc[2] $select narrows; dotted field refused INVALID_FIELD pass GET $select=name,status and POST fields:['name','status'] → all 14 records key set exactly {name,status}; POST showcase_invoice fields:['account.name…
api-backend.query-contract-matrix acc[3] full sort both ways; INVALID_SORT pass annual_revenue asc/desc full 14-id sequence equals locally sorted baseline on GET $orderby and POST orderBy; $orderby=no_such_field and POST orderBy …
api-backend.query-contract-matrix acc[4] expand honors target RLS/FLS (both personas) pass contributor-bound member (qa-contributor-bound-member recipe; sees 0 of 12 seeded invoices) created own INV-A3-001 with contact=Carl Fox; contributor…
api-backend.query-contract-matrix acc[5] scalar comparand refused on both doors pass POST {where:{status:{$nin:'done'}}} → 400 VALIDATION_FAILED fields[0].field 'query.where.status.$nin' message names $nin, status, ARRAY; POST AST ['s…
api-backend.query-contract-matrix acc[6] unknown inputs get ledgered codes pass ?$pageSize=5 → 400 UNSUPPORTED_QUERY_PARAM listing $top,$skip,$orderby,$select,$count,$search,$searchFields,$filter,$expand; ?not_a_field=x → 400 INV…
api-backend.query-contract-matrix acc[7] $in [] zero rows, $nin [] full set pass showcase_task (10 rows): $in [] → 200, 0 rows (POST obj, POST AST, GET); $nin [] → 200, 10 rows = full id set (POST obj + AST)
api-backend.query-contract-matrix acc[8] every variant has a recorded verdict pass all 16 op variants (+like verbatim, date, unicode) and params $top,$skip,$select,$orderby,$filter,$expand (list GET $expand=account → embedded accoun…
api-backend.query-contract-matrix neg[0] no silent widening on malformed body pass POST {limit:'ten'} → 400 VALIDATION_FAILED query.limit; POST {not_a_query_key:{x:1}} → 400 INVALID_FIELD; no response carried rows
api-backend.error-envelope-ledger acc[0] every sampled code is in ErrorCode pass VALIDATION_FAILED, UNAUTHENTICATED, PERMISSION_DENIED, OBJECT_NOT_FOUND, RECORD_NOT_FOUND, BATCH_NOT_ATOMIC, UNSUPPORTED_QUERY_PARAM all ErrorCode.sa…
api-backend.error-envelope-ledger acc[1] validation sample has fields[] name/required pass POST showcase_invoice {} -› 400 {code:VALIDATION_FAILED, fields:[{field:'name',code:'required',message:'Invoice Number is required',label:'Invoice Nu…
api-backend.error-envelope-ledger acc[2] no fieldErrors key in any body pass grep of all 7 captured bodies: no 'fieldErrors'
api-backend.error-envelope-ledger acc[3] status matches code family pass 400 VALIDATION_FAILED/BATCH_NOT_ATOMIC/UNSUPPORTED_QUERY_PARAM, 401 UNAUTHENTICATED, 403 PERMISSION_DENIED, 404 OBJECT_NOT_FOUND/RECORD_NOT_FOUND; no…
api-backend.error-envelope-ledger acc[4] two 404 flavors distinguishable pass not_a_real_object -› 404 OBJECT_NOT_FOUND "Object 'not_a_real_object' is not registered"; showcase_task/nonexistent-id-0000 -› 404 RECORD_NOT_FOUND "…
api-backend.error-envelope-ledger acc[5] one sample per family captured pass 7/7 families: validation, 401 (anon GET showcase_private_note), 403 (Mei POST showcase_announcement -› PERMISSION_DENIED; identity proven via get-ses…
api-backend.error-envelope-ledger neg[0] no 500 for caller-fixable input, no 2xx pass all 7 probes 4xx
api-backend.bulk-write-contract acc[0] createMany parity with single door pass baseline member (admin create-user, no position): createMany bare array of 3 → 201; {records} wrapper → 400 VALIDATION_FAILED; createMany row vs sing…
api-backend.bulk-write-contract acc[1] updateMany touches only named rows pass updateMany {records:[{id,data:{body:'A3-UPDATED'}}×3]} → total 3 succeeded 3; re-read: 3 markers updated, 4th own note body null, admin-owned foreign…
api-backend.bulk-write-contract acc[2] nonexistent/foreign id calm per-row RECORD_NOT_FOUND pass member updateMany foreign admin note alone → 200 success false, RECORD_NOT_FOUND; nonexistent alone → RECORD_NOT_FOUND (identical code); both with op…
api-backend.bulk-write-contract acc[3] 201 records → 400 BATCH_TOO_LARGE, zero rows pass admin createMany 201 → 400 BATCH_TOO_LARGE count 201 max 200; query A3-CAP-* → 0 rows; /batch create 201 → 400 BATCH_TOO_LARGE
api-backend.bulk-write-contract acc[4] deleteMany id-exact, per-row delete gate pass member deleteMany 2 own ids → row0 PERMISSION_DENIED, row1 NOT_ATTEMPTED, nothing deleted (single DELETE 403); {where} → 400 naming ids; admin delete…
api-backend.bulk-write-contract acc[5] no ERR_BULK_RESULT_MISMATCH pass grep of all captured responses and both boot logs → 0 hits
api-backend.bulk-write-contract neg[0] invisible row neither counted nor mutated pass foreign note → RECORD_NOT_FOUND same as nonexistent, succeeded 0, row unchanged
api-backend.declarative-endpoint-execution acc[0] authed 200 + Cache-Control private, max-age=30 pass live GET /api/v1/apps/showcase/tasks (admin bearer) → 200, cache-control: private, max-age=30, body {success,data:{object:'showcase_task',records:[…]…
api-backend.declarative-endpoint-execution acc[1] anonymous → 401 UNAUTHENTICATED pass live unauth GET → 401 code UNAUTHENTICATED, no cache-control header; declarative-endpoint-policy.dogfood 8/8 passed ('an OMITTED authRequired denies …
api-backend.declarative-endpoint-execution acc[2] script/proxy refused at authoring; runtime 501 pinned pass scratch config (baseline validate exit 0) + type 'script' and 'proxy' endpoints → os validate exit 1: '✗ apis.3.type: Endpoint 'qa_a3_script_api' (ap…
api-backend.declarative-endpoint-execution acc[3] unmatched /apps path → transport 404 pass GET /api/v1/apps/showcase/nope → 404 ENDPOINT_NOT_FOUND (authed and anon)
api-backend.declarative-endpoint-execution neg[0] no anonymous serving with authRequired default pass anon → 401
api-backend.filter-comparand-conformance acc[0] every accepted comparand type accepted with known answers pass REST POST /query on showcase_field_zoo (2 rows): string name='Specimen — Full' -› 1 [Full]; number f_number $gt 100 -› 1 [Full]; boolean true -› [Ful…
api-backend.filter-comparand-conformance acc[1] non-accepted type refused, located, prescriptive pass POST {f_number:{$eq:{x:1}}} -› 400 VALIDATION_FAILED fields[query.where.f_number.$eq] 'Filter comparand is a plain object ... must be a string, numbe…
api-backend.filter-comparand-conformance acc[2] bigint exact-limit enforced at in-process door pass engine-comparand-type-door.test.ts 12/12 incl. 'refuses an oversized bigint with the envelope, and NO driver read runs'; 'a bigint beyond ±2^53 is re…
api-backend.filter-comparand-conformance acc[3] dotted heads classified and handled pass relation f_lookup.name -› 400 'follows the relationship ... nest the condition beneath the relation field'; virtual f_formula.x -› 400 INVALID_FIELD …
api-backend.filter-comparand-conformance acc[4] refusal is contract-level across doors pass same plain-object comparand: POST /query 400 VALIDATION_FAILED fields[query.where.f_number.$eq]; GET ?$filter= 400 INVALID_FILTER 'Filter comparand a…
api-backend.filter-comparand-conformance neg[0] rejected predicate never dropped to full table pass every bad comparand answered 400 with no records
api-backend.filter-comparand-conformance neg[1] no cross-type coercion where contract refuses pass f_number $gt 'abc' -› 400 INVALID_FILTER on POST and GET; f_number '420' / $eq '420' -› 1 row is the declared numeric-string grammar (filter-number-c…
api-backend.filter-comparand-conformance neg[2] past-limit bigint not answered rounded pass in-process door refuses beyond ±2^53 in all 5 driver suites + engine
api-backend.filter-comparand-conformance neg[3] scalar dotted head not traversed pass name.x -› 400 INVALID_FIELD
api-backend.retired-def-refusal acc[0] every sampled retired def refused at os build pass minimal scratch stack baseline EXIT 0 (agent-without-lifecycle control also EXIT 0); 17 data/ExternalDataSource import EXIT 2; 18 automation/Schedule…
api-backend.retired-def-refusal acc[1] prescription refusals distinguishable from generic control pass carriers: 'manifest.loading: manifest.loading was removed in @objectstack/spec 17.0.0 (ADR-0049 ...) ... Delete the key. Plugins are composed at bo…
api-backend.retired-def-refusal acc[2] runtime door refuses same types as build pass live boot :41310 as admin: PUT /meta/agent/qa_agent (with lifecycle, and without) 403 'Metadata type agent is code-only'; PUT /meta/external_data_sou…
api-backend.retired-def-refusal acc[3] sample spans both version prefixes pass registry 224 entries: 53 at prefix 17, 171 at prefix 18; sample = 17 data/ExternalDataSource(R3, none), 17 kernel/PluginLoadingConfig(carrier manifes…
api-backend.retired-def-refusal neg[0] no retired def parses clean and dropped pass all 5 sampled defs non-zero exit; no artifact emitted for them
api-backend.retired-def-refusal neg[1] no bare unknown-type where prescription authored pass both carrier defs answered with their tombstone prescription, not the root Unrecognized-key text
api-backend.retired-def-refusal neg[2] no build/runtime door disagreement pass see acceptance[2] table
api-backend.retired-def-refusal neg[3] no wrong successor named pass manifest.loading -› defineStack plugin composition; agent.lifecycle -› skill/Flow/state_machine rule; both match their entry files and ADR text
api-backend.packaged-action-disabled-dispatch acc[0] REST door 409 ACTION_DISABLED, no side effect pass live :41360 — POST /actions/showcase_task/showcase_mark_done {recordId:'no-such-record-0000'} and {recordId:‹real seeded task BDTORUgoFI53x3WE›} both…
api-backend.packaged-action-disabled-dispatch acc[1] activation consult precedes param contract (contrast) pass live: identical request {recordId:'no-such-zoo-0000',params:{bogus_key:1}} to showcase_action_param_gallery — enabled(before) 400 VALIDATION_ERROR 'I…
api-backend.packaged-action-disabled-dispatch acc[2] consult precedes record load (absence-proven) pass live: both disabled traces are 409 with a nonexistent recordId present; real-id disabled call left the record untouched (snapshot equal). Run-record …
api-backend.packaged-action-disabled-dispatch acc[3] 403 never an oracle for the switch pass live: showcase_zoo_perm_missing as admin enabled vs disabled → both 403 PERMISSION_DENIED 'requires capability [showcase.restricted_ops] — caller is …
api-backend.packaged-action-disabled-dispatch acc[4] MCP run_action refuses with same envelope, re-arms pass live POST /api/v1/mcp tools/call run_action {actionName:'showcase_portfolio_snapshot'}: enabled → ok:true result{accounts:14,projects:5,invoices:13};…
api-backend.packaged-action-disabled-dispatch acc[5] switch durable across restart; row updated in place pass live: server killed and rebooted on same file DB (:41360); post-restart showcase_mark_done 409 ACTION_DISABLED (and showcase_bulk_reassign 409); re-e…
api-backend.packaged-action-disabled-dispatch acc[6] flow-type action refused by its own switch pass live: disable showcase_bulk_reassign → POST /actions/showcase_task/showcase_bulk_reassign 409 ACTION_DISABLED naming showcase_bulk_reassign; GET /aut…
api-backend.packaged-action-disabled-dispatch neg[0] no 400/handler answer for a disabled action pass every disabled invocation (mark_done, param_gallery w/ garbage params, bulk_reassign, portfolio_snapshot) answered 409, never 400/200
api-backend.packaged-action-disabled-dispatch neg[1] 403 wins over 409; no ACTION_DISABLED without a row pass 403 bodies identical enabled/disabled; with an empty ledger (GET sys_metadata_activation → total 0) enabled calls answered their normal shapes (param…
api-backend.packaged-action-disabled-dispatch neg[2] anonymous floor 401 pass anonymous POST /actions/showcase_task/showcase_mark_done → 401 UNAUTHENTICATED
api-backend.action-activation-door-contract acc[0] authority first: non-admin 403, anonymous 401 pass phone.demo@example.com (session verified) POST /actions/_activation/showcase_task/no_such_action {"enable":false} → 403 {code:PERMISSION_DENIED,messa…
api-backend.action-activation-door-contract acc[1] 2-segment door 400 shape sentence; 4-segment router 404 pass POST /actions/_activation/showcase_mark_done {} → 400 {code:VALIDATION_ERROR,message:'Path must be /actions/_activation/:object/:action (use global…
api-backend.action-activation-door-contract acc[2] body contract refuses, never inverts pass {"enable":false} → 400 VALIDATION_FAILED details.fields[0]={field:enable,code:unknown_field,message:'… did you mean enabled?'}; {"enabled":"false"}…
api-backend.action-activation-door-contract acc[3] empty body enables pass POST …/showcase_task/showcase_mark_done {} → 200 {success:true,data:{name:showcase_mark_done,objectName:showcase_task,enabled:true}}
api-backend.action-activation-door-contract acc[4] undeclared 404; refused probes write no row pass admin …/no_such_action {"enabled":false} → 404 {code:RESOURCE_NOT_FOUND,message:"Action 'no_such_action' on 'showcase_task' has no declaration — ther…
api-backend.action-activation-door-contract acc[5] happy path writes one row, no organization_id key, re-enable updates pass {"enabled":false} 200 → ledger total 1, row KjAB3v4BBIBA0QTo action showcase_mark_done active=false, keys=[active,created_at,created_by,id,metadata_t…
api-backend.action-activation-door-contract acc[6] ambiguity arm 409 RESOURCE_CONFLICT, no write (pin) pass oracle=test (no stock fixture): runtime action-activation-posture-gate.test.ts 'REFUSES an ambiguous name instead of switching off artifacts the call…
api-backend.action-activation-door-contract acc[7] 501 no projection, 503 non-durable (pins) pass posture-gate pin 'says so plainly when the engine has no activation ledger at all' ✓ and 'reports a write that could not be made durable, instead of …
api-backend.action-activation-door-contract neg[0] {enable:false} never 200 pass answered 400 unknown_field; ledger unchanged (0 rows)
api-backend.action-activation-door-contract neg[1] non-manage_metadata caller never sees body 400/decl 404 pass non-admin mis-bodied undeclared probe → 403 only; message names no positions/sets
api-backend.action-activation-door-contract neg[2] no refused arm leaves a ledger row pass 0 rows after 2 authority, 2 shape, 3 body, 1 declaration refusals
api-backend.action-activation-door-contract neg[3] _activation never read as invocation pass 2-segment _activation path answered the door's shape 400, not an action-invocation body
api-backend.aggregate-contract-matrix acc[0] 6 functions known answers grouped+ungrouped, count-all vs count-field pass 17 baseline accounts; per-function grouped-by-status and ungrouped values all MATCH local computation (e.g. sum active 609100000, avg active 67677777…
api-backend.aggregate-contract-matrix acc[1] 5 granularities ISO shapes, Monday weeks, real-null bucket pass clock 2026-10-19T12:46Z, TZ UTC; day/week/month/quarter/year bucket keys+counts all MATCH local ISO computation (14/13/12/8/3 distinct non-null bucke…
api-backend.aggregate-contract-matrix acc[2] empty-set identities on empty-where and measure filter pass empty where ungrouped -› {count:0,sum:0,avg:null,min:null,max:null,count_distinct:0}, grouped -› []; aggregations[].filter matching nothing, grouped …
api-backend.aggregate-contract-matrix acc[3] retired fns prescriptions vs unknown enum listing pass array_agg and string_agg -› 400 VALIDATION_FAILED fields[query.aggregations.0.function] 'array_agg was removed ... Run os migrate meta --from 16 …
api-backend.aggregate-contract-matrix acc[4] aggregate secured for restricted persona pass contributor-bound member (invited sign-up + sys_user_position contributor, one own invoice): own baseline 1 row {draft:1}, grouped count -› [{draft:1…
api-backend.aggregate-contract-matrix acc[5] all 11 variants carry recorded verdict pass 6 function rows + 5 granularity rows recorded; all 5 granularities answer-discriminating after seeding 3 accounts (2026-01-04 null revenue, 2024-12-3…
api-backend.aggregate-contract-matrix neg[0] refused aggregation never degrades to raw rows pass all refusals 400 with error bodies, no records array
api-backend.aggregate-contract-matrix neg[1] nonexistent aggregation field refused pass sum over no_such_field -› 400 INVALID_FIELD 'Unknown field ... sum answered 0 ...'; groupBy no_such_field -› 400 INVALID_FIELD
api-backend.aggregate-contract-matrix neg[2] pushdown vs in-memory labels agree not-run timezone lever not exercised; only the UTC path observed (path not observable on this boot)
api-backend.formula-stdlib-matrix acc[0] 29 functions known answers; docs match pass source re-count registerStdLib = 29 registerFunction calls (now..isEmpty, can outside); formulas.mdx table 19 rows / 29 names; registered-not-docum…
api-backend.formula-stdlib-matrix acc[1] calendar-day trio uses reference tz pass now=2026-08-30T22:00:00Z tz Asia/Shanghai: today()=2026-08-31T00:00:00.000Z, daysFromNow(1)=09-01, daysAgo(1)=08-30, isoDate(today())='2026-08-31'; n…
api-backend.formula-stdlib-matrix acc[2] documented sharp edges hold pass addMonths(date('2026-01-31'),1)=2026-02-28T00:00Z; floor(-1.2)=-2 ceil(-1.2)=-1; joinNonEmpty([record.a..d],'-') with {a,null,' ',b}='a-b' (literal m…
api-backend.formula-stdlib-matrix acc[3] mixed arithmetic promotes; int/int integer pass record.amount(250.5)/100=2.505; record.amount(1.25)*2=2.5; 7/2=3
api-backend.formula-stdlib-matrix acc[4] same evaluator serves live read path pass live :41310: GET showcase_project budget_remaining 2000/180000/90000 (=budget-spent); showcase_field_zoo f_formula 315, 3.5; scratch object qa_fx_pro…
api-backend.formula-stdlib-matrix acc[5] unregistered function refused 422 at authoring door pass PUT /meta/object/qa_fx_sqrt{1,2} (active) bad_f=sqrt(4) -› 422 code INVALID_METADATA issue rule expression-invalid path "object 'qa_fx_sqrt1' · field…
api-backend.formula-stdlib-matrix neg[0] harness not loading src pass RESOLVED packages/formula/dist/index.js
api-backend.formula-stdlib-matrix neg[1] today() no wall-clock / UTC-day drift pass today() values all exact UTC midnight; Shanghai run returned zone day, not UTC day
api-backend.formula-stdlib-matrix neg[2] unregistered fn never saves 2xx pass active save 422 x2, promotion 422, nothing stored
api-backend.api-methods-verb-gate acc[0] 404 apiEnabled:false vs 405 whitelist-miss fork pass [system objects] admin GET /data/sys_oauth_consent (and /abc) -› 404 OBJECT_API_DISABLED "Object 'sys_oauth_consent' is not exposed via the API"; PAT…
api-backend.api-methods-verb-gate acc[1] 405 allowed[] is effective closure in API_OPERATION_ORDER pass [scratch qa_verb_gate_probe ['get','list','create']] PATCH/DELETE -› 405 allowed ["get","list","create","aggregate","search","import","export"] == lo…
api-backend.api-methods-verb-gate acc[2] three-state: undefined open, []/stripped/non-array deny-all, subset pass [scratch] no apiMethods -› PATCH 200 + DELETE 200; authored [] -› GET one 405 allowed:[]; ['upsert'] stripped -› list/get/create/update all 405 allow…
api-backend.api-methods-verb-gate acc[3] bulk∧child and writeMode-precise import pass [scratch] without bulk: createMany -› 405 'bulk'; with ['get','list','create','bulk']: createMany 201, updateMany 405 'update', per-object batch upda…
api-backend.api-methods-verb-gate acc[4] legacy values stripped-and-warned, not rejected pass PUT ['upsert'] -› 200; log: "[spec] enable.apiMethods declares retired legacy value(s) [upsert] ... upsert: declare ['create','update'] — upsert …
api-backend.api-methods-verb-gate acc[5] object gate answers before caller authz (405 before 403) pass [sys_session] PATCH as admin, as Mei (own session and another's) -› identical 405 allowed [get,list,aggregate,export]; anonymous -› 401 UNAUTHENTICAT…
api-backend.api-methods-verb-gate acc[6] cross-object batch gated per-op before txn pass POST /batch [create showcase_task 'qa-vg-batch-task', update sys_session] atomic -› 405 "API operation 'bulk' is not allowed on object 'sys_session'"…
api-backend.api-methods-verb-gate neg[0] no write-then-refuse on refused ops pass every 405 was followed by a re-read: sys_session revoke_reason null, probe row name 'r1' unchanged after refused PATCH/import-update/updateMany, batc…
api-backend.api-methods-verb-gate neg[1] allowed[] never raw whitelist, never restore/purge pass allowed[] carries derived aggregate/search/import/export beyond raw ['get','list','create']; restore/purge absent on every captured body incl. unrest…
api-backend.api-methods-verb-gate neg[2] internal callers not filed as bypass pass no internal-path write was scored; only external REST doors probed
api-backend.api-methods-verb-gate neg[3] legacy value not hard-rejected at parse pass PUT ['upsert'] and ['get','history'] both answered 200 (strip-and-warn)
api-backend.rest-crud-config-contract acc[0] stock: six default data mounts answer pass admin :41370 showcase_task: GET list 200, POST create 201 (id u_dy0FFxGmPlXJA2), GET /:id 200, POST /query 200, PATCH /:id 200, DELETE /:id 200 {succ…
api-backend.rest-crud-config-contract acc[1] create/read/update/delete remove one; list removes two pass harness diffs, added=[]: create → POST /data/:object; read → GET /data/:object/:id; update → PATCH …/:id; delete → DELETE …/:id; list → GET /data/:ob…
api-backend.rest-crud-config-contract acc[2] unmounted route distinguishable from OBJECT_API_DISABLED pass switched-off op: no handler in the RestServer table (harness); routing 404 control body {success:false,error:{code:ENDPOINT_NOT_FOUND,message:'Not fo…
api-backend.rest-crud-config-contract acc[3] dataPrefix re-bases data surface and discovery pass harness {crud:{dataPrefix:'/records'}}: 0 routes under /api/v1/data; 22 under /api/v1/records = the full baseline data family (CRUD, query, clone, ex…
api-backend.rest-crud-config-contract acc[4] crud.patterns and objectParamStyle refused at construction pass 'crud does not satisfy CrudEndpointsConfigSchema … crud.patterns was removed … crud.dataPrefix is the one live knob … an endpoint on a custom…
api-backend.rest-crud-config-contract acc[5] schema defaults are the only defaults; partial ops kept pass pin §C/§D ✓ ('KEEPS a partial crud.operations'); harness empty → crud {operations: all five true, dataPrefix:'/data'}; {operations:{create:false}} …
api-backend.rest-crud-config-contract neg[0] no route stays mounted with switch false pass every crud switch-off table lacks exactly its route(s)
api-backend.rest-crud-config-contract neg[1] absence never scored from bare 404 pass absences scored from the route table + the control body, all live probes authenticated
api-backend.rest-batch-config-contract acc[0] stock: four per-object bulk doors mounted pass admin :41370 showcase_private_note: POST …/batch 200 {success:true,operation:update,total:0}, /createMany 201 {records:[],count:0}, /updateMany 200, …
api-backend.rest-batch-config-contract acc[1] enableBatchEndpoint gates only per-object /batch pass harness diff enableBatchEndpoint:false → removed ['POST /api/v1/data/:object/batch'], added []; 'POST /api/v1/batch' still mounted (true). Pin §1 'ba…
api-backend.rest-batch-config-contract acc[2] each *Many removes own mount; gates AND protocol member pass harness: createMany/updateMany/deleteMany false each remove exactly POST …/createMany | /updateMany | /deleteMany; protocol without batchData/creat…
api-backend.rest-batch-config-contract acc[3] maxBatchSize is the one cap for all five doors pass pin rest-batch-size-cap.test.ts 8/8 ✓ (incl. 'the cap follows the deployment config, not a hardcoded 200', 'cross-object batch … BATCH_TOO_LARGE'); h…
api-backend.rest-batch-config-contract acc[4] live: 201 records → 400 BATCH_TOO_LARGE, nothing created pass POST /data/showcase_private_note/createMany 201 rows → 400 {error:'Batch too large: 201 records (max 200)',code:BATCH_TOO_LARGE,count:201,max:200}; q…
api-backend.rest-batch-config-contract acc[5] upsertMany and defaultAtomic (true/false) refused pass constructor throws 'batch does not satisfy BatchEndpointsConfigSchema … batch.operations.upsertMany was removed … Upsert is an operation type o…
api-backend.rest-batch-config-contract acc[6] maxBatchSize bounds 0/2000/2.5 refused; empty → 200 pass pin §A 3 refusals ✓ + §C 'an empty config still constructs, with the declared defaults' ✓; harness texts 'Too small: expected number to be ›=1' / 'To…
api-backend.rest-batch-config-contract neg[0] no bulk door mounted with switch false; cap honours config pass every switch-off table lacks its route; cap 5 reported max:5
api-backend.rest-batch-config-contract neg[1] cross-object /batch not used as enableBatchEndpoint evidence pass per-object switch scored from the per-object mount only
api-backend.rest-metadata-config-contract acc[0] stock default-prefix metadata mounts answer, not routing-404 pass live :41370 admin: GET /meta 200, /meta/types 200, /meta/diagnostics 200 {entries:[],scannedTypes:27}, /meta/_drafts 200 {drafts:[]}, /meta/object 20…
api-backend.rest-metadata-config-contract acc[1] prefix moves all metadata mounts and discovery advertisement pass harness {metadata:{prefix:'/metadata'}}: 0 routes left under /api/v1/meta, 19 under /api/v1/metadata (baseline 19 under /meta); GET /api/v1/discovery…
api-backend.rest-metadata-config-contract acc[2] four endpoint switches each remove exactly their named mounts pass harness diffs vs all-true baseline (75 routes), added=[] for all: types → GET /meta, GET /meta/types; items → GET /meta/:type only; maintenance → GET…
api-backend.rest-metadata-config-contract acc[3] maskObjectFields default ON hides unreadable fields; false passes through pass live: member a4.liaison (granted showcase_client_liaison, session verified via /auth/get-session) GET /meta/object/showcase_project → 19 fields; admi…
api-backend.rest-metadata-config-contract acc[4] enableCache selects cached read; six carve-outs bypass it pass harness GET /meta/:type/:name with getMetaItemCached+getMetaItem spies: enableCache=true plain object → cached 1/uncached 0; enableCache=false → cach…
api-backend.rest-metadata-config-contract acc[5] cacheTtl (3600/0/-1) and endpoints.schema refused at construction pass all four throw 'REST API configuration is invalid: metadata does not satisfy MetadataEndpointsConfigSchema … metadata.cacheTtl was removed in @…
api-backend.rest-metadata-config-contract neg[0] served schema never carries an unreadable field pass liaison showcase_project document: no budget/spent/budget_remaining key or string in the whole body
api-backend.rest-metadata-config-contract neg[1] masking never scored from admin's document pass masking scored from the liaison member (no admin capability); admin copy used only as the diff baseline
api-backend.rest-metadata-config-contract neg[2] no metadata route mounted with its switch false pass every switch-off table lacks exactly its routes; no route survives its own switch
api-backend.rest-route-generation-tombstones acc[0] four routes.* keys refused at construction pass includeObjects, excludeObjects, nameTransform 'none' AND 'plural', overrides each throw 'routes does not satisfy RouteGenerationConfigSchema (@ob…
api-backend.rest-route-generation-tombstones acc[1] refusal survives createRestApiPlugin().start() pass pin §B 'rejects createRestApiPlugin({ api: { routes: { nameTransform: "none" } } }).start()' ✓ and §E 'the plugin path refuses the same keys' ✓; harn…
api-backend.rest-route-generation-tombstones acc[2] each prescription names a replacement that exists pass enable.apiEnabled (spec data/object.zod.ts:271) live — showcase_a4_hidden answers 404 OBJECT_API_DISABLED; enable.apiMethods (object.zod.ts:283); cru…
api-backend.rest-route-generation-tombstones acc[3] authoring any of the four is a tsc error pass RUNDIR/tsc tsc -p (repo TypeScript, spec + rest dist types): cfg.ts(6,41) TS2741 includeObjects, (7,41) TS2741 excludeObjects, (8,41) TS2322 nameTran…
api-backend.rest-route-generation-tombstones acc[4] routes:{} constructs; unknown key stripped pass harness: routes:{} → no refusal, normalized routes {}; routes:{someUnknownKey:1} → no refusal, normalized {}; pin §E 'an empty routes sub-object st…
api-backend.rest-route-generation-tombstones neg[0] no routes.* key parses clean anywhere pass refused at constructor, plugin path and tsc
api-backend.rest-route-generation-tombstones neg[1] not scored from spec schema tests alone pass scored from the real RestServer/createRestApiPlugin (dist) and rest pins
api-backend.second-object-exposure-and-internal-fields acc[0] permanent pins pass at 5b14b7f pass t1-api-backend.log: @objectstack/metadata-protocol protocol.relation-condition-target-exposure.test.ts 13, protocol.expand-target-exposure.test.ts 15…
api-backend.second-object-exposure-and-internal-fields acc[1] nested-relation filter → 404/405, both personas pass scratch app (:41361) showcase_qa_source→showcase_qa_hidden(apiEnabled:false)/showcase_qa_getonly(apiMethods:['get']). Admin AND member identical: GET…
api-backend.second-object-exposure-and-internal-fields acc[2] $expand into unexposed target → bare id pass admin+member: list GET $expand=t_ref,g_ref, by-id ?expand=, POST expand map → t_ref = 'gW6cvWJAmP0VYO7Q' (bare id); control g_ref (get-whitelisted, a…
api-backend.second-object-exposure-and-internal-fields acc[3] internal field 400 INVALID_FIELD in every position pass admin+member: filter (GET filter, implicit ?internal_f=, $filter, POST where) / sort (?sort, $orderby, POST orderBy) / groupBy / aggregations[0].fiel…
api-backend.second-object-exposure-and-internal-fields neg[0] no 200 row-count oracle on internal filter pass no internal-field evaluate position answered 200
api-backend.data-request-shape-and-query-arity acc[0] permanent pins pass at 5b14b7f pass t1-api-backend.log @5b14b7f3: @objectstack/rest request-schema-gate.conformance.test.ts 16 passed; @objectstack/runtime data-write-request-gate.test.…
api-backend.data-request-shape-and-query-arity acc[1] null/array/scalar PATCH + empty token → 400, updated_at unchanged pass PATCH /data/showcase_task/BDTORUgoFI53x3WE body null/[]/5/"str" → each 400 VALIDATION_FAILED fields[data] 'expected record, received …'; {expectedVer…
api-backend.data-request-shape-and-query-arity acc[2] null /query body → 400 pass POST /data/showcase_task/query body null → 400 VALIDATION_FAILED fields[query] 'expected object, received null', no records
api-backend.data-request-shape-and-query-arity acc[3] repeated query name 400; doubled keepData refused pass GET /packages?status=a&status=b → 400 VALIDATION_ERROR 'supplied 2 times'; DELETE /packages/com.example.showcase?keepData=true&keepData=true → 400 VA…
api-backend.data-request-shape-and-query-arity acc[4] stale If-Match on unreadable row → 404 pass contributor-bound member (task RLS hides BDTORUgoFI53x3WE) PATCH with If-Match "2020-01-01T00:00:00.000Z" → 404 RECORD_NOT_FOUND (no currentRecord); …
api-backend.data-request-shape-and-query-arity neg[0] doubled keepData never honoured pass 400 before any work; package + tables intact (reads above)
api-backend.meta-read-doors-v18 acc[0] seven permanent pins pass at subject sha pass t1-api-backend.log @5b14b7f3: metadata-protocol protocol.app-package-id-key 8 ✓ (Test Files 4 passed, EXIT 0); runtime meta-app-package-id-key 12 ✓, …
api-backend.meta-read-doors-v18 acc[1] app by package id; unknown package = unknown-name 404 pass GET /meta/app/com.example.showcase 200 {type:app,name:showcase_app,…}; /meta/app/com.unknown.pkg 404 {error:{code:RESOURCE_NOT_FOUND,message:'Metadat…
api-backend.meta-read-doors-v18 acc[2] ?member= reads one member; non-bundled 400; unknown param 400 pass GET /meta/email_template/auth.password_reset?member=zh-CN 200 item.locale=zh-CN label 密码重置 (ja-JP → ja-JP; none → en-US); /meta/object/showcase_task?…
api-backend.meta-read-doors-v18 acc[3] ?package=all byte-identical to no parameter pass GET /meta/view?package=all vs /meta/view: cmp BYTE-IDENTICAL, 36 ids equal in order; discriminating control on object: ?package=all 107 items byte-id…
api-backend.meta-read-doors-v18 acc[4] FLS-hidden field unsortable in meta and 403 on data sort pass liaison member on showcase_project (stock FLS fixture; showcase_task has none): sortability.fields has no budget/spent entry (name:{sortable:true}); …
api-backend.error-sentences-and-unique-violation-wire-code acc[0] four permanent pins pass at subject sha pass t1-api-backend.log @5b14b7f3: packages/rest rest-write-route-hook-refusal-sentence.ledger.test.ts 577 ✓ 0 ✗, rest-hook-script-fault-envelope.test.ts …
api-backend.error-sentences-and-unique-violation-wire-code acc[1] hook refusal → 400 VALIDATION_ERROR with hook sentence blocked(fixture) the step's sys_sharing_rule hook cannot be authored by a package, so the nested-envelope VALIDATION_ERROR rows (sharing/approvals/suggested-bindings …
api-backend.error-sentences-and-unique-violation-wire-code acc[2] duplicate via action door → 409 UNIQUE_VIOLATION, details name field fail scratch :41371 POST /api/v1/actions/showcase_a4_unique/showcase_a4_dup (twice, also with /:recordId) → 409 {success:false,error:{code:UNIQUE_VIOLATIO…
api-backend.error-sentences-and-unique-violation-wire-code acc[3] forced storage 500 carries generic sentence only pass scratch :41372 with OS_STORAGE_LOCAL_ROOT under a regular file: PUT /api/v1/storage/_local/raw/‹token› (twice) → 500 {success:false,error:{code:INTER…

Reproduction rules (fails)

  • api-backend.error-sentences-and-unique-violation-wire-code acceptance[2] — disposition: assertion-defect · the product matches its pinned contract (dispatcher-unique-violation-wire-code.test.ts: details carry field only when the driver names a single column; a tenancy-scoped composite unique names none), the clause over-claims. Per this wave's plan (no checklist edits, no anchor cards from runners) the test-fix is parked on the wave anchor via the Checklist-accuracy section below for the dispatch session to collect; no product card.
    • repro: scratch app: object showcase_a4_unique {code: text unique:true}; script action showcase_a4_dup (perRecord) whose body does ctx.api.object('showcase_a4_unique').insert({code:'DUP-A4'}); POST /api/v1/data/showcase_a4_unique {code:'DUP-A4'} → 201; POST /api/v1/actions/showcase_a4_unique/showcase_a4_dup {recordId:‹id›} → 409
    • expected vs actual: clause expects details naming the field; actual details = {developerMessage, object}, no field. The pin dispatcher-unique-violation-wire-code.test.ts asserts exactly this key set for an engine write ('The driver names no single column: the index is the tenancy-scoped composite' → ['developerMessage','object']) and adds field only when DuplicateRecordError states a column. Product matches its pinned contract; the clause over-claims.
    • mechanism: packages/runtime/src/dispatcher-unique-violation-wire-code.test.ts:195-201 (key set without field) vs :207-211 (field only for a named-column throw)

Derived item verdicts

20 pass · 1 partial · 1 fail · 0 blocked · 5 not-run (of 27).

Tier 1 pin runs (RUNNER rule 6, one vitest batch per package, all at the subject sha):

  • packages/metadata-protocol: 4 files, 77 passed (relation-condition-target-exposure, expand-target-exposure, data-door-internal-field-positions, app-package-id-key)
  • packages/runtime: 12 files, 296 passed (action-activation-dispatch, action-activation-posture-gate, data-write-request-gate, data-delete-expected-version, dispatcher-query-arity, packages-write-flag-arity, data-conflict-caller-visibility, dispatcher-unique-violation-wire-code, endpoint-executor, meta-object-sortability-caller-fls, meta-app-package-id-key, meta-package-all-fold)
  • packages/objectql: 3 files, 202 passed (engine incl. [Security: $expand bypasses RLS/FLS on the referenced object (data leak on lookups) #2850], engine-filter-array-lowering, internal-field-positions)
  • packages/rest: 9 files, 742 passed (request-schema-gate.conformance, rest-sub-config-parse-not-cast, rest-config-mount-table.pin, rest-batch-size-cap, rest-write-route-hook-refusal-sentence.ledger, rest-hook-script-fault-envelope, meta-object-sortability-caller-fls, rest-server-meta-member-selector, rest-server-meta-door-closed-sets)
  • packages/spec: 1 file, 48 passed (api/apis-publish-gates)
  • packages/services/service-storage: 1 file, 18 passed (storage-routes.server-fault-withheld)
  • packages/qa/dogfood: 5 files, 57 passed (declarative-endpoint-policy, action-params-contract, owner-anchor-and-bulk-writes, packaged-activation-ledger-reach, showcase-declarative-endpoints) — first attempt was OOM-killed (exit 137, container memory cap) and re-run with --maxWorkers=1; the re-run is the evidence

Partial / gap notes:

  • api-backend.aggregate-contract-matrix: negative[2] (driver pushdown vs in-memory bucket labels agree under a non-UTC zone) not-run — the timezone lever was not exercised; everything else passed
  • api-backend.error-sentences-and-unique-violation-wire-code: acceptance[1] blocked(fixture) — a package cannot author a hook on sys_sharing_rule (compile refuses), so the VALIDATION_ERROR rows rest on the ledger pin only; the /data-family probe on a scratch object returned the hook sentence verbatim with the pinned code-less 400

Handover — items with no verdict this run

  • api-backend.server-timing-admin-gated r4 · P2 · api — Tier 3 deferred by the 18.0 release-sweep plan
  • api-backend.route-ledger-live-parity r4 · P2 · api — Tier 3 deferred by the 18.0 release-sweep plan
  • api-backend.package-rest-lifecycle r3 · P2 · api — Tier 3 deferred by the 18.0 release-sweep plan
  • api-backend.api-console-discovery-execute r2 · P2 · browser — Tier 3 deferred by the 18.0 release-sweep plan
  • api-backend.date-range-preset-matrix r2 · P2 · api — Tier 3 deferred by the 18.0 release-sweep plan

Checklist-accuracy findings / fixture gaps

Recorded for the wave anchor (collected by the dispatch session); not extracted, no checklist edit in this run.

Checklist accuracy:

  • api-backend.error-envelope-ledger · acceptance[3] · HttpStatusErrorCodeMap is a status→floor-code map (400→VALIDATION_ERROR, 404→RESOURCE_NOT_FOUND …), not a code→status map; OBJECT_NOT_FOUND/RECORD_NOT_FOUND/VALIDATION_FAILED etc. have no entry in it, so the clause can only be judged by code family (ErrorHttpStatusMap category). Name the oracle the clause actually means
  • api-backend.aggregate-contract-matrix · step 6 · 'aggregations as a non-array → the shape refusal with the worked example': on POST /data/:object/query the request schema answers first (400 VALIDATION_FAILED fields[query.aggregations] 'Invalid input: expected array, received object'), so protocol.ts's worked-example message (~line 13960) is not reached on this door — the same spec: FilterConditionSchema (the save-time door) admits a non-boolean $null / $exists flag, so a stored dataset or widget filter carrying one saves clean and is refused 400 on every query face #20116 door posture filter-comparand-conformance rev 3 records. Step text should name the door or expect the schema refusal
  • api-backend.api-methods-verb-gate · fixtures · scratch-object legs need OS_METADATA_WRITABLE=object on the boot and the object body needs sharingModel (author-time lint security-owd-unset 422 otherwise); the item says only 'runtime metadata authoring'. Non-array apiMethods is refused 422 by Zod at PUT, so the fail-closed arm of acceptance[2] is reachable only via the local resolver, not live
  • api-backend.api-methods-verb-gate · step 7 · the cross-object /batch 405 names 'bulk' (the gate the route checks) not 'update'; the step's expectation is unspecific, recorded for the next runner
  • api-backend.batch-transactional-discovery · step 4 · an invoice missing required fields fails pre-write validation, so it may not exercise a real transaction rollback; a mid-batch runtime failure (update on a nonexistent id after a create) proves the rollback more directly — consider naming it
  • api-backend.formula-stdlib-matrix · acceptance[2]/step 3 · 'coalesce falls back on null/undefined ONLY' — undefined is not observable through CEL: a record key whose value is undefined faults 'No such key' before coalesce runs; the clause is effectively null-only from the authoring surface
  • api-backend.enforce-or-remove-authoring-gates · step 2 · a 'view' filter is the array shape [{field,operator,value}], not a FilterCondition; the stored-$regex leg is only meaningful on a widget/report filter (used ops-dashboard widget filter)
  • api-backend.retired-def-refusal · step 5 · manifest.loading's carrier has no runtime metadata-write door at all (package/manifest/plugin are 'not a metadata type'); step could say so like it does for code-only agent
  • api-backend.second-object-exposure-and-internal-fields · step 1 · the literal probe filter=[["t_ref.name","=","x"]] is a DOTTED path and answers 400 INVALID_FIELD (prescribing the nested form), not the exposure refusal; the nested-relation spelling that reaches the exposure gate is filter={"t_ref":{"name":"x"}} / where {t_ref:{name:x}}
  • api-backend.second-object-exposure-and-internal-fields · acceptance[1] · clause says the refusal names 'where.t_ref'; both GET and POST doors locate it as 'filter.t_ref'
  • api-backend.bulk-write-contract · step 4 / acceptance[2] · updateMany stops at the first failed row by default, so a single batch [nonexistent, foreign] reports the foreign id NOT_ATTEMPTED, not RECORD_NOT_FOUND; the step must send the ids in separate calls or with options.continueOnError:true to observe the no-existence-oracle parity
  • api-backend.query-contract-matrix · observation · list GET accepts $expand while single-record GET /data/:object/:id refuses $expand (400 VALIDATION_ERROR, 'Supported parameters: expand, select') with a different envelope ({error:{code,message}} vs flat {error,code}) — not an item claim, A repeated ?filter= answers two different error codes depending on which data route received it #8001-family residual
  • api-backend.query-contract-matrix · observation · POST /query body sort:'name' (bare string) → 400 VALIDATION_FAILED query.sort; only the array spelling is served — not an item claim
  • api-backend.declarative-endpoint-execution · observation · the stack-schema refusal text reads 'Only object_operation and flow endpoints execute in 17.x' on the 18.0 subject (packages/spec/src/api/endpoint-publish-gate.ts:371) — stale version wording; dogfood pin title '[E8(#5040 执行器):验收 —— showcase 端点回迁 /apps/showcase/… + RED-first e2e + 真实 boot 探针 + 升级文档安全复核 #5112] GET /meta/api returns both restored declarations' while the showcase declares three
  • api-backend.packaged-action-disabled-dispatch · observation · POST /auth/admin/create-user answered membershipCreated:false, yet the user operated in the Default Organization (stamped organization_id on writes) — no clause affected
  • api-backend.rest-crud-config-contract · knownGaps[1] + automated.ref · 'the MOUNT half has no permanent pin' is stale: packages/rest/src/rest-config-mount-table.pin.test.ts ([finding] The MOUNT half of every RestServerConfig switch is unpinned — the tests assert what a switch normalizes to, never that the route leaves the table #15544) pins every crud.operations.* radius as an exact route-set diff (24/24 ✓ at 5b14b7f) — add it to automated.ref
  • api-backend.rest-batch-config-contract · knownGaps[1] + automated.ref · same: the mount pin covers batch.enableBatchEndpoint, operations.*Many and the protocol-member conjunct (§2) — add it to automated.ref
  • api-backend.rest-metadata-config-contract · acceptance[4]/step 9 · enableCache carve-outs are now SEVEN: a ?member= (memberScoped, [finding] email_template: a Studio save of the same template in a second locale replaces the first locale's overlay at the next boot (sys_metadata keeps one overlay row per type and name) #22877) read also bypasses getMetaItemCached (packages/rest/src/meta-item-read-routes.ts:672-673)
  • api-backend.rest-metadata-config-contract · personas[1] · still says 'cannot read every field of showcase_account'; rev 4 moved the fixture to showcase_project/client_liaison
  • api-backend.meta-read-doors-v18 · step 5 / acceptance[4] · step names showcase_task, but stock FLS only exists on showcase_project (showcase_client_liaison); and the contract is that the hidden field is ABSENT from sortability (pin: 'sortability never offers the unreadable field'), not 'marked unsortable'
  • api-backend.error-sentences-and-unique-violation-wire-code · fixtures/step 1/acceptance[1] · a package hook on sys_sharing_rule is refused at compile ("Hook … references object 'sys_sharing_rule' which is not defined in objects"); the /data door answers a hook refusal 400 with NO code by pinned design ('the refusal envelope carries no code when the hook declared none'); VALIDATION_ERROR applies only to the re-dressed hand-built rows (REFUSED_400 in the ledger pin)
  • api-backend.error-sentences-and-unique-violation-wire-code · acceptance[2] · 'details naming the field' over-claims: details carry field only when the driver names a single column; an engine write against a tenancy-scoped composite unique index answers details {developerMessage, object} (dispatcher-unique-violation-wire-code.test.ts:195-211)
  • api-backend.error-sentences-and-unique-violation-wire-code · fixtures · 'pnpm dev -- --fresh -p PORT' boot spelling vs RUNNER canonical boot; also a scratch object needs sharingModel or the author-time rule security-owd-unset refuses compile
  • api-backend.action-activation-door-contract · acceptance[4] · the metadata-plane-degraded 503 arm (actions.ts:212-221) is named in the clause but is neither stock-reachable nor covered by any pin in automated.ref
  • api-backend.rest-crud-config-contract · acceptance[2] · the harness can only show 'no handler'; the switched-off op's live wire answer is unobservable ([finding] No shipped boot path authors RestServerConfig at all — os serve fixes it and the dev plugin passes none, so every live crud / metadata / batch key is embedder-only #15543) and the composed server's hono dispatcher catch-all also serves /data routes — the clause's dispatcher-vs-hono-route trap is not discharged by a RestServer-only table

Fixture gaps:

  • api-backend.aggregate-contract-matrix · stock showcase_account has no row with null annual_revenue (needed for count-'*' vs count-field) and no Sat/Sun or year-boundary ISO-week pair — 3 rows seeded at run time
  • api-backend.filter-comparand-conformance · showcase_field_zoo has only 2 rows — answer sets are discriminating but thin
  • api-backend.query-contract-matrix · acceptance[4] needs a contributor-bound member owning an invoice WITH a contact; no seeded user holds the contributor position and no seeded invoice carries a contact (all 12 contact:null). Provisioned at runtime: admin create-user + sys_user_position{position:'contributor'} (search:qa-contributor-bound-member) + member-created invoice with owner=self, account=Contoso, contact=Carl Fox
  • api-backend.packaged-action-disabled-dispatch · acceptance[3] both-persona variant used the same runtime-provisioned contributor member
  • api-backend.error-sentences-and-unique-violation-wire-code · no package-authorable hook can reach a hand-built nested-envelope write row (sharing rules / approvals / suggested bindings) — the VALIDATION_ERROR half is pin-only
  • api-backend.action-activation-door-contract · ambiguity / 501 / 503 arms still pin-only (no colliding scratch package authored this run)

Incidental product finding (outside any clause)

  • Seen while driving api-backend.error-sentences-and-unique-violation-wire-code acceptance[3] (forced storage fault), independently re-verified on a healthy stock boot: POST /api/v1/storage/upload/complete commits a file record (status committed) for bytes that were never stored; the signed download then answers 500. Extracted as its own defect card at close-out (see the close-out comment).

Activity

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out (extraction) for this run record.

    Extracted: #24548 · api-backend.error-sentences-and-unique-violation-wire-code · acceptance[3] (incidental, outside the clause)
    

    Still open on this record, handed to the dispatch session for the wave anchor (runners file no anchor card this wave):

    • api-backend.error-sentences-and-unique-violation-wire-code acceptance[2] fail — disposition assertion-defect (product matches its pinned contract; the clause over-claims details.field), plus acceptance[1] blocked(fixture). Test-fix belongs on the anchor.
    • api-backend.aggregate-contract-matrix partial — negative[2] (non-UTC pushdown vs in-memory labels) not-run.
    • 5 Tier 3 items not-run by plan (handover list in the body).

    No P0 item failed in this area; no authentication/authorization finding.


    Generated by Claude Code

  2. changed the title [-]QA run · area:api-backend (22/27) · 5b14b7f3 · 2026-10-19 · 20 PASS / 1 PARTIAL / 1 FAIL / 0 BLOCKED / 5 NOT-RUN[/-] [+]QA run · api-backend (22/27) · 5b14b7f3 · 2026-10-19 · 20 PASS / 1 PARTIAL / 1 FAIL / 0 BLOCKED / 5 NOT-RUN[/+] on Oct 19, 2026
  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Parked-on: #24579 · this record's checklist-accuracy findings, fixture gaps, partial coverage gaps and not-run handover (wave anchor §2–§4)
    Parked-on: #24579 · api-backend.error-sentences-and-unique-violation-wire-code · acceptance[2] (re-point, wave anchor §1)


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Superseded-by: #24595

    Round 2 at ba4afcc re-judged this record's A-class unjudged clauses (api-backend.aggregate-contract-matrix negative[2] — FAIL (in-memory date bucketing shifts a Field.date a day earlier under a negative-offset zone; rule-7 verified)) and carried every other verdict forward to #24595 (Carried-forward: lines there, valid for 5b14b7f). B-class gaps stay parked on #24579.


    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