Skip to content

fix(platform-objects): remove the permanently-empty permission_change tile from the System Overview dashboard - #8731

Merged
hotlong merged 2 commits into
mainfrom
claude/issue-8148-remove-permission-change-widget
Aug 14, 2026
Merged

fix(platform-objects): remove the permanently-empty permission_change tile from the System Overview dashboard#8731
hotlong merged 2 commits into
mainfrom
claude/issue-8148-remove-permission-change-widget

Conversation

@hotlong

@hotlong hotlong commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #8148

The System Overview board shipped a "Permission Changes" metric tile filtering sys_audit_log.action = 'permission_change'. It could never report anything but 0, on any deployment that has ever existed — the value had no writer anywhere in the repo. There are exactly two sys_audit_log writers: plugin-audit's generic hook writer, whose actionFor maps afterInsert/afterUpdate/afterDelete to create/update/delete and nothing else, and plugin-auth's admin user-import. Neither has ever emitted permission_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

  • The tile is removed. The two surviving Row 2 tiles ("Login Events", "Config Changes") split the 12-column row in half — the Row 3 shape — rather than leaving a 4-column hole where it sat.
  • Its title/description are dropped from all four locale bundles (en / zh-CN / ja-JP / es-ES).
  • The by-action tile's description stops naming permission among 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 / update rows written by the generic hook against the permission objects. The honest lens on them is object_name on 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.

⚠️ Scope narrowed against the card body — import is deliberately untouched

The 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']. import is retained.
  • The same file's config_changes list view actively filters ['config_change', 'import'] — consumed, not merely tolerated.
  • plugin-auth/src/admin-import-users.ts writes action: 'import' — a real writer, pinned by dogfood case W4.

Executing the card verbatim would have stripped import from 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 for import was 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

  • Tombstone (system-overview-tile-semantics.test.ts): no board widget may filter a retired action value, and widget_permission_changes may 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. import is explicitly not on the retired list, with a comment saying why it must not be added.
  • The reverse direction the parity test was missing (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):

check result
pnpm --filter @objectstack/platform-objects test 20 files, 376 tests passed
pnpm --filter @objectstack/platform-objects typecheck exit 0
check:i18n (--filter=platform-objects) OK — in sync (8 bundles), no undeclared authoring keys
check:nul-bytes OK, 5745 files, no raw control bytes
check:type-check-coverage (structural) OK
check:query-options-erasure OK — none new; baseline verified against 6158146
TEST_DEBT re-measure, exclusion lifted exactly 3, all pre-existing in feature-gate-guard.test.ts (TS2339 x2, TS7006 x1) — matches the ledger, none in the edited test files, ratchet unmoved

Gate 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.ts explains why: Setup is composed at runtime, so regenerating over it would delete ~40 live nav translations per locale). The generated bundles are typed TranslationData['objects'] / ['metadataForms'] and carry no dashboards subtree, 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 to main. check:i18n confirms that directly rather than by inference. No overlap with #8705 (already merged as 6158146, and it touched no bundle this diff reads).

Filed while here, not fixed here

#8721widget_recent_events serves its pre-conversion title (Recent Audit Events) in all four locales while the source declares Audit Events by Action; the hand-authored apps / dashboards translation 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

claude added 2 commits August 14, 2026 16:16
… 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
@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 14, 2026 4:41pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/platform-objects.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/plugins/packages.mdx (via @objectstack/platform-objects)
  • content/docs/ui/setup-app.mdx (via @objectstack/platform-objects)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 14, 2026
@hotlong
hotlong marked this pull request as ready for review August 14, 2026 17:07
@hotlong
hotlong added this pull request to the merge queue Aug 14, 2026
Merged via the queue into main with commit b887013 Aug 14, 2026
29 checks passed
@hotlong
hotlong deleted the claude/issue-8148-remove-permission-change-widget branch August 14, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants