Admin Cockpit · Surface walkthrough

Meta · Access not granted

A per-surface walkthrough of the Admin Cockpit admin surface: layout, states, interactions, data, and cross-references.

drafted
8sections3 minread

On this page

Context. surface admin · domain meta · route /unauthorized · auth anon (public path) · source apps/oshun/admin/src/app/unauthorized/page.tsx

Last walked.

Purpose#

Auth-denial UI for the admin app. Reason-based copy from the internal REASON_COPY table; surfaces the attempted returnTo path so the operator can resume after handoff. Always renders the same lightweight card with no shell chrome.

Entry points#

  • Middleware bounce — apps/oshun/admin/src/middleware.ts redirects here when a non-public path is hit without a valid admin session (shell/02-routing-layouts.md). Reasons:
    • missing-session (no OSHUN_ADMIN_SESSION_COOKIE_NAME)
    • invalid-session (parseAdminSessionToken returned null — cookie also deleted on the response)
  • Page-level / BFF redirect — forbidden-workspace reason can be surfaced when a page (or downstream) detects an operator with a valid session but missing workspace scope. Middleware itself does not check scope today, so this is dispatched by individual pages or by HandoffLauncher flows
  • Direct URL — PUBLIC_PATHS includes /unauthorized; no session required

Layout regions#

This page does NOT render AdminShell. Renders a plain <main role="main" className={styles.page}>:

  • Card (section.styles.card):
    • Eyebrow — "Oshun · Operations"
    • Heading — h1 from REASON_COPY[reasonKey].heading
    • Body<p> from REASON_COPY[reasonKey].body
    • Attempted path — when returnTo is non-null and validates via sanitizeReturnTo, renders <p>Attempted path: <code> {returnTo}</code></p>
    • Action link<Link href="/">Return to handoff entry</Link> (anchors to admin root, which middleware will re-bounce to /handoff if there's no admin session)

States#

The reasonKey selection runs before render:

  • searchParams.reason matches a REASON_COPY key (missing-session / invalid-session / forbidden-workspace) → that copy renders
  • searchParams.reason absent or unrecognized → defaults to missing-session
  • returnTo query missing → "Attempted path" line omitted
  • returnTo query starts with / but not // → "Attempted path: " renders
  • returnTo query starts with // or doesn't start with /sanitizeReturnTo returns null; line omitted
  • Reason copy variants (from page source):
    • missing-session — h1 "Admin session required"; body explains privileged-handoff requirement and that customer sessions cannot enter admin routes
    • invalid-session — h1 "Admin session expired or invalid"; body explains token verification failure and recommends requesting a new privileged handoff
    • forbidden-workspace — h1 "Workspace access denied"; body explains the operator's admin role does not grant the workspace scope and to contact a studio operator

Interactions#

  • "Return to handoff entry" (link — primary)
    • Function: navigates to / (admin root). Anonymous operators hit middleware, get bounced to /handoff (the privileged- handoff entry). Operators with a valid admin session will land on the dashboard.
    • Tab order: the only focusable control on the page

The page exposes no buttons or forms.

Data & contracts#

  • Reads:
    • searchParams (Promise) — reason, returnTo
    • REASON_COPY — module-local constant mapping missing-session / invalid-session / forbidden-workspace to { heading, body }
  • Writes: None.
  • Realtime: None.
  • Auth/role check: NO middleware session check — /unauthorized is in PUBLIC_PATHS

Cross-references#

  • Shell: shell/02-routing-layouts.md (middleware redirect logic), shell/03-auth-session.md (the three reasons documented there match REASON_COPY exactly)
  • Sibling meta route: handoff.md (the page operators land on after clicking the action link, when no admin session is present)

Open questions / known gaps#

  • forbidden-workspace reason: middleware does NOT check workspace scope; this reason is presumably dispatched by a page-level check or by the BFF /api/admin/signin flow. Locate the actual dispatcher
  • No "Sign in differently" or "Switch operator" affordance — verify whether a future state should expose operator switching from here
  • Action link points to / not /handoff; this is intentional (it lets the middleware bounce back to /handoff for anonymous traffic) but it adds an extra redirect hop