Uh oh!
There was an error while loading. Please reload this page.
fix(platform-objects): remove the permanently-empty permission_change tile from the System Overview dashboard - #8731
Merged
Conversation
… dashboard tile The System Overview board's "Permission Changes" tile filtered `sys_audit_log.action = 'permission_change'`, a value nothing in the repo has ever written — the only two audit writers are plugin-audit's generic hook (create/update/delete) and plugin-auth's admin user-import. The tile read `0` on every deployment that has ever existed, and #8147 then retired the value from the enum outright, leaving a filter no row can match. On a compliance surface an empty tile is worse than a missing one: "Permission Changes: 0" reads as a negative finding rather than an absent feature. - remove the tile; the two surviving Row 2 tiles split the 12-col row in half rather than leaving a hole where it sat - drop its title/description from all four locale bundles - stop naming `permission` among the example actions in the by-action tile's description (source + all four locales — the translations are the served text) - pin both directions: a tombstone for retired action values on the board, and the missing reverse direction in the app/dashboard translation parity test, which had no guard against a translation outliving its widget `import` is deliberately untouched: it was named in the same ruling but keeps a live writer and a shipped list view, so retiring it from the UI would produce the inverse defect. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeQRiAa7vYRVX5Fog7Zby8
…le removal Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeQRiAa7vYRVX5Fog7Zby8
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 14, 2026
hotlong
marked this pull request as ready for review
August 14, 2026 17:07
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#8148
The System Overview board shipped a "Permission Changes" metric tile filtering
sys_audit_log.action = 'permission_change'. It could never report anything but0, on any deployment that has ever existed — the value had no writer anywhere in the repo. There are exactly twosys_audit_logwriters:plugin-audit's generic hook writer, whoseactionFormaps afterInsert/afterUpdate/afterDelete tocreate/update/deleteand nothing else, andplugin-auth's admin user-import. Neither has ever emittedpermission_change. #8147 (PR #8200,344a22a8) then retired the value from the action enum outright, so the tile's filter now names a value the platform does not even declare — doubly dead.An empty tile on a compliance surface is worse than a missing one. A permanently-
0"Permission Changes" count does not read as "this platform does not track permission changes"; it reads as a negative finding — an auditor concludes the platform watched over the selected window and found none. 审计面宁窄勿谎.What changed
en/zh-CN/ja-JP/es-ES).permissionamong its example actions, in the source and in all four locales. The translations are the strings actually served, so correcting only the source would not have reached a single user.Removed, not refiltered onto a live action
Permission and role edits are captured today — as ordinary
create/updaterows written by the generic hook against the permission objects. The honest lens on them isobject_nameon the audit list view: a row-level question, not a single-number KPI. Approximating one as a tile would have put a second not-quite-true number on the same board. This is the ruling's own 宁窄勿谎 default, and the card's unlock note reached it independently.importis deliberately untouchedThe issue body quotes a ruling retiring three values (
export/import/permission_change) and marks it "binding — not re-adjudicable". Only two landed, and I re-measured that on the merged ref rather than inheriting the report:plugin-audit/src/objects/sys-audit-log.object.ts— the enum is['create','update','delete','login','logout','config_change','import'].importis retained.config_changeslist view actively filters['config_change', 'import']— consumed, not merely tolerated.plugin-auth/src/admin-import-users.tswritesaction: 'import'— a real writer, pinned by dogfood case W4.Executing the card verbatim would have stripped
importfrom the dashboard while the enum keeps it, a list view filters it, and a real writer produces it — an audit action that can be written but cannot be found, the exact inverse of the ruling's own principle. I am not re-adjudicating: the retirement premise forimportwas falsified during #8147's implementation and the enum already landed on the falsified-corrected fact. This PR aligns the dashboard with what landed.Both directions are pinned
system-overview-tile-semantics.test.ts): no board widget may filter a retired action value, andwidget_permission_changesmay not come back. Carries an opposite-direction control — a live action filter (login,config_change) must still be visible through exactly the same read, so the block cannot pass on a board with no widgets or whose predicates moved.importis explicitly not on the retired list, with a comment saying why it must not be added.app-nav-translation-parity.test.ts): it asserted every declared widget has a translation, but nothing stopped a translation outliving its widget — which is exactly what these four locale entries would have done. The same block already existed for Studio's nav ids; a dashboard can be walked statically, so there was nothing preventing the general claim.Reverse verification (from the committed state, direction predicted before running): restoring the widget turns 6 assertions red — 2 tombstone + 4 parity forward-direction (one per locale) — while the live-action control stays green. Both new blocks are load-bearing.
Verification
All at
e6e8aa0, the final commit, on a built dependency closure (pnpm --filter '@objectstack/platform-objects^...' build):pnpm --filter @objectstack/platform-objects testpnpm --filter @objectstack/platform-objects typecheckcheck:i18n(--filter=platform-objects)check:nul-bytescheck:type-check-coverage(structural)check:query-options-erasure6158146feature-gate-guard.test.ts(TS2339 x2, TS7006 x1) — matches the ledger, none in the edited test files, ratchet unmovedGate list re-derived against the actual changed paths with
scripts/pm/dispatch-gates.mjs, which surfaced three families beyond the dispatched list —check:query-options-erasure,check:type-check-coverage,check:type-check-debt— all run or accounted for above.No bundle was regenerated, and none needed to be. The
dashboards.*half of this package's i18n is hand-authored by design (scripts/i18n-extract.config.tsexplains why: Setup is composed at runtime, so regenerating over it would delete ~40 live nav translations per locale). The generated bundles are typedTranslationData['objects']/['metadataForms']and carry nodashboardssubtree, the emit is--objects-only, and this diff touches no object definition and no*.generated.ts— so a fresh extract's input is byte-identical tomain.check:i18nconfirms that directly rather than by inference. No overlap with #8705 (already merged as6158146, and it touched no bundle this diff reads).Filed while here, not fixed here
#8721 —
widget_recent_eventsserves its pre-conversion title (Recent Audit Events) in all four locales while the source declaresAudit Events by Action; the hand-authoredapps/dashboardstranslation half has no source-vs-translation content gate at all, so any source-string edit silently leaves four bundles behind it under a green build. Unrelated drift, deliberately left alone here.#8315(restore) is not addressed here, and objectui#4476 carries the same wrong "three retired values" framing — different repo, different seat, untouched.Generated by Claude Code