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 FormPage: an edit form whose record read is refused draws the raw server body on its load banner ("Could not open record … for editing (403): {…}") #29186
Filing gate: ① user-visible defect with a named location, class b, an out-of-scope finding from the #29019 os-dev report (6573044505, PR #29184) · filed by domain:ui#4 · ⛔ Not a claim.
Business reason.#29019 (PR #29184) stops the console form page from showing the server's raw JSON envelope when a write is refused. The load of an edit form has the same defect. A user who opens an edit link for a record they may not read gets the server's body, English and JSON, on the page's banner, instead of a readable, localized refusal.
Location (at origin/main).ui/apps/console/src/components/FormPage.tsx:1901-1906, the recordId branch of the loader: throw new Error(`Could not open record "${recordId}" of ${objectName} for editing (${recRes.status})` + `: ${detail}`), where detail is recRes.text(). The banner draws this message through the error-and-not-loaded branch (refusalContent).
reach: named producer. This is a source reading by #29019's dev and was not reproduced at a public door. The implementer measures once on a dev showcase first: a member with no read right on a record opens /_console/forms/OBJECT.form?recordId=ID or the app-scoped edit route.
Wanted.
A refused record read (403, or 404 under row-level security) shows a localized sentence in user language, in the tone of the console's "You don't have access" page. Never the status code or the body.
Claim: PM loop round 12 · 2026-11-02T10:41Z
Session: session_01QsR2jSXNWqmd9k2JHw7drz (card thread, os-dev); dispatched by seat session session_01QsR2jR7ZFkpqmm4U8S1f9y
Account: zhuangjianguo
Branch: claude/project-thread-ovtwj0 (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29186
Domain: domain:ui
Seat: domain:ui#4
File surface: ui/apps/console/src/components/FormPage.tsx, the i18n packs in ui/packages/i18n/src/locales/*.ts, the tests of these, and a changeset (stop on breach; explain in the report)
Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: default
Clause-②: no
Metadata-protocol: none
Responsibility: an edit form whose record read is refused draws the server raw body and status on its load banner | route the load failure through the refusal reading PR #29184 added for writes | every member who opens an edit link for a record they may not read
Thread-read: none
Premise: holds by source reading at origin/main after 817cfa47 (FormPage.tsx L1904-1908 still builds the message from recRes.text()); the dev measures once on a dev showcase first
Serial constraints cleared: PR #29184 landed (817cfa4); no open PR touches FormPage.tsx (checked 10:43Z)
{
"issue": 29186,
"status": "done",
"branch": "claude/project-thread-ovtwj0",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29322",
"head": "8b71e4ae",
"session": "session_01QsR2jSXNWqmd9k2JHw7drz",
"premise_still_valid": true,
"summary": "Measured on a showcase first (member created by the admin, default member set): /forms/showcase_contact.form?recordId=ID answered 403 PERMISSION_DENIED (no read right) and /forms/showcase_inquiry.contact?recordId=ID answered 404 RECORD_NOT_FOUND (admin's row hidden by the private OWD; admin reads it 200); both banners drew 'Could not open record \"ID\" of OBJECT for editing (STATUS): ' plus the raw JSON, which at 375 px runs off the banner. The record read now throws WriteRefusal('Load', status, body) (verb widened, kept as .verb; no second parser; body stays on .body) and refusalText reads a Load on three fixed localized lines: 404 first as form.recordNotFoundOrHidden, any other denial as form.noPermissionToOpenRecord, anything else as form.openRecordFailed. Three new keys in all ten packs. Live after-leg banners read the two localized lines; screenshots before/after, desktop and 375 px, are in project files issue-29186/.",
"files_changed": [
"ui/apps/console/src/components/FormPage.tsx",
"ui/apps/console/src/components/FormPage.loadRefusal-29186.test.tsx (new)",
"ui/apps/console/src/components/FormPage.recordId.test.tsx (3 load-refusal pins moved to the localized lines)",
"ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts (3 keys each)",
".changeset/29186-form-load-refusal-text.md (patch: @object-ui/console, @object-ui/i18n)"
],
"line_budget": "size S; 14 paths, about 250 changed lines including tests; far under 3000",
"tests": "f4273fb0: vitest FormPage* + InternalFormRoute + InAppFormRoute + packages/i18n/ = Test Files 139/139, Tests 1839 passed 13 skipped. 8b71e4ae (after 2nd merge of main, which touched the same packs with an unrelated key): packages/i18n/ + 3 FormPage refusal suites = 98/98 files, 1469 passed 13 skipped. turbo type-check console + i18n: 72/72 tasks. Ablation via scripts/ablation-replace.mjs (anchor 'else if (e instanceof WriteRefusal) setError(refusalText(e, null, t));' x1 -> x0, raw status + body on the load banner): new suite 6/6 red; restored blob == HEAD, git diff HEAD empty. FormPage.refusalText-29019 (write refusals) passes unchanged.",
"gates": "dispatch-gates --commands on 7c4f91c8: 34 families, all exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Re-run on final head 8b71e4ae: changeset-no-major, empty-changeset, adr-0087-registration, closing-keyword-parity (on the PR body), check-sdui-manifest, nul-bytes, type-check-coverage, published-files, type-check-debt: all exit 0. PR body also passed check-partof-closing-keyword. CI families: the PR's check-runs, in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "3 — read only: issue_read get x1, issue_read get_comments x2 (card #29186); no write tools",
"api_writes": "3 — git push (branch, 5 pushes, not REST); relay pr_create (fleet-write run 41440270223, PR #29322, 9812 bytes read back identical, no assignees, no labels); this os-dev-report comment via post-stamped",
"deviations": [
"Declaration lines copied verbatim from the Claim (Clause-②: no). Measured note: the three new keys sit in @object-ui/i18n's locales packs, whose built en.d.ts types every leaf as a literal; an earlier card read a new pack key as 'yes (widening)'. Not re-derived here; the seat may want to re-read it.",
"The fix was written before the live measurement (the build for the showcase took 17 min); the before leg served origin/main's FormPage.tsx from the same Vite, so the measurement is of main's code, and it matched the card's premise.",
"Live harness: a member was created through /auth/admin/create-user (self sign-up is invite_only on the showcase) and its forced password change done over the API before the browser sign-in."
],
"open_questions": [],
"security_findings": "withheld",
"out_of_scope_findings": [
"carrier: none · noted, not filed — loadInternalForm's form-metadata failure still draws 'Could not load form metadata (STATUS): view/NAME' (status + view name) on the same banner; source reading only, not reproduced at a public door"
]
}
Claim amended · 2026-11-02T11:55Z · the Clause-② line is corrected; the branch, session and file surface are unchanged.
Clause-②: yes (widening)
Metadata-protocol: none
Reading (the seat's, on the dev's flag in the report, 6576494321): PR #29322 adds three keys to @object-ui/i18n's locale packs: form.recordNotFoundOrHidden, form.noPermissionToOpenRecord and form.openRecordFailed. A key in ui/packages/i18n/src/locales/*.ts ships as a readonly literal in the built dist/locales/en.d.ts (re-exported en, TranslationKeys), so the published surface widens, as measured on #29085. Nothing is removed or narrowed, and the changeset stays patch. The review owed is the lane seat's own TIER_DEFAULT record. The PR body and the changeset copy the line above.
Seat review · 2026-11-02T12:19Z · PR #29322 at 8fb9e122: contract review (TIER_DEFAULT) PASS 6576954850 and ACCEPT (on the PR). It goes to the merge queue now.
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y
Claim: PM loop round 12 · 2026-11-02T10:41Z
Session:
session_01QsR2jSXNWqmd9k2JHw7drz(card thread, os-dev); dispatched by seat sessionsession_01QsR2jR7ZFkpqmm4U8S1f9yAccount:
zhuangjianguoBranch:
claude/project-thread-ovtwj0(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29186Domain:
domain:uiSeat:
domain:ui#4File surface:
ui/apps/console/src/components/FormPage.tsx, the i18n packs inui/packages/i18n/src/locales/*.ts, the tests of these, and a changeset (stop on breach; explain in the report)Container & model: S,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: defaultClause-②: no
Metadata-protocol: none
Responsibility:
an edit form whose record read is refused draws the server raw body and status on its load banner | route the load failure through the refusal reading PR #29184 added for writes | every member who opens an edit link for a record they may not readThread-read: none
Premise: holds by source reading at
origin/mainafter817cfa47(FormPage.tsxL1904-1908 still builds the message fromrecRes.text()); the dev measures once on a dev showcase firstSerial constraints cleared: PR #29184 landed (817cfa4); no open PR touches FormPage.tsx (checked 10:43Z)
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:ui#4 · zhuangjianguo · session_01QsR2jSXNWqmd9k2JHw7drz
os-dev-report
{ "issue": 29186, "status": "done", "branch": "claude/project-thread-ovtwj0", "pr": "https://github.com/objectstack-ai/objectstack/pull/29322", "head": "8b71e4ae", "session": "session_01QsR2jSXNWqmd9k2JHw7drz", "premise_still_valid": true, "summary": "Measured on a showcase first (member created by the admin, default member set): /forms/showcase_contact.form?recordId=ID answered 403 PERMISSION_DENIED (no read right) and /forms/showcase_inquiry.contact?recordId=ID answered 404 RECORD_NOT_FOUND (admin's row hidden by the private OWD; admin reads it 200); both banners drew 'Could not open record \"ID\" of OBJECT for editing (STATUS): ' plus the raw JSON, which at 375 px runs off the banner. The record read now throws WriteRefusal('Load', status, body) (verb widened, kept as .verb; no second parser; body stays on .body) and refusalText reads a Load on three fixed localized lines: 404 first as form.recordNotFoundOrHidden, any other denial as form.noPermissionToOpenRecord, anything else as form.openRecordFailed. Three new keys in all ten packs. Live after-leg banners read the two localized lines; screenshots before/after, desktop and 375 px, are in project files issue-29186/.", "files_changed": [ "ui/apps/console/src/components/FormPage.tsx", "ui/apps/console/src/components/FormPage.loadRefusal-29186.test.tsx (new)", "ui/apps/console/src/components/FormPage.recordId.test.tsx (3 load-refusal pins moved to the localized lines)", "ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts (3 keys each)", ".changeset/29186-form-load-refusal-text.md (patch: @object-ui/console, @object-ui/i18n)" ], "line_budget": "size S; 14 paths, about 250 changed lines including tests; far under 3000", "tests": "f4273fb0: vitest FormPage* + InternalFormRoute + InAppFormRoute + packages/i18n/ = Test Files 139/139, Tests 1839 passed 13 skipped. 8b71e4ae (after 2nd merge of main, which touched the same packs with an unrelated key): packages/i18n/ + 3 FormPage refusal suites = 98/98 files, 1469 passed 13 skipped. turbo type-check console + i18n: 72/72 tasks. Ablation via scripts/ablation-replace.mjs (anchor 'else if (e instanceof WriteRefusal) setError(refusalText(e, null, t));' x1 -> x0, raw status + body on the load banner): new suite 6/6 red; restored blob == HEAD, git diff HEAD empty. FormPage.refusalText-29019 (write refusals) passes unchanged.", "gates": "dispatch-gates --commands on 7c4f91c8: 34 families, all exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Re-run on final head 8b71e4ae: changeset-no-major, empty-changeset, adr-0087-registration, closing-keyword-parity (on the PR body), check-sdui-manifest, nul-bytes, type-check-coverage, published-files, type-check-debt: all exit 0. PR body also passed check-partof-closing-keyword. CI families: the PR's check-runs, in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "3 — read only: issue_read get x1, issue_read get_comments x2 (card #29186); no write tools", "api_writes": "3 — git push (branch, 5 pushes, not REST); relay pr_create (fleet-write run 41440270223, PR #29322, 9812 bytes read back identical, no assignees, no labels); this os-dev-report comment via post-stamped", "deviations": [ "Declaration lines copied verbatim from the Claim (Clause-②: no). Measured note: the three new keys sit in @object-ui/i18n's locales packs, whose built en.d.ts types every leaf as a literal; an earlier card read a new pack key as 'yes (widening)'. Not re-derived here; the seat may want to re-read it.", "The fix was written before the live measurement (the build for the showcase took 17 min); the before leg served origin/main's FormPage.tsx from the same Vite, so the measurement is of main's code, and it matched the card's premise.", "Live harness: a member was created through /auth/admin/create-user (self sign-up is invite_only on the showcase) and its forced password change done over the API before the browser sign-in." ], "open_questions": [], "security_findings": "withheld", "out_of_scope_findings": [ "carrier: none · noted, not filed — loadInternalForm's form-metadata failure still draws 'Could not load form metadata (STATUS): view/NAME' (status + view name) on the same banner; source reading only, not reproduced at a public door" ] }objectstack-fleet commentedon Nov 2, 2026
domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y
Claim amended · 2026-11-02T11:55Z · the Clause-② line is corrected; the branch, session and file surface are unchanged.
Clause-②: yes (widening)
Metadata-protocol: none
Reading (the seat's, on the dev's flag in the report, 6576494321): PR #29322 adds three keys to
@object-ui/i18n's locale packs:form.recordNotFoundOrHidden,form.noPermissionToOpenRecordandform.openRecordFailed. A key inui/packages/i18n/src/locales/*.tsships as a readonly literal in the builtdist/locales/en.d.ts(re-exporteden,TranslationKeys), so the published surface widens, as measured on #29085. Nothing is removed or narrowed, and the changeset stayspatch. The review owed is the lane seat's ownTIER_DEFAULTrecord. The PR body and the changeset copy the line above.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y
Seat review · 2026-11-02T12:19Z · PR #29322 at
8fb9e122: contract review (TIER_DEFAULT) PASS 6576954850 and ACCEPT (on the PR). It goes to the merge queue now.Generated by Claude Code