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
Studio OWD panel: saving "Controlled by parent" on a detail whose master_detail is not yet required answers 409 DESTRUCTIVE_CHANGE with no way forward #27458
Filing gate: ① a product defect, a QA run clause fail (studio-authoring.access-owd-and-suggestions acceptance[1]).
Reproduction
Boot the showcase and sign in as admin. POST /api/v1/packages {"manifest":{"id":"com.qa.rnine","name":"QA R9","version":"0.1.0","type":"app","namespace":"qnine"}}.
PUT /api/v1/meta/object/qnine_project?mode=draft&package=com.qa.rnine with {"name":"qnine_project","sharingModel":"private","fields":{"name":{"type":"text"}}}.
PUT /api/v1/meta/object/qnine_step?mode=draft&package=com.qa.rnine with {"name":"qnine_step","sharingModel":"private","fields":{"name":{"type":"text"},"project":{"type":"master_detail","reference":"qnine_project"}}}. required is not set and the table is empty.
POST /api/v1/packages/com.qa.rnine/publish-drafts.
Open /_console/studio/com.qa.rnine/access → "Record sharing (OWD)". On QN Step choose "Controlled by parent — inherited from the master record" (the row shows "By parent → qnine_project"), then click "Save 1 change(s)".
Expected: the draft saves. Choosing controlled-by-parent makes the master_detail required, and on an empty table that is safe, or the panel asks for confirmation.
Actual: PUT /api/v1/meta/object/qnine_step?mode=draft&package=com.qa.rnine&surface=studio → 409 DESTRUCTIVE_CHANGE "Field 'project' is now required but has no default value — existing rows with null values may fail validation. — re-submit with ?force=true to proceed." The banner shows the message, the row stays "Unsaved", and the panel has no confirm or force control. The offered option cannot be saved. Reproduced twice on fresh loads.
Control: after making projectrequired: true through the API (?force=true, then publish), the same panel save answers 200, and the live object reads controlled_by_parent.
Mechanism
The panel's save implies a required flip on the master_detail field, and the destructive-change guard refuses it without ?force=true. The panel neither offers the force path (with the confirm the guard asks for) nor skips the guard when the table is empty.
Read fresh. A clause fail: saving "Controlled by parent" on a detail whose master_detail is not yet required answers 409 DESTRUCTIVE_CHANGE, with no way forward in the panel. From the 18.3.0 RC run ([sweep] v18.3.0 release test sweep #27377 §5); it is retested on the next wave.
The panel names the prerequisite (make the relationship required) and offers it. ⛔ The server's 409 stands, because the guard is right.
Claim: PM loop round 1 · 2026-10-29T11:31Z
Session: session_01L6bhgXU26UBEjd1KKHgNEx (seat; in-seat mode:subagent dev, same session, identity by branch)
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-27458-owd-cbp-prerequisite
Worktree: objectstack-issue-27458
Domain: domain:ui
Seat: domain:ui#1
File surface: ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.tsx (the controlled-by-parent save path), studio-design/owd-sharing.ts only if measured necessary, the existing destructive-change confirm pattern reused (no new dialog component), ui/packages/i18n/src/namespaces/studio/* (confirm copy), tests beside, one patch changeset (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: TIER_DEFAULT (seat-run dispatch-gates --tier on the paths: no path-derived mandate), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: Studio OWD panel (this lane) | the existing DESTRUCTIVE_CHANGE confirm-then-force pattern (ResourceEditPage.tsx ~1701/1866) | every Studio author who sets a detail object to "Controlled by parent" before its master_detail is required; the server 409 guard stays
Thread-read: 6491362803
Premise: holds — on origin/main57c51aab4d, PackageOwdOverviewPanel.tsxdoSave (~337–393) flips required: true on master_detail fields via requireCbpMasterDetails and saves with no force; the catch only sets formatMetadataError(e), so the 409 is terminal with no way forward.
Serial constraints cleared: no open PR changes these files (seat read of every open PR's ui file list at claim time); Studio neighbours dispatched this round (#27518 dataset pickers, #27458 / #27464) share only ui/packages/i18n/src/namespaces/studio.
Resume-from: none
{
"issue": 27458,
"status": "done",
"branch": "claude/issue-27458-owd-cbp-prerequisite",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27553",
"session": "session_01L6bhgXU26UBEjd1KKHgNEx",
"premise_still_valid": true,
"summary": "Re-measured on origin/main 6892888e: PackageOwdOverviewPanel doSave flips required on master_detail via requireCbpMasterDetails and saves with no force; the catch only set formatMetadataError. Now a 409 DESTRUCTIVE_CHANGE on a row whose CBP save makes a master_detail required opens the existing shared Dialog naming the relationship (field -> master) and the server's issue messages, with no error banner; confirm retries the same save with force (only on rows carrying the prerequisite), cancel saves nothing. Other refusals keep the banner. Server guard untouched; owd-sharing.ts not changed.",
"tests": "At e50eba20: pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel -> Test Files 9 passed (9), Tests 40 passed (40). Ablation via scripts/ablation-replace.mjs (confirm-branch if-condition -> 'if (false) {', anchor 1->0, blob 8ea5726e660c->dac064a26bd7; test imports the panel by relative src path, no dist leg): new 27458 file 3 failed | 1 passed (three confirm legs red, non-destructive leg green); restore blob == HEAD, git diff HEAD empty. pnpm --filter @object-ui/app-shell --filter @object-ui/i18n run type-check -> exit 0. pnpm --dir ui exec vitest run packages/i18n/ -> 89 files / 1374 tests passed.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at e50eba20: 34 derived, each run with exit captured before any pipe, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/ -> 169 files passed, 4901 tests). --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED (derived zero, all with exit codes). Extra: pnpm check:changeset-fixed exit 0 (roster under .changeset); pnpm --dir ui run check:new-line-citations exit 0, 0 new citations (first attempt as a root script was MODULE_NOT_FOUND-class exit 254, script lives in ui/). CI check-runs on e50eba20 at report time: Check Changeset, Check PR Size, Governed Surface Queue Guard, Lint (ESLint, PM dispatch-gates, repo & tooling, CI/release/engine, docs & code guards, scoped x3), PR-body guards, Type Check (workspace, source, consumer, debt ledger) all in_progress; opt-in harnesses skipped.",
"line_budget": "216 changed lines (+214/-2, 5 files) vs 250 cap",
"files_changed": [
".changeset/27458-owd-cbp-prerequisite-confirm.md",
"ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.tsx",
"ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.cbpPrerequisiteConfirm-27458.test.tsx",
"ui/packages/i18n/src/namespaces/studio/en.ts",
"ui/packages/i18n/src/namespaces/studio/zh.ts"
],
"deviations": [
"Dispatch order vs os-dev.md (os-dev wins): PR body footer uses the session-URL form required for PR bodies instead of the bare footer the dispatch named; declaration lines (Fixes/Clause-②/Metadata-protocol) placed before ## 维护者速读 per os-dev ('声明行后'), not after it.",
"Panel imports readFields from metadata-admin/previews/object-fields-io.js (already a dependency of owd-sharing.ts) to name the relationship; within the declared panel surface."
],
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls via fleet-write dispatch, repository_dispatch HTTP 204); issue comment POST /repos/objectstack-ai/objectstack/issues/27458/comments via post-stamped. Plus git push (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — multi-row save: rows written before the refused row are already drafts when the confirm opens; cancel leaves them (non-destructive). Recorded in PR Acceptance notes."
]
}
Landing refused · 2026-10-29T12:52Z · PR #27553 · ACCEPT 6497175213 at head e50eba20be.
Command: node scripts/pm/fleet-write/dispatch.mjs --repo objectstack-ai/objectstack --actions-file F, F = [{"op":"pr_ready","pull":27553},{"op":"automerge_enable","pull":27553}].
Refusal: the seat container's auto-mode permission classifier denied the call before it ran ("Merge Without Review"). Nothing was sent; the PR stays draft, CI green, mergeable_state: clean.
Per pm-dispatch landing rule (classifier refusal ⇒ stop, report to the maintainer, no other spelling), the seat has stopped and reported. The PR waits for the maintainer: either their own ready + merge, or a permission change that lets this seat run the landing op.
Landing refused again · 2026-10-29T13:06Z · PR #27553 · head e50eba20be unchanged since ACCEPT 6497175213.
After the maintainer's 13:00Z word in the seat thread (use pm-dispatch for issues and PRs), the seat retried the same command, same actions file (pr_ready + automerge_enable, pull 27553).
Refusal: the same auto-mode permission classifier denied it before it ran ("Merge Without Review"). Nothing was sent.
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: studio | studio-authoring.access-owd-and-suggestions | P①
Triage: p2 ·
domain:ui·area:access· 2026-10-29T08:05Z⛔ Not a claim.
master_detailis not yet required answers 409DESTRUCTIVE_CHANGE, with no way forward in the panel. From the 18.3.0 RC run ([sweep] v18.3.0 release test sweep #27377 §5); it is retested on the next wave.bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
Claim: PM loop round 1 · 2026-10-29T11:31Z
Session:
session_01L6bhgXU26UBEjd1KKHgNEx(seat; in-seatmode:subagentdev, same session, identity by branch)Account:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-27458-owd-cbp-prerequisiteWorktree:
objectstack-issue-27458Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.tsx(the controlled-by-parent save path),studio-design/owd-sharing.tsonly if measured necessary, the existing destructive-change confirm pattern reused (no new dialog component),ui/packages/i18n/src/namespaces/studio/*(confirm copy), tests beside, one patch changeset (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: TIER_DEFAULT(seat-rundispatch-gates --tieron the paths: no path-derived mandate),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: Studio OWD panel (this lane) | the existing
DESTRUCTIVE_CHANGEconfirm-then-forcepattern (ResourceEditPage.tsx~1701/1866) | every Studio author who sets a detail object to "Controlled by parent" before its master_detail is required; the server 409 guard staysThread-read: 6491362803
Premise: holds — on
origin/main57c51aab4d,PackageOwdOverviewPanel.tsxdoSave(~337–393) flipsrequired: trueon master_detail fields viarequireCbpMasterDetailsand saves with noforce; thecatchonly setsformatMetadataError(e), so the 409 is terminal with no way forward.Serial constraints cleared: no open PR changes these files (seat read of every open PR's ui file list at claim time); Studio neighbours dispatched this round (#27518 dataset pickers, #27458 / #27464) share only
ui/packages/i18n/src/namespaces/studio.Resume-from: none
objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
os-dev-report
{ "issue": 27458, "status": "done", "branch": "claude/issue-27458-owd-cbp-prerequisite", "pr": "https://github.com/objectstack-ai/objectstack/pull/27553", "session": "session_01L6bhgXU26UBEjd1KKHgNEx", "premise_still_valid": true, "summary": "Re-measured on origin/main 6892888e: PackageOwdOverviewPanel doSave flips required on master_detail via requireCbpMasterDetails and saves with no force; the catch only set formatMetadataError. Now a 409 DESTRUCTIVE_CHANGE on a row whose CBP save makes a master_detail required opens the existing shared Dialog naming the relationship (field -> master) and the server's issue messages, with no error banner; confirm retries the same save with force (only on rows carrying the prerequisite), cancel saves nothing. Other refusals keep the banner. Server guard untouched; owd-sharing.ts not changed.", "tests": "At e50eba20: pnpm --dir ui exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel -> Test Files 9 passed (9), Tests 40 passed (40). Ablation via scripts/ablation-replace.mjs (confirm-branch if-condition -> 'if (false) {', anchor 1->0, blob 8ea5726e660c->dac064a26bd7; test imports the panel by relative src path, no dist leg): new 27458 file 3 failed | 1 passed (three confirm legs red, non-destructive leg green); restore blob == HEAD, git diff HEAD empty. pnpm --filter @object-ui/app-shell --filter @object-ui/i18n run type-check -> exit 0. pnpm --dir ui exec vitest run packages/i18n/ -> 89 files / 1374 tests passed.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at e50eba20: 34 derived, each run with exit captured before any pipe, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/ -> 169 files passed, 4901 tests). --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED (derived zero, all with exit codes). Extra: pnpm check:changeset-fixed exit 0 (roster under .changeset); pnpm --dir ui run check:new-line-citations exit 0, 0 new citations (first attempt as a root script was MODULE_NOT_FOUND-class exit 254, script lives in ui/). CI check-runs on e50eba20 at report time: Check Changeset, Check PR Size, Governed Surface Queue Guard, Lint (ESLint, PM dispatch-gates, repo & tooling, CI/release/engine, docs & code guards, scoped x3), PR-body guards, Type Check (workspace, source, consumer, debt ledger) all in_progress; opt-in harnesses skipped.", "line_budget": "216 changed lines (+214/-2, 5 files) vs 250 cap", "files_changed": [ ".changeset/27458-owd-cbp-prerequisite-confirm.md", "ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.tsx", "ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.cbpPrerequisiteConfirm-27458.test.tsx", "ui/packages/i18n/src/namespaces/studio/en.ts", "ui/packages/i18n/src/namespaces/studio/zh.ts" ], "deviations": [ "Dispatch order vs os-dev.md (os-dev wins): PR body footer uses the session-URL form required for PR bodies instead of the bare footer the dispatch named; declaration lines (Fixes/Clause-②/Metadata-protocol) placed before ## 维护者速读 per os-dev ('声明行后'), not after it.", "Panel imports readFields from metadata-admin/previews/object-fields-io.js (already a dependency of owd-sharing.ts) to name the relationship; within the declared panel surface." ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls via fleet-write dispatch, repository_dispatch HTTP 204); issue comment POST /repos/objectstack-ai/objectstack/issues/27458/comments via post-stamped. Plus git push (not REST).", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — multi-row save: rows written before the refused row are already drafts when the confirm opens; cancel leaves them (non-destructive). Recorded in PR Acceptance notes." ] }objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
Landing refused · 2026-10-29T12:52Z · PR #27553 · ACCEPT 6497175213 at head
e50eba20be.node scripts/pm/fleet-write/dispatch.mjs --repo objectstack-ai/objectstack --actions-file F, F =[{"op":"pr_ready","pull":27553},{"op":"automerge_enable","pull":27553}].mergeable_state: clean.objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
Landing refused again · 2026-10-29T13:06Z · PR #27553 · head
e50eba20beunchanged since ACCEPT 6497175213.pr_ready+automerge_enable, pull 27553).objectstack-fleet commentedon Oct 29, 2026
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
落地 · 2026-10-29T19:53Z
c63e9980ca在origin/main上git grep -c "cbpPrerequisite" origin/main -- ui/packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.tsxuseState= 7)状态:卡已由 PR 关闭,摘
pm:dispatched。