Skip to content

Latest commit

 

History

History
80 lines (56 loc) · 6.39 KB

File metadata and controls

80 lines (56 loc) · 6.39 KB

Frontend Standards & Consistency Backlog

Status: active

Generated by the platform frontend-parity sweep (2026-06-03). Prioritized remediation backlog for frontend/src (core) and extensions/system/frontend/src (system extension). tsc --noEmit baseline at audit time = 0 errors — this is the hard gate after every batch.

Canonical helpers (reuse — do NOT introduce new ones)

Concern Canonical Location
Permission check usePermissions().hasPermission / currentUser?.permissions?.includes() shared/hooks/usePermissions.ts, shared/utils/permissionUtils.ts
Notifications (192 uses) useNotifications().addNotification({type,title,message}) shared/hooks/useNotifications.ts
Form submit + toasts + field errors useFormSubmission shared/hooks/useFormSubmission.ts
Service base (34 extend it) BaseApiService shared/services/ai/BaseApiService.ts
Page shell PageContainer shared/components/layout/PageContainer.tsx
Tabs (canonical = path-based) per-tab URL segment + nested <Routes> + <Link> frontend/src/pages/app/admin/AdminSettingsPage.tsx, extensions/system/frontend/src/pages/app/system/ComputePage.tsx
Theme classes color tokens in assets/styles/tailwind-theme.css; bg-/text-/border-/ring-theme-<token> generated by Tailwind proven focus ring: focus:ring-theme-interactive-primary

Theme-class safety (load-bearing)

Plausible-looking theme classes that lack a defining token compile to nothing (prior 91-file white-on-white incident). Verified canonical tokens include: surface, surface-hover, surface-selected, background-secondary, primary, secondary, tertiary, success, warning, error, danger, info, link, interactive-primary, interactive-secondary, focus. Never use bg-theme-secondary (→bg-theme-surface), *-bg suffixes, or any token not present in the stylesheet/shipped components.


P0 — Hard-rule items

Role-based access → VERIFICATION PASS (not a rewrite)

The access layer is already 100% permission-based (permissionUtils.hasAdminAccess etc. delegate to hasPermission). The 9 originally-flagged sites are legitimate display/stat/list-filter usage of role names, not access gating:

  • features/account/components/TeamMembersManagement.tsx:137 (admin stat count) — real gate at :22 is permission-based.
  • features/admin/components/users/SystemUserManagement.tsx:165,231 (role list-filter + stat).
  • pages/app/account/UsersPage.tsx:143, pages/app/admin/WorkersPage.tsx:192 (role list-filters).
  • pages/app/admin/AdminSettingsOverviewPage.tsx:543 (role badge display).
  • RoleUsersModal, WorkerFilters, CreateWorkerModal, WorkerEditForm — roles as domain data (assign/filter workers).

Action: confirm no hidden role-gated access path; document; do not rewrite.

Hardcoded colors → theme classes (~20 real)

  • pages/app/ai/AgentMarketplacePage.tsx — 8× focus:ring-blue-500focus:ring-theme-interactive-primary (proven canonical).
  • Sweep ~12 remaining offenders in features/ + pages/.
  • Exclude: pages/public/WelcomePage.tsx (intentional marketing gradient), var(--theme-*, #hex) fallbacks, test files.

P1 — High priority

Service-layer any → typed (~20)

Define response-envelope interfaces per endpoint, export for reuse. No runtime change.

  • features/admin/storage/services/storageApi.ts (6 envelope generics)
  • features/admin/audit-logs/services/auditLogsApi.ts (3: Promise<any[]>, Promise<any>, data?:any)
  • features/ai/knowledge-graph/api/knowledgeGraphApi.ts (2)
  • features/admin/services/adminSettingsApi.ts (2)

Real bugs (fix test-first)

  • features/developer/components/ApiKeyManager.tsxapi.get('/api/v1/api_keys') double-prefixes to /api/v1/api/v1/api_keys (404). Fix: consolidate onto features/devops/api-keys/services/apiKeysApi.ts.
  • features/ai/debugging/components/TraceList.tsx — raw fetch('/api/v1/ai/execution_traces') bypasses auth/refresh. Fix: new features/ai/debugging/services/executionTracesApi.ts extending BaseApiService.

Local error/success state → global notifications (core ~91 + system 64)

Rubric — MOVE to global (addNotification): success toasts; page-level/submit failure banners; errors far from their input. KEEP local: inline field validation; empty/zero states; loading. Prefer migrating form submits onto useFormSubmission (does global toast + local field errors). Batch by feature. Start: governance/SpendDashboard, ai/provisioning/*.


P2 — Consistency

Service consolidation (~25–38 direct apiClient/fetch in components)

Extract into feature services extending BaseApiService. Priority: ai/provisioning/* (→ one provisioningApi), governance/SpendDashboard, onboarding/*. Often combine with the notification batch for the same feature.

Tab-component standardization

Two competing implementations: layout/TabContainer (state-based) vs the canonical path-based pattern (per-tab URL). TabNavigation/BreadcrumbAwareTabNavigation have near-zero importers. Decision: path-based tabs are canonical (deep-linkable; matches platform convention + dated user correction). @deprecated-tag ui/TabContainer, TabNavigation, BreadcrumbAwareTabNavigation; delete once importer count hits zero.

Progress (AI IA refactor): FinOpsPage, CreditsContent, and OutcomeBillingContent migrated state→path tabs; AIMonitoringPage (TabContainer) split into ObservabilityPage + OperationsPage on PathTabs. New canonical vertical sub-nav primitive shared/components/navigation/SubNavRail.tsx (path-based, permission-gated) for deep hubs — first consumer: CostPage. Remaining TabContainer importers should migrate next.


System extension (extensions/system/frontend) — already clean

0 hardcoded colors, 0 any, 0 role-gates, canonical useNotifications (72 files). Only work: the 64 local-state→notification rubric pass (P1) and the GitOps/CVE gap fills (see parity matrix). The 7 hubs already use the canonical path-based tab pattern.

Sequencing

  1. P1 typing → P0 colors → P0 role verification → P1 bug fixes → wire-ups (Cost/Developer) → system GitOps/CVE → P1 notifications (batched) → P2 service consolidation → P2 tab standardization.
  2. tsc --noEmit = 0 after every batch; targeted jest; eslint on changed files.

Last verified: 2026-06-04