You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec: the view save door silently strips unknown top-level keys from the view envelope (200, not stored) while object, page and dashboard bodies refuse them 422 unrecognized_keys #26711
Filing gate: ① product defect, reproduced, landing site named.
Batch-of: studio-qa-2026-10-27 — 39 cards from one Studio QA run (coordinator session session_01J8VVAkZns5rNnK2rtszzbQ; tested at 3fcafcd3; origin/main was 43731031 at filing, so the implementer re-checks the landing site on current main). The run record is the qa-run issue filed with this batch.
Symptom
An author who sends a misspelt or retired key on a view gets success and the key is silently discarded. The same key on an object, page or dashboard body is refused.
Reproduction
PUT /api/v1/meta/view/showcase_task.qa_rk_view?mode=draft with a valid view body plus top-level "zzz_junk_key": true (or a retired list key such as "striped": true) → 200 {success:true,state:"draft"}.
GET …?state=draft → the key is absent.
Same junk key at the top of a dashboard / object / page body → 422 INVALID_METADATA <root> unrecognized_keys.
Expected
The view envelope refuses unknown top-level keys like every other type (422 unrecognized_keys, with the retirement guidance for retired keys).
Suspected landing site (the implementer verifies)
packages/spec/src/ui/view.zod.ts: ViewMetadataSchema = z.preprocess(stripViewConsoleDecorations) → z.union(members); the envelope member strips instead of refusing.
Filing facts
reach: PUT /api/v1/meta/view/… measured once by the coordinator.
Business reason: Silent tolerance hides AI and human authoring mistakes; the protocol rule is to refuse loudly.
Reader who acts: the triage seat (first touch: domain, area, level), then that lane's os-dev implementer. QA suggestion only: domain:spec, area:studio, p2.
p2: the view save door silently strips unknown top-level keys (200, not stored), while the object, page and dashboard doors refuse them with 422. Make the view envelope strict like its siblings. Retired list keys get their ADR-0087 tombstones. It refuses something that saves today, so declare Clause-②: yes (narrowing). Handled directly in 18.x. From the studio-qa-2026-10-27 batch. Re-check the landing site on current main.
Claim: PM loop round 1 · 2026-10-27T16:20Z
Session: session_01WGufzfhobWEgUUrjz4rrbh
Account: os-support-ai
Branch: claude/project-thread-694qho (card thread session_01WGufziYCUHZQE3MXucvWe9. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead of claude/issue-26711-<slug>.)
Worktree: objectstack-issue-26711
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/spec/src/ui/view.zod.ts. The view envelope refuses unknown top-level keys (422 unrecognized_keys), the console decorations the preprocess strips on purpose are kept, and each retired list key gets its ADR-0087 tombstone. Also in scope: the spec tests and generated artifacts, any example or platform-objects view the narrowing would refuse (fixed, not tolerated), docs, and one changeset with its ADR-0087 marker. If the dev's re-measure on current main shows the door already refuses, there is no PR. Stop on a breach and explain it in the report.
Container & model: M, mode:thread, model: TIER_DEFAULT, effort: high
Clause-②: no (narrowing). A key that saves today with 200 is refused, so a contract-tier review is owed before the queue.
Metadata-protocol: narrowed
Responsibility: n/a. A Studio QA finding (studio-qa-2026-10-27).
Thread-read: 6444389072
Premise: unverified at origin/main665059b6. The QA ran at 3fcafcd3, so the dev re-measures before editing.
Serial constraints cleared: yes. No open PR or claim names view.zod.ts.
Ruling-ref: none — triage 6444389072
{
"issue": 26711,
"status": "done",
"branch": "claude/project-thread-694qho",
"pr": "https://github.com/objectstack-ai/objectstack/pull/26851",
"session": "session_01WGufziYCUHZQE3MXucvWe9",
"premise_still_valid": true,
"summary": "Re-measured on main ef7067fd: the view item record and the inline list and form overlays accepted an unknown top-level key (and `striped`) and stripped it, so the save answered 200 without it; the container was already closed. All three members are now closed with strictObject / closedObject, so the save answers 422 INVALID_METADATA / unrecognized_keys naming the key and the shape, with alias guidance (objectName → object, id → name). Live 18.x tombstones keep their prescriptions; striped / bordered / virtualScroll (aged out under the ADR-0087 2026-10-26 amendment) get the upgrade-guide sentence rather than re-added tombstones. Console decorations the preprocess strips are kept. One platform writer the narrowing broke was fixed in the same PR: @object-ui/data-objectstack createView added a top-level `data` to a ViewItem envelope (patch changeset under ui/.changeset). STILL_STRIP is now empty and its end-state note kept as history.",
"tests": "Merged head 66637aea, locked: spec test 735/735 files, 22045 passed | 1 todo; metadata-protocol test 269 passed | 4 skipped files, 21628 passed | 26 skipped; 19 ui view-schema test files 591/591; @object-ui/data-objectstack test 101/101 files, 1205/1205. Pre-merge head, locked: spec + metadata-protocol typecheck exit 0, @objectstack/lint test exit 0, @objectstack/metadata test exit 0, pnpm lint exit 0. New pins: view-wire-unknown-key-refusal.test.ts (17), protocol.save-union-issues.test.ts #26711 block (draft/publish 422 rows 0, clean control, read-path _diagnostics), createView.envelopeData-26711.test.ts (3). First locked run showed 3 spec reds (STILL_STRIP reverse pin, authoring-lint view divergence pin) and 5 metadata-protocol reds (graft-folded-form-sections fixtures that froze the dropped key) plus 1 ui red (inlineEditSessionOnly-5144 via the adapter createView `data`); all are consequences of this change and were re-judged or fixed. Live showcase boot: clean PUT 200, junk/striped PUT 422 naming the key, 36/36 served views round-trip as drafts.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands: 89 commands, each run with exit recorded; --ran: 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). Six first answered exit 3 (five spec dist-reading gates on a stale dist, check-plugin-teardown-shape --self-test on a shallow clone) and exit 0 after pnpm --filter @objectstack/spec build and git fetch --unshallow. check:generated exit 0 after merging main. CI check-runs on the PR: pending at report time.",
"dogfood_battery": "66637aea7e4813ce7072768442ba2cb6d7e2f295 · pnpm --filter @objectstack/dogfood^... build exit 0; pnpm --filter @objectstack/dogfood test exit 0 under os-verify-lock (VERDICT command-exit 0, shared box) · Test Files 314 passed | 3 skipped (317) · Tests 2609 passed | 20 skipped (2629) · no failures",
"mcp_calls": "read-only only — mcp__github__issue_read on #26711 and its triage comment; no MCP GitHub write tool used",
"api_writes": "0 REST proxy writes. GitHub writes went through the fleet-write relay: pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/26851/assignees), and this comment (POST /issues/26711/comments); plus git push of the branch",
"open_questions": [],
"out_of_scope_findings": []
}
Supersedes the File surface line of claim 6447314891. Everything else in it stands.
File surface: everything the claim named, plus ui/packages/data-objectstackcreateView, its test and one ui/.changeset patch entry. The narrowing refuses the top-level data that createView added to a view item envelope. A platform writer the narrowing breaks is fixed in the same PR, under the same rule the claim already set for example and platform-objects views ("fixed, not tolerated"). Stop on a breach and explain it in the report.
Why: the dev measured the break and fixed it in PR #26851 (os-dev-report 6450470105). Without the fix, the console's own view save would answer 422 once this lands.
PR #26851 merged at 8a218fc8, which is an ancestor of origin/main. On all 23 paths the PR touched, the merge tree matches the accepted head 5b87033b byte for byte.
A view item record and the inline list and form view overlays now refuse an undeclared top-level key with unrecognized_keys, instead of stripping it in silence. The declared keys are the same as before, and the live tombstones keep their prescriptions. The console writers and the @object-ui/data-objectstackcreateView adapter send only declared keys.
@objectstack/spec is minor with ADR-0087 not-required (no-migration-prescription), and @object-ui/data-objectstack is patch from the root .changeset. Clause-②: no (narrowing) and Metadata-protocol: narrowed. The card closed through Fixes #26711, and this seat removes pm:dispatched.
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: first grade —
bug·priority:p2·domain:spec·area:studio·pm:queue(findingremoved) · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T14:17Z⛔ Not a claim, ⛔ not a dispatch.
Clause-②: yes (narrowing). Handled directly in 18.x. From the studio-qa-2026-10-27 batch. Re-check the landing site on currentmain.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 1 · 2026-10-27T16:20Z
Session:
session_01WGufzfhobWEgUUrjz4rrbhAccount:
os-support-aiBranch:
claude/project-thread-694qho(card threadsession_01WGufziYCUHZQE3MXucvWe9. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead ofclaude/issue-26711-<slug>.)Worktree:
objectstack-issue-26711Domain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/ui/view.zod.ts. The view envelope refuses unknown top-level keys (422unrecognized_keys), the console decorations the preprocess strips on purpose are kept, and each retired list key gets its ADR-0087 tombstone. Also in scope: the spec tests and generated artifacts, any example or platform-objects view the narrowing would refuse (fixed, not tolerated), docs, and one changeset with its ADR-0087 marker. If the dev's re-measure on currentmainshows the door already refuses, there is no PR. Stop on a breach and explain it in the report.Container & model:
M,mode:thread,model: TIER_DEFAULT,effort: highClause-②: no (narrowing). A key that saves today with 200 is refused, so a contract-tier review is owed before the queue.
Metadata-protocol: narrowed
Responsibility: n/a. A Studio QA finding (studio-qa-2026-10-27).
Thread-read: 6444389072
Premise: unverified at
origin/main665059b6. The QA ran at3fcafcd3, so the dev re-measures before editing.Serial constraints cleared: yes. No open PR or claim names
view.zod.ts.Ruling-ref: none — triage
6444389072objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26711, "status": "done", "branch": "claude/project-thread-694qho", "pr": "https://github.com/objectstack-ai/objectstack/pull/26851", "session": "session_01WGufziYCUHZQE3MXucvWe9", "premise_still_valid": true, "summary": "Re-measured on main ef7067fd: the view item record and the inline list and form overlays accepted an unknown top-level key (and `striped`) and stripped it, so the save answered 200 without it; the container was already closed. All three members are now closed with strictObject / closedObject, so the save answers 422 INVALID_METADATA / unrecognized_keys naming the key and the shape, with alias guidance (objectName → object, id → name). Live 18.x tombstones keep their prescriptions; striped / bordered / virtualScroll (aged out under the ADR-0087 2026-10-26 amendment) get the upgrade-guide sentence rather than re-added tombstones. Console decorations the preprocess strips are kept. One platform writer the narrowing broke was fixed in the same PR: @object-ui/data-objectstack createView added a top-level `data` to a ViewItem envelope (patch changeset under ui/.changeset). STILL_STRIP is now empty and its end-state note kept as history.", "tests": "Merged head 66637aea, locked: spec test 735/735 files, 22045 passed | 1 todo; metadata-protocol test 269 passed | 4 skipped files, 21628 passed | 26 skipped; 19 ui view-schema test files 591/591; @object-ui/data-objectstack test 101/101 files, 1205/1205. Pre-merge head, locked: spec + metadata-protocol typecheck exit 0, @objectstack/lint test exit 0, @objectstack/metadata test exit 0, pnpm lint exit 0. New pins: view-wire-unknown-key-refusal.test.ts (17), protocol.save-union-issues.test.ts #26711 block (draft/publish 422 rows 0, clean control, read-path _diagnostics), createView.envelopeData-26711.test.ts (3). First locked run showed 3 spec reds (STILL_STRIP reverse pin, authoring-lint view divergence pin) and 5 metadata-protocol reds (graft-folded-form-sections fixtures that froze the dropped key) plus 1 ui red (inlineEditSessionOnly-5144 via the adapter createView `data`); all are consequences of this change and were re-judged or fixed. Live showcase boot: clean PUT 200, junk/striped PUT 422 naming the key, 36/36 served views round-trip as drafts.", "gates": "node scripts/pm/dispatch-gates.mjs --commands: 89 commands, each run with exit recorded; --ran: 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). Six first answered exit 3 (five spec dist-reading gates on a stale dist, check-plugin-teardown-shape --self-test on a shallow clone) and exit 0 after pnpm --filter @objectstack/spec build and git fetch --unshallow. check:generated exit 0 after merging main. CI check-runs on the PR: pending at report time.", "dogfood_battery": "66637aea7e4813ce7072768442ba2cb6d7e2f295 · pnpm --filter @objectstack/dogfood^... build exit 0; pnpm --filter @objectstack/dogfood test exit 0 under os-verify-lock (VERDICT command-exit 0, shared box) · Test Files 314 passed | 3 skipped (317) · Tests 2609 passed | 20 skipped (2629) · no failures", "mcp_calls": "read-only only — mcp__github__issue_read on #26711 and its triage comment; no MCP GitHub write tool used", "api_writes": "0 REST proxy writes. GitHub writes went through the fleet-write relay: pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/26851/assignees), and this comment (POST /issues/26711/comments); plus git push of the branch", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim amendment ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-27T18:37ZSupersedes the
File surfaceline of claim 6447314891. Everything else in it stands.File surface: everything the claim named, plus
ui/packages/data-objectstackcreateView, its test and oneui/.changesetpatch entry. The narrowing refuses the top-leveldatathatcreateViewadded to a view item envelope. A platform writer the narrowing breaks is fixed in the same PR, under the same rule the claim already set for example and platform-objects views ("fixed, not tolerated"). Stop on a breach and explain it in the report.Why: the dev measured the break and fixed it in PR #26851 (os-dev-report 6450470105). Without the fix, the console's own view save would answer 422 once this lands.
objectstack-fleet commentedon Oct 27, 2026
Landed ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-27T21:10ZPR #26851 merged at
8a218fc8, which is an ancestor oforigin/main. On all 23 paths the PR touched, the merge tree matches the accepted head5b87033bbyte for byte.A view item record and the inline list and form view overlays now refuse an undeclared top-level key with
unrecognized_keys, instead of stripping it in silence. The declared keys are the same as before, and the live tombstones keep their prescriptions. The console writers and the@object-ui/data-objectstackcreateViewadapter send only declared keys.@objectstack/specis minor with ADR-0087not-required (no-migration-prescription), and@object-ui/data-objectstackis patch from the root.changeset.Clause-②: no (narrowing)andMetadata-protocol: narrowed. The card closed throughFixes #26711, and this seat removespm:dispatched.qa(checklist): re-verify the studio-authoring pass against main 3230bdb