feat(portal): M10.1 — fill the 10 customer-area shells #12
Reference in New Issue
Block a user
Delete Branch "feat/m10.1-real-shells"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Fills the 10 M5.2 shells. Four surfaces (
settings,settings/api-keys,audit,products) are backed by live tenant-registry data and let the IT_ADMIN do useful work today. Five (projects,settings/users,settings/integrations,billing,support) keep the empty-state shape but pick up richer copy + per-surface CTAs (e.g., billing links to catalog).Highlights
details+ctaslots so the five remaining empty pages don't all look identical.Why
After M5.2 + M11.1 + M12.1, the portal had a working catalog + signup but the rest of the sidebar pointed at empty shells. M10.1 closes that gap: an IT_ADMIN can sign in, see who they are, manage API keys for their tenant, audit everything, and see what products are active. That's the minimum 'this product is real' surface.
Linked milestone: M10.1 (settings editing is the only deferred bit; everything else is shipped).
How
<form action={asyncFn}>, redirect with?ok=/?err=flash.method=GETso the URL is bookmarkable.?plaintext=…). Not perfect — it ends up in browser history. Acceptable for dev; M10.1 follow-up moves it to a server-stashed flash cookie when we add real session-flash plumbing.formatRelative,formatDateTime,truncate) consolidated insrc/lib/format.tsso we don't reinvent date strings per page.Test plan
pnpm lint/typecheck/test(56 cases, 100%src/libline+branch+function) /build— all greenRisk
Checklist
canSee()+ parent layout slug matchFour real surfaces backed by live tenant-registry data: /[slug]/settings read-only tenant identity + plan + status + lifecycle dates with badge for status /[slug]/settings/api-keys full CRUD: list active + revoked keys, create form, plaintext-shown-once banner, revoke action /[slug]/audit paginated table with cursor-based next-page navigation, action+actor_id GET filters, formatRelative timestamps, metadata preview /[slug]/products live entitlements (filtered to enabled), trial expiry chip, links to catalog when empty Five remaining surfaces upgraded to milestone-aware empty states (projects / users / integrations / billing / support) with CTAs where useful — billing links to catalog, support points at oncall@. ShellEmpty component grew a 'details' string and a 'cta' ReactNode slot so the empty pages don't all look identical. Library additions: src/lib/format.ts formatRelative, formatDateTime, truncate src/lib/tenant-registry fetchAPIKeys, createAPIKey, revokeAPIKey, fetchAudit — typed result shapes so server actions can branch cleanly Tests: src/lib/format.test.ts 12 cases, 100% coverage src/lib/tenant-registry.test +14 cases for new client methods, 100% line+branch+function tests/e2e/surfaces.spec.ts one canary per of 10 customer-area routes (signed-out → 403) CI all green: lint / typecheck / test / build. Refs: M10.1