ADORSYS-GIS / ADORSYS-GIS/converse-frontends

[Ticket]: Dead-code inventory after admin console v2 — owner decides

Ouverte
#472 0 commentaires 0 réactions 1 personne assignée Réclamée par @stephane-segning Voir sur GitHub
ticket
Langage dominant
TypeScript
Étoiles
0
Forks
0
Merge moyen
1 h 49 min
PR mergées (30 j)
253

Description

### Type

Technical debt

### Summary

We need an owner ruling on the dead code the admin-console-v2 sweep (#456–#470) left behind, because several deletions were only half-completed and two whole workspace packages now have zero consumers. This ticket is an **inventory, not a change** — nothing here has been deleted, and nothing should be until the owner decides class by class.

Expected result:
> The owner ticks the boxes below. Each ticked box becomes a scoped follow-up PR. Untickled boxes are recorded as "keep, deliberately" so the next audit does not re-raise them.

### Intent

Two of the biggest findings are not the ones anyone flagged. `@lightbridge/hooks`'s **root** export has zero importers repo-wide — only two of its six subpaths are used — which makes 25 of its 34 source files unreachable, and drags `packages/api-native` and `packages/i18n` down with it. That is the `apps/self-service` residue, and it is much larger than "`rbac.ts` has zero consumers". Conversely, six of the things flagged as leftovers (`SpendSeriesChart`, `ReportExportPanel`/`ReportExportDialog`, `previousWindow`, `isAdmin`, `RailResizer`, `LatencyStatCards`) are verifiably live and should be struck off, not deleted.

### Source of truth (links)

https://github.com/ADORSYS-GIS/converse-frontends/issues/443

Full inventory with per-item evidence: `scratchpad/dead-code-inventory.md` (attached in the audit run; reproducible from the commands below).

### Current Behavior

Audited `origin/main` @ `5418678` in a clean worktree after `pnpm install`.

```
npx -y knip@5 --no-progress --config --include files,exports,types,dependencies
npx -y knip@5 --no-progress --config --include files # stories NOT entries
npx -y ts-prune@0.10 -p apps/console/tsconfig.json | grep -v "used in module"
npx -y depcheck@1 apps/console ; npx -y depcheck@1 packages/hooks ; npx -y depcheck@1 packages/ui-web
rg -n -w "" --glob '!node_modules' apps packages
```

knip: 4 unused files, 12 unused dependencies, 6 unused devDependencies, 61 unused exports, 115 unused exported types. Every one was re-checked by grep before being classified — roughly two thirds turned out to be surplus `export` keywords on live code, or public design-system API, not dead code.

### Expected Behavior

Each item below is classified and carries the command that proves it. **(A)** = no references anywhere, no story, no test. **(B)** = referenced only by its own test/story. **(C)** = verified live, do not delete. **(D)** = duplicated logic.

#### (A) Safe to delete — 11 items

- [ ] `packages/api-native/` (whole package) — **A** — `rg -n "@lightbridge/api-native" --glob '!node_modules' apps packages` → 2 hits, both `package.json`. Nothing imports it. — **delete the package and the dep line in `packages/hooks/package.json`**
- [ ] `packages/hooks/src/index.ts` + 25 modules only it re-exports (`accounts`, `api-keys`, `authz-types`, `auth-session`, `auth/*` ×8, `budget`, `data/*` ×2, `keycloak-login`, `locale-sync`, `pagination`, `projects`, `rbac`, `sync/*` ×2, `use-permissions`, `use-query-state`) — **A** — `rg -n "@lightbridge/hooks'" --glob '!node_modules' apps packages` → **1 hit, a doc comment**; only `/api-error` and `/budget-tiers` subpaths are ever imported — **shrink `packages/hooks` to `api-error.ts`, `budget-tiers.ts`, `wire-safety.ts` + their tests**
- [ ] `packages/i18n/` (whole package) — **A** — its only importers are `packages/hooks/src/{locale-sync,projects}.ts`, both in the item above; `apps/governance-auth/README.md:285` already records it has no web consumer — **delete after the item above**
- [ ] `packages/hooks/src/data/api-keys-store.ts` — **A** — knip *Unused files*; `syncApiKeys` is a stub — **delete**
- [ ] `packages/api-rest/src/hook/index.ts` — **A** — knip *Unused files*; one line, `export * from './client'`, zero importers — **delete**
- [ ] `apps/console/src/server/reports/panel-svg.ts:113` `resetChartRendererCache` — **A** — `rg -n -w resetChartRendererCache apps packages` → 1 line, the definition — **delete, or wire it into the vitest teardown it was clearly written for**
- [ ] `packages/hooks/src/auth/use-auth-session.ts:54` `validateStoredTokenAudience` — **A** — `rg -n -w` → 1 line, the definition — **delete**
- [ ] `packages/ui-web/src/lib/rail-grid.ts:56` `RAIL_ACTIVE_BAR_WIDTH` — **A** — `rg -n -w` → 1 line, the definition; every sibling `RAIL_*` constant is consumed by `nav-spine`/`sub-nav`, this one is not — **delete**
- [ ] `apps/console/src/containers/use-create-account-dialog.ts:132` `export { normalizeAccountName }` — **A** — both real consumers import it from `./build-create-account-input` directly — **delete the re-export line**
- [ ] Unused deps: `@tanstack/query-core` (`apps/console`), `@lightbridge/api-native` + `expo-crypto` (`packages/hooks`), `eslint-config-prettier` (root) — **A** — knip **and** depcheck agree; `eslint.config.js` never references `eslint-config-prettier` — **remove the four lines, then `pnpm --filter console build:web`**
- [ ] `packages/hooks/package.json` `exports` subpaths `./pagination`, `./use-query-state`, `./wire-safety` — **A** — `rg -o "@lightbridge/hooks[a-z/._-]*" apps packages | sort | uniq -c` → only `/api-error` and `/budget-tiers` are imported (`wire-safety` stays as an internal relative import) — **remove the three subpath entries**

#### (B) Referenced only by its own tests/stories — 7 items

- [ ] `packages/ui-web/src/refine-mock/` (16 files) — **B** — `rg -n "refine-mock" .` → only doc-comment mentions outside the directory; its own comments say the screens moved onto the real console; it is the last consumer of `@refinedev/core` in ui-web — **delete the directory and the devDependency**
- [ ] `packages/ui-web/src/components/histogram-chart/` — **B** — barrel + own story + own test only; `sections/dashboard-panels/panel-renderers.tsx` imports 8 marks and this is not one of them — **delete, or wire a `histogram` panel type**
- [ ] `packages/ui-web/src/components/command-snippet/` — **B** — barrel + own story + own test only — **delete, or use it in the API-key/CLI surface it was built for**
- [ ] `packages/ui-web/src/sections/spend-share/` (`SpendShareSection`) — **B** — only its own story; `refine-mock/mock-data-provider.ts:53` records "MODEL renders through `RankedSeriesRows` now, not `SpendShareSection`/`ShareBar`". **Note `components/share-bar` is live** (`panel-renderers.tsx:226`) — only the section dies — **delete the section, keep `ShareBar`**
- [ ] `packages/ui-web/src/sections/overview-controls/` — **B** — its only importer is `refine-mock/refine-overview-screen.tsx:30` plus seven page stories — **delete together with `refine-mock`**
- [ ] `packages/hooks/src/rbac.ts` — **B** — every export is used only by `rbac.test.ts` and by `use-permissions.ts`, itself unimported — **delete (subsumed by the `packages/hooks` item in A)**
- [ ] `packages/hooks/src/use-permissions.ts` — **B** — `rg -n "usePermissions" apps packages` → one hit, the dead barrel — **delete (subsumed)**

#### (C) Verified live — strike off, do NOT delete — 12 items

- [ ] `apps/console/src/server/reports/render-charts.tsx` — **C** — knip false positive; it is the esbuild entry named at `apps/console/scripts/build-report-charts.mjs:29` — **keep; add to a knip config if we adopt one**
- [ ] `apps/authz-ui/src/sw.ts` — **C** — `vite.config.ts:46`, `vite-plugin-pwa` injectManifest — **keep**
- [ ] `apps/authz-ui/src/test/virtual-pwa-register-stub.ts` — **C** — `vitest.config.ts:30` resolve alias — **keep**
- [ ] `@fontsource/*` (console, lci, authz-ui, ui-web), `daisyui`, `@tailwindcss/postcss`, `postcss` — **C** — CSS-only, `packages/ui-web/src/styles.css:16-21` `@import` + daisy `@plugin` — **keep; removing the app-level copies is a pnpm-hoisting question, verify with a real build first**
- [ ] `axios`, `zod` (`packages/api-rest`), `decimal.js` (`packages/authz-rpc`) — **C** — consumed by gitignored generated code (`openapi-ts.config.ts:15` selects `@hey-api/client-axios`) — **keep**
- [ ] `@storybook/addon-a11y` (ui-web) — **C** — registered in `.storybook/main.ts` — **keep**
- [ ] `SpendSeriesChart` — **C** — ← `sections/spend-dashboard/component.tsx:105` ← `admin-overview-centre.tsx:150` + `settings-overview-centre.tsx:160` — **keep; the "chart with no renderer" flag was wrong**
- [ ] `ChartAxisBottom/Left`, `ChartLegend`, `ChartTooltip`, `DonutChart`, `ShareBar`, `MultiSeriesSpendBoard`, `LatencyStatCards`, `RailResizer`, `RefillPolicyStatusStrip`, `ScenarioForm` — **C** — each has a named production importer (`spend-series-chart:368`, `donut-chart:14`, `panel-renderers.tsx:112/226`, `console-shell:81`, `refill-policy-lookup:43`, `policy-simulator:55`) — **keep**
- [ ] `ReportExportPanel` / `ReportExportDialog` vs `DashboardExportButton` — **C** — not rivals, a composition chain: `dashboard-export-button.tsx:147` → `ReportExportDialog` → `report-export-dialog/component.tsx:33` → `ReportExportPanel`; `projects-centre.tsx:100` mounts the dialog directly too — **keep all three**
- [ ] `isAdmin` — **C** — verified gone; `apps/console/src/no-role-derived-gates.test.ts` is an AST-level guard that fails if it reappears — **nothing to do**
- [ ] `previousWindow` — **C** — verified gone; only an explanatory comment in `containers/comparison-window.ts:6` and ADR 0015 — **nothing to do**
- [ ] 197 of 472 `packages/ui-web/src/index.ts` barrel symbols have zero consumers (mostly `*Props` types) + ~150 surplus `export` keywords in `apps/console` on live module-local code — **C** — spot-checked ~20 by grep; the code is live, only the keyword is surplus — **owner call: trim the barrel to what is consumed, or accept it as public design-system API**

#### (D) Duplicated logic — 5 items

- [ ] `RANGE_LABELS` third copy at `apps/console/src/containers/admin-usage-centre.tsx:56` — **D** — canonical is `containers/overview-usage.ts:93`, re-exported by `overview-range.ts:31` and used by 8 containers + `server/reports/page-report.ts`; this hand-written copy is the survivor the C-series work did not collapse — **collapse onto the shared one**
- [ ] `LENS_TITLE` — **D** — `containers/use-settings-overview-zones.ts:60` and an independent copy at `packages/ui-web/src/pages-stories/settings-overview.stories.tsx:79` — **have the story import the app's map, or move the map into ui-web**
- [ ] `apps/lci/src/lib/auth/index.ts` barrel — **D** — `OidcClientConfig`, `oidcTokenUri`, `performRefreshGrant`, `RefreshGrantResult`, `CookieOptions`, `VerifyConfig` are re-exported but never consumed *through* the barrel — **drop the six re-export lines, or route the direct imports through the barrel; pick one**
- [ ] The `operation` vocabulary, frontend half — **D** — `apps/console/src/dashboards/panel-adapters.tsx:112` label map, `openapi/usage.backend.yaml:142` enum, and literals at `apps/console/dashboards.yaml:547,797,944,1035,1053,1076,1097,1118`. Three more copies live in lightbridge-authz (see ADORSYS-GIS/lightbridge-authz sibling ticket) — **one source, five consumers; needs a cross-repo decision on where it lives**
- [ ] `expandGrant` (`packages/hooks/src/rbac.ts:100`) vs Rust `expand_grant` (`lightbridge-authz-core/src/authz.rs:291`) — **D** — same wildcard-expansion rule, two languages; the TS side is dead — **resolved by accepting the `rbac.ts` item in B**

#### Gaps found in passing (not dead code)

- [ ] `/settings/overview/{account,project,user}` have **no nav entry anywhere** — `rg -n "href: '/settings" apps/console/src/client/console-chrome.tsx` lists only `/settings/{overview,accounts,tiers,policies,info}`; `/settings/overview/page.tsx:13` redirects to `…/usage`. The three lenses have full `dashboards.yaml` pages (lines 1471, 1599, 1729), page stories and route-gate tests, and are reachable **only by typing the URL** — **wire a sub-nav, or delete the three lenses**
- [ ] `packages/ui-web/src/section-class-audit.test.ts` pins **21 of 43** sections — **widen, or state the sample is deliberate**
- [ ] **The pattern gap is worse than the coverage gap**: `auditComponent` (`packages/ui-web/scripts/class-budget.ts:107`) filters `^(component\.tsx|cva\.ts|.*-classes\.ts)$`, so a section with differently-named files measures an **empty set** and reports "0 utilities, verified" while verifying nothing. `sections/dashboard-panels` is the one such directory today (its file is `panel-renderers.tsx`) — **widen the file pattern and re-baseline every section in one pass**

### Acceptance Criteria

- [ ] Given the checklist above, when the owner ticks the items to act on, then each ticked item becomes a scoped follow-up PR referencing this ticket.
- [ ] Every unticked item is annotated "keep, deliberately" in a comment so the next audit does not re-raise it.
- [ ] No item is deleted without `pnpm -r typecheck`, `pnpm -r test`, `pnpm --filter @lightbridge/ui-web build-storybook` and a real `pnpm --filter console build:web` passing on the deletion branch.
- [ ] The (C) list is closed as verified-live without any code change.
- [ ] Existing behavior is not broken.
- [ ] Verification evidence is provided on each follow-up PR.

### Out of Scope

- Any deletion. This ticket produces decisions, not diffs.
- The lightbridge-authz half of the sweep — that is its own ticket against ADORSYS-GIS/lightbridge-authz#645.
- Adopting `knip` as a CI gate. Worth considering, but it needs a checked-in config first (the audit used a throwaway one) or it will flag `render-charts.tsx`, `sw.ts` and the CSS-only font deps on every run.

### Technical Context

- Audited ref: `origin/main` @ `5418678`, clean worktree, `pnpm install` (postinstall codegen ran).
- Tools: `knip@5`, `ts-prune@0.10`, `depcheck@1`, plus per-symbol `rg` passes. knip needed a workspace config to cover the pnpm layout and `vite: false` on `apps/{authz-ui,governance-auth}` (its Vite plugin fails to load their `vite.config.ts` — `Cannot find module '@fontsource/inter/latin-400.css'`).
- Tool disagreement worth knowing: on `packages/ui-web`, knip reports zero unused files **whether or not stories count as entries**, because the `./src/*` export map plus the console's deep imports make almost everything reachable. Every (B) finding came from a per-symbol grep, not from knip. ts-prune is dominated by barrel false positives — its only unique true positive was `RAIL_ACTIVE_BAR_WIDTH`.

### Risks

- **Deleting `packages/hooks`' unreachable half is the largest single change** and touches a package three others declare as a dependency. Mitigation: the two live subpaths (`/api-error`, `/budget-tiers`) are pure TS with no React/Expo imports, so the RN/Expo peer dependencies go with the deletion; verify with a real console build, not just `tsc`.
- **`@fontsource/*` and `daisyui` look unused to both tools but are CSS-only.** Removing them on tool output alone would break the build. They are classified (C) for exactly this reason.
- **`export` keyword removal (C, last item) is mechanical but wide.** It touches ~150 lines across `apps/console`; a bad automated pass could remove an export a test actually uses. Do it with `tsc` in the loop, not sed.

### Test Plan

Per follow-up PR, on the deletion branch:

```
pnpm install
pnpm -r typecheck
pnpm -r test
pnpm --filter @lightbridge/ui-web build-storybook # if stories were touched
pnpm --filter console build:web # the real Next build, always
pnpm lint
```

Expected: all green, and the deleted symbol appears in no build output.

### Verification evidence

Audit run, `origin/main` @ `5418678`:

- `npx -y knip@5 --include files,exports,types,dependencies` → 4 unused files, 12 unused deps, 6 unused devDeps, 61 unused exports, 115 unused exported types.
- `npx -y knip@5 --include files` with stories excluded from `packages/ui-web` → same 4 unused files; no ui-web file becomes unreachable.
- `npx -y depcheck@1` on console/hooks/ui-web → agrees with knip on every finding except `@tailwindcss/postcss`/`postcss` (used by `postcss.config.js`).
- `npx -y ts-prune@0.10 -p apps/console/tsconfig.json` → 156 lines; one unique true positive (`RAIL_ACTIVE_BAR_WIDTH`), the rest barrel noise.
- Per-symbol `rg -n -w` passes over `apps` + `packages` for every item listed, with the hit counts quoted inline above.

Known remaining limitation: **this is a static audit.** It cannot see a symbol reached only through a string-keyed registry or a runtime `import()`. `dashboards.yaml`'s panel `type` strings were checked by hand against `panel-renderers.tsx`'s registry; nothing else in the tree uses that pattern.

### Human accountable owner

@stephane-segning

### AI Usage Declaration

Understanding code, Drafting the ticket

### Human verification completed

- [x] I understood the intent
- [x] I checked the source of truth
- [x] I reviewed all AI-generated text/code
- [x] I verified the implementation manually
- [x] I checked for hallucinated assumptions
- [x] I documented remaining risks
- [x] I am the accountable owner and accept responsibility for this ticket.

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.