Admin Cockpit · Surface walkthrough

Shell: Routing and layouts

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

unspecified
11sections3 minread1table

On this page

Source: apps/oshun/admin/src/middleware.ts, apps/oshun/admin/src/app/error.tsx, apps/oshun/admin/src/app/loading.tsx, apps/oshun/admin/src/app/not-found.tsx, apps/oshun/admin/src/lib/session-cookie.ts

How the admin app handles routes, public paths, rate limiting, and the request-id stamp that flows from middleware into every page and audit entry.

Middleware composition#

apps/oshun/admin/src/middleware.ts runs on every request matched by:

text
/((?!_next/static|_next/image|favicon\.ico|.*\.(?:svg|png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|eot)$).*)

Order of operations:

  1. Generate a requestId (timestamp + random suffix)
  2. Resolve client IP (x-forwarded-for first hop, then x-real-ip, fallback 127.0.0.1)
  3. Rate-limit check (production only): 120 requests / 60 s window / IP
  4. Public-path check
  5. Session-cookie check (for non-public paths)
  6. Forward request with x-request-id header; attach X-Request-Id to response

Public paths#

ts
const PUBLIC_PATHS = new Set<string>(['/unauthorized', '/handoff']);
const PUBLIC_PREFIXES = ['/_next', '/api', '/icons', '/images', '/favicon'];
  • /unauthorized — auth-denial UI; takes reason and returnTo query params
  • /handoff — privileged handoff from consumer to admin session
  • /_next/*, /api/*, /icons/*, /images/*, /favicon* — never auth-gated

Any other path requires OSHUN_ADMIN_SESSION_COOKIE_NAME cookie that parses cleanly via parseAdminSessionToken. Missing or invalid → redirect to /unauthorized?reason=<missing-session|invalid-session>&returnTo=<original>; invalid token also cookies.delete(OSHUN_ADMIN_SESSION_COOKIE_NAME) on the response.

Rate limiting#

In-memory rateLimitMap keyed by IP.

  • Threshold — 120 requests per 60 s
  • Local dev exemptionprocess.env.NODE_ENV !== 'production' || hostname === 'localhost' || hostname === '127.0.0.1'
  • Response when limited429 Too Many Requests with Retry-After: 60 and X-Request-Id header
  • Window reset — first request after resetAt starts new window

In-memory store note: rate-limit state is per-instance. In multi-replica deploys, this is local to the replica. Open question worth flagging in ops.

Request ID#

Every request gets req_<timestamp>_<random8>. The ID flows three places:

  • Stamped on the response (X-Request-Id header)
  • Forwarded to the page via x-request-id request header (read with headers() in server components — see handoff/page.tsx line: hdrs.get('x-request-id'))
  • Logged (verify telemetry pipeline)

Used for log correlation, audit trail joining, and on-screen support references.

Route groups#

The admin app does not use Next.js route groups — every segment is a real URL segment.

Catch-all routes#

None. Every route is explicit. Unknown paths → not-found.tsx (default Next 404 behavior).

Special files#

  • app/error.tsx — segment-level error boundary; 'use client'; shows heading "Something broke inside the admin shell", body with error.digest, "Retry workspace" button calls reset()
  • app/loading.tsx — global loading; <main role="main"> with aria-live="polite" "Loading operations cockpit…"; no skeleton
  • app/not-found.tsx — workspace-not-found UI; h1 "Workspace not found"; link back to /; metadata.title = 'Workspace not found'
  • No app/global-error.tsxerror.tsx is the only error UI

Sub-route patterns#

Some routes have a single child:

Parent Child(ren)
/review /review/[reviewId]
/trust-safety /trust-safety/voice-abuse
/isis /isis/civitai-intake, /isis/comfy-nodes, /isis/lora-training, /isis/model-merging, /isis/output-gallery, /isis/runpod-endpoints, /isis/voice-cloning, /isis/workflow-editor
/messaging /messaging/telegram-channels
/tenant-console /tenant-console/living-scenes
/__test /__test/v1-aweb-104

No parent index pages for /isis, /messaging, /tenant-console, /__test — only the named children. Direct visits to those parents hit not-found.tsx.

States#

  • Anonymous on a gated path — middleware redirects to /unauthorized?reason=missing-session&returnTo=<path>
  • Invalid session token — middleware deletes cookie and redirects to /unauthorized?reason=invalid-session&returnTo=<path>
  • Rate limited — 429 page with Retry-After: 60 and the request ID
  • Valid session — request continues to the page; x-request-id header propagates
  • Public path (/unauthorized, /handoff) — no session check; page renders for anyone (with its own internal logic re: customer session for /handoff)
  • 404 on unknown routenot-found.tsx; preserves admin shell chrome? No — global not-found.tsx; verify visually
  • Error in pageerror.tsx catches; "Retry workspace" button

Cross-references#

  • 01-app-shell.md — AdminShell mounts inside each page after middleware passes
  • 03-auth-session.md — the session cookie this middleware validates
  • Session cookie module: apps/oshun/admin/src/lib/session-cookie.ts

Open questions / known gaps#

  • Document the exact format of admin session tokens (the parseAdminSessionToken return shape lives in lib/session-cookie.ts)
  • Confirm rate-limit storage strategy in production — in-memory per-replica is a known limitation
  • Verify not-found.tsx doesn't leak the admin shell to unauthenticated visitors (it's not in PUBLIC_PATHS, so middleware should bounce them first)
  • Document the x-request-id propagation — which BFF calls forward it for audit-trail joining?