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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Implement the objectstack#7494 ruling: view config is explicitly org-wide — console wording/UX + permission-gated write path #5232
Filed by the triage seat (session session_014tGY3fzu4uwCoe7HrfUtWg) as the destination card for a maintainer ruling that had no implementation card for six days. Unassigned — for the repo:objectui lane.
Provenance (the ruling this card implements — final, not to be re-adjudicated)
Wording/UX: console stops presenting sort / hiddenFields / columnState / rowHeight as "persisted user preferences … per-view personal config" (ObjectView.tsx ~1455 and any sibling prose); present them as view configuration that applies to all users of the view.
Permission gate: the updateViewConfig write path (packages/data-objectstack/src/index.ts) is gated behind a view-management-class permission, so an ordinary user can no longer restyle a shared view org-wide from the toolbar.
Not in scope
Per-user view config: parked in objectstack#7611 (v18 direction, restart = real customer demand). ⛔ Do not build any per-user storage under this card.
persistViewPatch merged-base freezing: separate defect card (filed alongside this one, same ruling line 「独立小修,现在做」).
Claim: PM loop round 38 (refill slot)
Session: session_01CSoz9uGhaaSgiq3hshtN7L
Branch: claude/issue-5232-view-config-org-wide
Worktree: objectui-issue-5232
Domain: domain:ui
Container & model: M, mode:subagent, model: opus
Clause-②: yes — a write path gains a permission gate, which changes who a call succeeds for. Declared; Opus under this seat's recorded Fable-quota exemption.
File surface: the console wording (ObjectView.tsx ~:1455 and any sibling prose) and the updateViewConfig write path in packages/data-objectstack/src/index.ts, plus tests and a changeset.
⚠️⚠️HARD SERIAL — packages/data-objectstack/src/index.ts is contended right now. PR #6109 (#5729, per-column sortability) touches fetchObjectSchemaFreshin that exact file and is not merged yet. ⛔ Branch from a base containing it once it lands, and ⛔ if your edit lands in or adjacent to fetchObjectSchemaFresh, stop and report.updateViewConfig should be a different function — ✅ confirm that before writing, and say so. Other siblings: #5420 (app-shell designer save→publish), #5373 (types/core/cli, retiring CRUDSchema), #5247 (core/registry + cli, did-you-mean).
裁决 — maintainer ruling, ⛔ final, not to be re-adjudicated
Maintainer huangyiirene, 2026-08-12, on objectstack#7494 (comment 5261754173), verbatim:
⚠️ This ruling sat six days without an implementation card. It is not a proposal; it is the contract.
Scope — two halves of one contract change
Wording/UX. The console stops presenting sort / hiddenFields / columnState / rowHeight as "persisted user preferences … per-view personal config". They are view configuration that applies to all users of the view, and the UI must say so where an operator can see it before acting.
Permission gate. The updateViewConfig write path is gated behind a view-management-class permission, so an ordinary user can no longer restyle a shared view org-wide from the toolbar.
⛔ Explicitly NOT in scope
⛔ Per-user view config. Parked in objectstack#7611 (v18; restart requires real customer demand). ⛔ Do not build any per-user storage under this card — not a fallback, not a feature flag, not a "while I'm here".
⛔ persistViewPatch merged-base freezing — a separate defect card from the same ruling line (「独立小修,现在做」).
PM mechanism assumptions — measure, do not inherit
⚠️The line number is six days old.ObjectView.tsx ~1455 was measured when the card was filed; packages/plugin-view has moved since. Re-derive the wording site(s) by searching for the prose, not by line number, and report what you found. ⚠️ There may be more than one — the card says "and any sibling prose", which is an admission that the census was not exhaustive. ✅ Do your own census and state its method.
⚠️"A view-management-class permission" names a class, not a permission. ⛔ Do not invent a permission name. Find what this repo already uses for view/designer-class authority, reach that, and say which one you chose and why. ⚠️ If no suitable permission exists, that is a contract gap and you ⛔ stop and report — minting a permission name is not a dev decision.
⚠️A gate that only hides the button is not a gate. The ruling says the write path is gated. Hiding the toolbar affordance while updateViewConfig still accepts the call leaves the org-wide write reachable by anything that calls the adapter. ✅ Gate the write; ⛔ do not settle for the affordance. If you also hide the affordance, say so as an addition, not as the fix.
⚠️The wording change is user-visible text. Check whether these strings are i18n keys before editing English in place; if they are, the change belongs in the locale packs and check:i18n-keys / check:i18n-drift become live gates for you.
Verification
Predict the direction before running. The load-bearing legs: a permitted user still writes view config successfully, and an unpermitted user is refused — both in the same run, so "the gate works" cannot be satisfied by breaking the write for everyone.
⚠️Commit your own edit before you ablate — measured on #5859 today: a trap restore using git checkout -- reverted the dev's still-uncommitted edit along with the probe's mutation, and it reported success both times. ⛔ And note the sharper variant measured on #5674: git checkout <ref> -- <path> writes the INDEX as well as the worktree, so using it to read a baseline and then restoring with git checkout -- <path> restores the baseline over your work.
⚠️Five phantom-class defects were self-caught by devs on this round's cards, all one root: an assertion or control that cannot distinguish the two states of the world — including one where a shared mock object carried a previous test's write into the next case and made it pass while measuring nothing. ✅ State explicitly which of your assertions would still pass if your change were reverted, and make each control a string present in both versions of the file.
⚠️A cached turbo green is not a measurement — measured on #5852 today: an un-forced sweep reported 77/78 cached. Use --force on any turbo-run gate you treat as evidence.
Prove every mutation on disk by grepping injected and separately removed text; ⚠️ print the landing site; ⚠️ assert anchor uniqueness before writing; ⚠️ restore under trap … EXIT INT TERM with a cwd-independent command; confirm git diff HEAD --stat is empty afterwards.
Gates by name, with exit codes:type-check for every package touched (⚠️ hyphenated; echo the script name; distinguish the unbuilt-closure red from the missing-node_modules red; ⚠️build ./examples/** too, not just ./packages/**), root-form vitest quoting per-test names, the downstream prefix-form sweep with the direction demonstrated, eslint with merge-base delta (⚠️ plain eslint .; ⛔ no --no-inline-config), plus check:i18n-keys / check:i18n-drift if item 5 applies.
⚠️Use pnpm exec vitest run [paths] from the repo root — ⛔ notpnpm --filter … test -- [paths], which silently drops everything after --. ⚠️Zero-match pnpm trap: a filter matching nothing prints "No projects matched the filters" and exits 0. Run node scripts/check-changeset-presence.mjs rather than guessing — ⚠️#6073 widened it beyond /src/ today. Changeset minor if a published signature changes, otherwise patch; ⛔ never major. ⚠️Standing rule from #5874: derive your gate set by enumerating each CI job's own step list, ⛔ not from top-level script names.
Deliverable
Draft PR, body with Fixes #5232. ⛔ Do not mark ready, ⛔ do not enqueue, ⛔ no auto-merge — the PM lands it. ⚠️Audit your PR body for closing keywords near any sibling issue number — GitHub's parser ignores negation, so "filed, not fixed: #NNNN" still closes #NNNN (measured on #5674 today). Post the terminal report here (plain-text first-line marker os-dev-report; ⛔ avoid short angle-bracket placeholders in prose) and return it. State, per gate: command, exit code, what a red would have meant; your wording census and its method; which permission you gated on and why; what an unpermitted caller now sees, quoted; which of your assertions would still pass on a revert; and any deviation with its reason.
Activity
yinlianghui commentedon Aug 24, 2026
Claim: PM loop round 38 (refill slot)
Session:
session_01CSoz9uGhaaSgiq3hshtN7LBranch:
claude/issue-5232-view-config-org-wideWorktree:
objectui-issue-5232Domain:
domain:uiContainer & model:
M,mode:subagent,model: opusClause-②: yes — a write path gains a permission gate, which changes who a call succeeds for. Declared; Opus under this seat's recorded Fable-quota exemption.
File surface: the console wording (
ObjectView.tsx~:1455 and any sibling prose) and theupdateViewConfigwrite path inpackages/data-objectstack/src/index.ts, plus tests and a changeset.packages/data-objectstack/src/index.tsis contended right now. PR #6109 (#5729, per-column sortability) touchesfetchObjectSchemaFreshin that exact file and is not merged yet. ⛔ Branch from a base containing it once it lands, and ⛔ if your edit lands in or adjacent tofetchObjectSchemaFresh, stop and report.updateViewConfigshould be a different function — ✅ confirm that before writing, and say so. Other siblings: #5420 (app-shell designer save→publish), #5373 (types/core/cli, retiringCRUDSchema), #5247 (core/registry +cli, did-you-mean).裁决 — maintainer ruling, ⛔ final, not to be re-adjudicated
Maintainer huangyiirene, 2026-08-12, on objectstack#7494 (comment
5261754173), verbatim:Scope — two halves of one contract change
sort/hiddenFields/columnState/rowHeightas "persisted user preferences … per-view personal config". They are view configuration that applies to all users of the view, and the UI must say so where an operator can see it before acting.updateViewConfigwrite path is gated behind a view-management-class permission, so an ordinary user can no longer restyle a shared view org-wide from the toolbar.⛔ Explicitly NOT in scope
persistViewPatchmerged-base freezing — a separate defect card from the same ruling line (「独立小修,现在做」).PM mechanism assumptions — measure, do not inherit
ObjectView.tsx ~1455was measured when the card was filed;packages/plugin-viewhas moved since. Re-derive the wording site(s) by searching for the prose, not by line number, and report what you found.updateViewConfigstill accepts the call leaves the org-wide write reachable by anything that calls the adapter. ✅ Gate the write; ⛔ do not settle for the affordance. If you also hide the affordance, say so as an addition, not as the fix.table.defaultSort#5861, recordActivityFeed: pin the feed-kind map's OPEN-vocabulary relationship tosys_activity.type(ruled direction 4 on objectstack#11507) #5969). ✅ State, quoted, what a user without the permission now sees — and ⛔ if the answer is "the call quietly no-ops", that is not done.check:i18n-keys/check:i18n-driftbecome live gates for you.Verification
Predict the direction before running. The load-bearing legs: a permitted user still writes view config successfully, and an unpermitted user is refused — both in the same run, so "the gate works" cannot be satisfied by breaking the write for everyone.
traprestore usinggit checkout --reverted the dev's still-uncommitted edit along with the probe's mutation, and it reported success both times. ⛔ And note the sharper variant measured on #5674:git checkout <ref> -- <path>writes the INDEX as well as the worktree, so using it to read a baseline and then restoring withgit checkout -- <path>restores the baseline over your work.--forceon any turbo-run gate you treat as evidence.Prove every mutation on disk by grepping injected and separately removed text;⚠️ print the landing site; ⚠️ assert anchor uniqueness before writing; ⚠️ restore under
trap … EXIT INT TERMwith a cwd-independent command; confirmgit diff HEAD --statis empty afterwards.Gates by name, with exit codes:⚠️ hyphenated; echo the script name; distinguish the unbuilt-closure red from the missing-⚠️ build ⚠️ plain
type-checkfor every package touched (node_modulesred;./examples/**too, not just./packages/**), root-form vitest quoting per-test names, the downstream prefix-form sweep with the direction demonstrated, eslint with merge-base delta (eslint .; ⛔ no--no-inline-config), pluscheck:i18n-keys/check:i18n-driftif item 5 applies.pnpm exec vitest run [paths]from the repo root — ⛔ notpnpm --filter … test -- [paths], which silently drops everything after--.node scripts/check-changeset-presence.mjsrather than guessing —/src/today. Changesetminorif a published signature changes, otherwisepatch; ⛔ nevermajor.Deliverable
Draft PR, body with⚠️ Audit your PR body for closing keywords near any sibling issue number — GitHub's parser ignores negation, so "filed, not fixed: #NNNN" still closes #NNNN (measured on #5674 today). Post the terminal report here (plain-text first-line marker
Fixes #5232. ⛔ Do not mark ready, ⛔ do not enqueue, ⛔ no auto-merge — the PM lands it.os-dev-report; ⛔ avoid short angle-bracket placeholders in prose) and return it. State, per gate: command, exit code, what a red would have meant; your wording census and its method; which permission you gated on and why; what an unpermitted caller now sees, quoted; which of your assertions would still pass on a revert; and any deviation with its reason.Generated by Claude Code