Skip to content

feat(admin): admin app foundation#1967

Merged
cdcore09 merged 31 commits into
cdcore09/site-redesignfrom
cdcore09/admin-foundation
May 11, 2026
Merged

feat(admin): admin app foundation#1967
cdcore09 merged 31 commits into
cdcore09/site-redesignfrom
cdcore09/admin-foundation

Conversation

@cdcore09
Copy link
Copy Markdown
Contributor

Closes #1956.

Spec: docs/superpowers/specs/2026-05-09-admin-app-foundation-design.md
Plan: docs/superpowers/plans/2026-05-09-admin-app-foundation.md

Summary

Establishes the admin-app foundation — workspace, auth posture, role/permission model, audit infrastructure, and frontend shell — so the ten subsystem specs queued behind it (members, vocab, organizations, groups, events, recognition, forms, elections, communications, operations) can land on a stable target.

Schema

  • New staff value on user_role enum (migration 0012); legacy admin backfilled and kept for one rev.

Backend (packages/api)

  • lib/policies/ — five pure-function policies (canEnterAdminApp, canApproveVocab, canMergeUsers, canEditGroup, canEditEvent, canViewAuditLog) + 19 Vitest tests.
  • middleware/actorContext.ts — walks user merge chain, loads leadership terms + chair memberships, populates c.var.actor.
  • middleware/policy.tsrequirePolicy factory.
  • middleware/audit.ts — afterware that writes one audit_log row per mutating admin request.
  • routes/admin/ — Hono sub-app mounted at /api/admin/* with requireAuth → requireActorContext → auditMiddleware. Endpoints: /me, cursor-paginated /audit.
  • routes/webhooks.tshandleUserCreated now links legacy CSV rows by email on first WorkOS sign-in (previously silently failed on email unique-constraint).

Frontend

  • New packages/auth-shell package — extracts WorkOS AuthShell, RootErrorBoundary, useApi from apps/web so both SPAs share one identity surface.
  • New apps/admin SPA — Vite + React 19 + Router 7 + Tailwind, design-system tokens fully wired.
  • Auto-redirects to WorkOS on first tab visit (silent SSO if a session exists elsewhere); manual sign-in fallback if cancelled.
  • Adaptive sidebar — three grouped bands (Dashboard / Curation / System) keyed off the actor's positions; group/event chairs see only their scoped items.
  • Dashboard tiles + cursor-paginated audit page; six stub pages with branded "in progress" treatment for the future subsystems.
  • "Admin portal" link in the public site's user dropdown, gated on users.role and environment-aware (localhost:5174 in dev, admin.us-rse.org in prod, VITE_ADMIN_URL override).

Infra

  • .github/workflows/deploy-admin.yml for the new Pages project.
  • .github/workflows/deploy.yml triggers extended to include this branch.
  • Root npm scripts: dev:web, dev:admin, dev:api.
  • Playwright smoke for the unauthenticated SPA.

Test plan

  • Sign into usrse.org (or the relevant preview) — user dropdown shows "Admin portal" when role is staff or super_admin, hidden otherwise.
  • Click the link → lands on the admin app, signed in already (silent SSO).
  • Adaptive sidebar shows the right items for your tier.
  • /admin/audit loads recent rows (super_admin only).
  • Sign out from the admin app — next visit auto-redirects through WorkOS again.
  • Dashboard tiles render without errors for staff and super_admin tiers.
  • Coming-soon pages render the branded "in progress" pill.

Out of scope (deferred, tracked by separate issues)

Manual ops still required

  • Cloudflare Pages project us-rse-admin is provisioned and serves admin.us-rse.org.
  • WorkOS redirect URIs include the admin domain + preview + localhost variants.
  • VITE_WORKOS_CLIENT_ID set as a Production + Preview env var on the admin Pages project.

cdcore09 and others added 30 commits May 9, 2026 06:49
Sixteen tasks plus pre-flight and wrap, covering migration 0012,
the auth-shell package extraction, policies + middleware, the
admin sub-app, the apps/admin scaffold, the adaptive shell,
dashboard, audit reader, CI lane, manual ops, and a Playwright
smoke. Each task is bite-sized with exact file paths, complete
code, expected output, and a commit step. Tracks GitHub #1956.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves AuthKitProvider mount, RootErrorBoundary, and useApi hook into
@us-rse/auth-shell so both the web SPA and the upcoming admin app can
share them without diverging. apps/web shims become thin re-exports.
Walks the WorkOS→canonical-user merge chain (depth 5), hydrates
leadership terms (joined to leadership_positions for positionType/label),
chaired groups, and chaired events in one parallel DB round-trip, then
gates entry on canEnterAdminApp and stashes ActorContext on c.var.actor.

Also extends Variables in types.ts with the optional actor field.
Adds requirePolicy middleware factory, the /api/admin Hono sub-app
(auth → actorContext in order), and GET /api/admin/me so the SPA
can bootstrap actor context on load.
Adds GET /api/admin/audit endpoint gated to super_admin (systemTier >= 2).
Supports filtering by actorId, action substring, targetType, targetId,
and a created_at date range. Cursor encodes createdAt|id for stable
keyset pagination across millisecond-level ties. Limit capped at 200.
Vite + React + Tailwind app on port 5174 with AuthShell provider,
project-reference TS configs, and Cloudflare Pages _redirects.
Wire auth callback, useActorContext polling /admin/me every 60s,
frontend policy mirror, NotEntitled gate, and App routing so the
shell knows who the actor is before rendering nav items.
Adds AdminShell layout wrapper with role-gated Sidebar nav, TopBar
with sign-out, useNavSections hook, and stub routes for all sections.
App.tsx now renders the shell instead of the debug gate.
Replaces the corner-of-the-page Sign-in placeholder with a centered,
branded landing surface that matches the public site palette and gives
the admin app a real first impression. Loading/pending/error states
now share the same shell so the boot sequence reads as one continuous
surface.
Calls signIn() on mount the first time per tab so an admin who is
already signed in elsewhere (usrse.org, another browser tab) lands
straight in the admin app — WorkOS silently SSOs them via its session
cookie and our callback runs without a button press.

Keeps the styled manual sign-in card as a fallback for the rare case
where they came back unauthenticated (cancelled the WorkOS prompt or
their session is invalid), so there's always an escape route.

Sign-out paths (TopBar, NotEntitled) clear the per-tab attempt flag
so the next visit gets the auto-redirect experience again instead of
being stuck on the manual card.
Copy the full Tailwind @theme block, keyframes, base layer, and custom
utilities from apps/web into apps/admin, keeping the design-system
tokens import and dropping MapLibre overrides. Replace Stub with a
ComingSoon editorial component, refine TopBar/Sidebar/AdminShell chrome,
bump SignInPage wordmark weight, replace NotEntitled inline styles with
Tailwind classes, and standardize all purple accent bars to purple-500.
@cdcore09 cdcore09 merged commit 0849344 into cdcore09/site-redesign May 11, 2026
3 of 4 checks passed
@cdcore09 cdcore09 deleted the cdcore09/admin-foundation branch May 11, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant