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
console: the record create/edit dialog shows only "You don't have permission to save this record." on a controlled_by_parent master-edit refusal, dropping the API's reason ("requires edit access to its master record"); #7366 regression on this path #33524
What happens (@objectstack 18.4.0, measured by HotCRM's Order to Cash browser pass on 2026-11-14)
A user who reads a contract but does not edit it opens the create dialog of a controlled_by_parent detail (HotCRM crm_billing_milestone, crm_invoice) and saves. The API answers 403 with a reason saying the write requires edit access to its master record. The console shows only the generic toast: "You don't have permission to save this record." The user cannot tell that the missing access is on the contract, not on the record they are creating.
#7366 (closed) fixed "Console discards the server error message on 403". This path either does not take that fix or has regressed.
Ask
On a 403 whose envelope carries a userMessage (or a master-chain reason), the create and edit dialogs show it, as they do for other refusals.
Acceptance
A master-edit refusal on create shows the server's reason, naming the master object, in the dialog or toast, in en and zh-CN.
The same applies on edit.
A refusal with no userMessage keeps the generic line.
The refusal is loud, but the console drops the reason that says which record needs edit access. On its own that is p3 copy. HotCRM's Order to Cash users hit it on 18.4.0, so it is raised once to p2. It looks like the #7366 fix does not cover the create/edit dialog path: check which error shape that path reads.
Claim: PM loop round 1 · 2026-11-15T00:13Z
Session: session_01FEkQ5m1xDT63aCaQJNjwXD (card thread, dev) · seat session_01FEkQ5oF8GgTHN2jBZoDwz8
Account: os-project-manager
Branch: claude/project-thread-bhbxol
Worktree: objectstack-issue-33524
Domain: domain:ui
Seat: domain:ui#2
File surface: ui/apps/console/src/components/FormPage.tsx (the permission-refusal text), the plugin-form modal/drawer submit refusal path if that is the create dialog, ui/packages/app-shell/src/providers/saveAdvisoryToast.ts, the error-toast reader in ui/packages/app-shell/src/utils/ (flowResponse.ts), their tests, i18n packs only if a key is truly new, root .changeset/. The dev declares the final files per half at first hand-back. ⛔ No packages/spec, server or cloud edit.
Container & model: M, mode:thread, model: default tier, effort: default
Clause-②: no
Metadata-protocol: none
Responsibility: the console's create/edit dialog replaces a 403's producer userMessage (plugin-security's master-edit refusal) with the generic permission line | the producer already sends the localized reason (#33290) | every user saving a controlled_by_parent detail without edit access on its master (HotCRM Order to Cash)
Thread-read: 6886080721
Premise: read at filing on 18.4.0 by HotCRM's browser pass; not re-measured by the seat; the dev measures on origin/main first
Serial constraints cleared: no other pm:dispatcheddomain:ui card claims a file in this surface (live label read; ui seat 1's live files #33317#33063#33061#33103#33377 are disjoint); no other ui seat holds a Claim: on these files
Scope: shared card thread with #32657 (one dev, one PR Fixes #33524 + Fixes #32657 if both halves land, else one PR per card). p2. Order: /mnt/project-files/pm-orders/ui/order-33524.md. Summons: the maintainer's 「同意 给队列最深的 ui 和 spec 各再开一个座位」 (this project, 2026-11-14T22:46Z).
Claim amendment · Premise: corrected · 2026-11-15T00:16Z · to claim 6886417201. Dev's measurement on e3f0cfd4 (/mnt/project-files/pm-orders/ui/33524-measurement.md):
The create dialog HotCRM opens is the console's modal form, and its renderer already reads the producer's userMessage first (as do the record form page and the edit conflict path). The generic "You don't have permission to save this record." shows only when the refusal carries no userMessage.
So acceptance 1 and 2 are a server fix (plugin-security composes a localized userMessage naming the master record), outside the ui lane.
The ui half shrinks to rendered pins proving the dialog shows a userMessage on create and edit (en and zh-CN) and keeps the generic line without one. That ships in the shared PR as Refs #33524, with no product change. After it merges, the seat releases this card to triage with pm:retriage to re-lane it to domain:server.
Activity
objectstack-fleet commentedon Nov 14, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: first touch →
domain:ui· p2 ·pm:queue· 2026-11-14T23:44Z⛔ Not a claim.
The refusal is loud, but the console drops the reason that says which record needs edit access. On its own that is p3 copy. HotCRM's Order to Cash users hit it on 18.4.0, so it is raised once to p2. It looks like the #7366 fix does not cover the create/edit dialog path: check which error shape that path reads.
objectstack-fleet commentedon Nov 15, 2026
domain:ui#2 · os-project-manager · session_01FEkQ5oF8GgTHN2jBZoDwz8
Claim: PM loop round 1 · 2026-11-15T00:13Z
Session:
session_01FEkQ5m1xDT63aCaQJNjwXD(card thread, dev) · seatsession_01FEkQ5oF8GgTHN2jBZoDwz8Account:
os-project-managerBranch:
claude/project-thread-bhbxolWorktree:
objectstack-issue-33524Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/apps/console/src/components/FormPage.tsx(the permission-refusal text), the plugin-form modal/drawer submit refusal path if that is the create dialog,ui/packages/app-shell/src/providers/saveAdvisoryToast.ts, the error-toast reader inui/packages/app-shell/src/utils/(flowResponse.ts), their tests, i18n packs only if a key is truly new, root.changeset/. The dev declares the final files per half at first hand-back. ⛔ Nopackages/spec, server or cloud edit.Container & model: M,
mode:thread,model: default tier,effort: defaultClause-②: no
Metadata-protocol: none
Responsibility: the console's create/edit dialog replaces a 403's producer
userMessage(plugin-security's master-edit refusal) with the generic permission line | the producer already sends the localized reason (#33290) | every user saving acontrolled_by_parentdetail without edit access on its master (HotCRM Order to Cash)Thread-read: 6886080721
Premise: read at filing on 18.4.0 by HotCRM's browser pass; not re-measured by the seat; the dev measures on
origin/mainfirstSerial constraints cleared: no other
pm:dispatcheddomain:uicard claims a file in this surface (live label read; ui seat 1's live files #33317 #33063 #33061 #33103 #33377 are disjoint); no other ui seat holds aClaim:on these filesScope: shared card thread with #32657 (one dev, one PR
Fixes #33524+Fixes #32657if both halves land, else one PR per card). p2. Order:/mnt/project-files/pm-orders/ui/order-33524.md. Summons: the maintainer's 「同意 给队列最深的 ui 和 spec 各再开一个座位」 (this project, 2026-11-14T22:46Z).objectstack-fleet commentedon Nov 15, 2026
domain:ui#2 · os-project-manager · session_01FEkQ5oF8GgTHN2jBZoDwz8
Claim amendment · Premise: corrected · 2026-11-15T00:16Z · to claim 6886417201. Dev's measurement on
e3f0cfd4(/mnt/project-files/pm-orders/ui/33524-measurement.md):userMessagefirst (as do the record form page and the edit conflict path). The generic "You don't have permission to save this record." shows only when the refusal carries nouserMessage.packages/plugins/plugin-security/src/security-plugin-cbp-write-gate.ts(~L463, the master-edit denial) throws a bare permission error with English developer prose and no user message. fix(plugin-security): permission refusals speak the caller's language, falling back to the workspace default (#32656, 2/2) #33290 localized the other permission refusals, not this one.userMessagenaming the master record), outside the ui lane.The ui half shrinks to rendered pins proving the dialog shows a
userMessageon create and edit (en and zh-CN) and keeps the generic line without one. That ships in the shared PR asRefs #33524, with no product change. After it merges, the seat releases this card to triage withpm:retriageto re-lane it todomain:server.