Admin Cockpit · Surface walkthrough

Shell: Auth and session

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

unspecified
9sections4 minread2tables

On this page

Source: apps/oshun/admin/src/lib/session-cookie.ts, apps/oshun/admin/src/lib/server-session.ts, apps/oshun/admin/src/lib/customer-session.ts, apps/oshun/admin/src/app/handoff/page.tsx, apps/oshun/admin/src/app/handoff/HandoffLauncher.tsx, apps/oshun/admin/src/app/unauthorized/page.tsx, libs/oshun/navigation/src/admin-ia.ts (OSHUN_ADMIN_WORKSPACE_MODEL.requiredScopes, canEnterAdminWorkspace)

How an operator becomes an operator — the privileged handoff, the session cookie, the scopes, and the unauthorized fallback.

Three cookies you need to know#

Cookie Owner Purpose
OSHUN_ADMIN_SESSION_COOKIE_NAME (admin) Admin Gates every non-public admin path via middleware
OSHUN_CONSUMER_SESSION_COOKIE_NAME (consumer) V1 PWA Customer session; admin's /handoff reads it to know whether to offer a privileged-handoff prompt

The admin and consumer cookies are scoped separately. A customer session alone does NOT confer admin access — explicit privileged handoff is required.

Auth states#

  • anonymous — no cookies; gated paths bounce to /unauthorized
  • customer-only — only the consumer cookie; visiting an admin path bounces to /unauthorized?reason=missing-session; visiting /handoff offers the privileged-handoff flow
  • admin (valid) — admin cookie parses cleanly; can access any path their scopes allow
  • admin (invalid) — admin cookie present but parseAdminSessionToken returns null; middleware deletes the cookie and bounces to /unauthorized?reason=invalid-session
  • admin + insufficient scope for workspace — middleware lets the request through (it only checks for any valid admin session), but the page's WorkspaceEntryPoint renders an "Access not granted" panel and the BFF returns accessible: false

Sign-in flow: privileged handoff#

apps/oshun/admin/src/app/handoff/page.tsx

  • Visit /handoff — public path (no admin session required)
  • Has admin session alreadyparseAdminSessionToken(adminToken) returns valid; redirect to returnTo ?? '/'
  • No admin session — render <HandoffLauncher> with:
    • Eyebrow: "Oshun · Operations"
    • Heading: "Privileged handoff"
    • Body: explanation that admin cockpit is entered through explicit privileged handoff from consumer
    • hasCustomerSession flag (from OSHUN_CONSUMER_SESSION_COOKIE_NAME presence)
    • requestId (from x-request-id header) for support reference
  • returnTo query param — sanitized via sanitizeReturnTo (verify the rules — likely path-only, no protocol/host)
  • reason query param — surfaced for the operator to see why they hit handoff

The handoff itself is an out-of-band action (likely a back-channel admin login or a one-time link). The page describes the flow but the admin cookie is set by a separate endpoint (verify which).

Sign-out#

The admin app does not have a dedicated sign-out route in apps/oshun/admin/src/app. Sign-out is presumably handled by:

  • Deleting OSHUN_ADMIN_SESSION_COOKIE_NAME via an API route (verify apps/oshun/admin/src/app/api/admin/*)
  • OR a header action wired through the studio governance flow

Open question: where does the operator sign out from? Flag in matrix.

Session refresh#

The admin cookie is parsed on every request via parseAdminSessionToken. No refresh path is visible in session-cookie.ts — token rotation likely happens out-of-band on each privileged handoff. Open question: does the token expire?

Scopes and workspace access#

Each workspace declares requiredScopes in OSHUN_ADMIN_WORKSPACE_MODEL. Examples:

  • dashboard['admin:*', 'admin:studio']
  • inbox['admin:*', 'admin:studio']
  • review['admin:*', 'admin:studio', 'admin:workspace:review']
  • trust-safety['admin:*', 'admin:studio', 'admin:workspace:moderation']
  • incidents['admin:*', 'admin:studio', 'admin:workspace:incident']
  • personas['admin:*', 'admin:studio', 'admin:workspace:persona']
  • models['admin:*', 'admin:studio', 'admin:workspace:model']
  • editorial['admin:*', 'admin:studio', 'admin:workspace:editorial']
  • research-integrity['admin:*', 'admin:studio', 'admin:workspace:research-integrity']
  • rights['admin:*', 'admin:studio', 'admin:workspace:rights']
  • support['admin:*', 'admin:studio', 'admin:workspace:support']
  • privacy['admin:*', 'admin:studio', 'admin:workspace:privacy']
  • policy['admin:*', 'admin:studio', 'admin:workspace:policy']
  • lilith['admin:*', 'admin:studio', 'admin:workspace:lilith']

admin:* is the superuser scope; admin:studio is the broad studio-operator scope; workspace-specific scopes (admin:workspace:*) allow finer-grained delegation. canEnterAdminWorkspace(scopes, workspaceId) returns true if any of the workspace's requiredScopes is present.

Scopes test matrix#

Operator scopes Can enter dashboard Can enter review Can enter trust-safety
['admin:*']
['admin:studio']
['admin:workspace:review']
['admin:workspace:moderation']
['admin:workspace:review', 'admin:workspace:moderation']
[]

The above is derived from how the requiredScopes arrays are written — verify with the canonical canEnterAdminWorkspace test suite at libs/oshun/navigation/src/admin-ia.test.ts.

Unauthorized page (/unauthorized)#

apps/oshun/admin/src/app/unauthorized/page.tsx

Three known reasons (from REASON_COPY):

  • missing-session — "Admin session required" heading; body tells operator to use privileged handoff and that customer sessions cannot enter admin routes
  • invalid-session — "Admin session expired or invalid" heading; body tells operator to request a new privileged handoff
  • forbidden-workspace — "Workspace access denied" heading; body tells operator their role doesn't grant the workspace scope

returnTo query param is preserved so the operator can resume after handoff.

Cross-references#

Open questions / known gaps#

  • Document the upstream service that issues the admin session token after privileged handoff
  • Confirm token expiry / refresh policy
  • Locate the sign-out path (likely an /api/admin/* route)
  • Verify sanitizeReturnTo rules in handoff/page.tsx
  • Document how forbidden-workspace is triggered — middleware doesn't check scope, so this reason originates from a page or BFF