Admin Cockpit · Journey

Journey: Privileged admin handoff

A source-reconciled journey record for Admin Cockpit — shipped behavior, state boundaries, failure modes, and the automation evidence available today.

automated · 1 spec
9sections7 minread1table

On this page
Journey at a glance
ActorsEligible operatorIneligible customerExpired admin operatorAnonymous visitor
Automation1 E2E spec(s)

Journey flow#

Generated from the authored steps below — click a node to jump to that section.

flowchart TD s1["1. Enter a protected route without an admin s…"] s2["2. Open the public handoff page"] s3["3. Request elevation"] s4["4. Resolve operator eligibility"] s5["5. Set the separate admin cookie"] s6["6. Return to a safe local path"] s7["7. Enter and use the Admin shell"] s8["8. Keep the rate limiter accurately bounded"] s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 click s1 href "#1-enter-a-protected-route-without-an-admin-session" click s2 href "#2-open-the-public-handoff-page" click s3 href "#3-request-elevation" click s4 href "#4-resolve-operator-eligibility" click s5 href "#5-set-the-separate-admin-cookie" click s6 href "#6-return-to-a-safe-local-path" click s7 href "#7-enter-and-use-the-admin-shell" click s8 href "#8-keep-the-rate-limiter-accurately-bounded"

The admin entry is a real, explicit privilege exchange. A protected route sends an unauthenticated browser to /unauthorized; the public /handoff page detects the customer cookie; the Admin API forwards that token to the BFF; and an eligible operator receives a separate scoped admin cookie before returning to a safe local path. The browser and route tests cover the chain in layers rather than one customer-cookie click-through E2E.

Boundary Responsibility
Admin middleware Request id, production rate limit, admin-cookie shape/expiry, protected-route redirect
/handoff + launcher Customer-cookie presence, explicit request, status and redirect
POST /api/admin/signin Forward customer token, sanitize return path, set admin cookie
BFF session route Authenticate customer, resolve operator eligibility/scopes, mint admin token
Proxied Admin BFF requests Authoritative token signature and scope verification

Personas#

  • Eligible operator — has a customer session and a BFF operator record with admin workspace scopes.
  • Ineligible customer — is authenticated as a customer but has no operator record.
  • Expired admin operator — has a malformed or expired admin cookie and must exchange again.
  • Anonymous visitor — has neither cookie and receives sign-in guidance without an elevation button.

Pre-conditions#

  • The customer shell has issued the oshun-session cookie, or a trusted caller supplies x-oshun-customer-token to the Admin signin route.
  • The BFF session handoff route is reachable.
  • Eligible users have a seeded or production operator record with roles, scopes, home workspace, and session TTL.
  • /handoff and /unauthorized are public Admin paths; workspace paths are protected.

Steps#

flowchart LR A[Protected route] -->|no admin cookie| B[Unauthorized] B --> C[Open /handoff] C -->|customer cookie present| D[Request admin handoff] D --> E[Admin signin route] E -->|Bearer customer token| F[BFF eligibility] F -->|scoped admin token| G[HttpOnly admin cookie] G --> H[Safe local returnTo] F -->|401 or 403| I[Visible handoff error]

1. Enter a protected route without an admin session#

  • Middleware generates an X-Request-Id.
  • A missing cookie redirects to /unauthorized?reason=missing-session&returnTo=<path>.
  • A malformed or expired cookie redirects with reason=invalid-session and is deleted on the redirect response.
  • The unauthorized page displays the attempted safe local path.
  • Its current Return to handoff entry link points to /, not directly to /handoff; without a cookie that protected root can redirect back to unauthorized.

2. Open the public handoff page#

  • /handoff reads both cookie namespaces without treating the customer cookie as an admin session.
  • A valid existing admin cookie immediately redirects to the sanitized returnTo or /.
  • Without an admin cookie, the page renders Privileged handoff, the explicit-elevation explanation, an optional readable reason, and the current request id.
  • Without a customer cookie, the launcher instructs the visitor to sign in through the consumer shell and does not render the request button.

3. Request elevation#

  • Request admin handoff posts JSON to /api/admin/signin with same-origin credentials.
  • The Admin route reads the customer token from the cookie or trusted header.
  • Missing customer state returns 401 customer-session-missing.
  • The route forwards the customer token as a Bearer credential to POST /v1/admin/session/handoff.
  • The launcher sends x-request-id to the Admin route, but the current BFF session client does not forward that header to the BFF exchange; do not claim one request id spans the full hop.

4. Resolve operator eligibility#

  • The BFF authenticates the customer and looks up their operator record.
  • An eligible operator receives resolved roles, scopes, home workspace, session id, audience, expiry, and a dev or JWT admin token.
  • An authenticated customer without an operator record receives 403 operator_not_eligible.
  • Missing or rejected customer authentication receives 401.
  • This is an explicit first-party HTTP exchange, not an undocumented out-of-band IdP step.
  • The Admin route stores the BFF token in oshun-admin-session.
  • Cookie attributes are Path=/, HttpOnly, SameSite=Lax, BFF-supplied expiry, and Secure in production.
  • Customer and admin cookie names remain separate.
  • The JSON response returns the operator view and sanitized redirect.

6. Return to a safe local path#

  • returnTo must start with one slash.
  • Scheme/host targets, protocol-relative paths, /unauthorized, and /handoff are rejected.
  • Unsafe or absent values fall back to the operator home workspace.
  • The launcher assigns window.location to the returned path after a successful exchange.
  • The sanitizer is a local-path rule, not a complete allowlist of every registered Admin route.

7. Enter and use the Admin shell#

  • Middleware decodes token claims for fast routing and expiry checks.
  • A signed-in operator can load the dashboard and workspace shell.
  • The BFF still performs authoritative signature and scope checks on each proxied Admin API request; middleware claim decoding is not the trust anchor.
  • When the admin cookie later expires or becomes malformed, the protected route closes the loop through invalid-session.

8. Keep the rate limiter accurately bounded#

  • Non-local production requests are limited to 120 requests per minute per derived IP and return 429 with Retry-After: 60 and a request id.
  • Local development requests bypass that limiter.
  • The middleware limiter uses a module-level Map, so it is per Admin instance and is not a shared multi-replica quota.
  • The focused handoff browser coverage does not drive the 121-request production-only boundary.

Post-conditions#

  • An eligible operator has a separate, scoped, expiring, HttpOnly admin cookie.
  • The browser lands on a sanitized local path or the operator home workspace.
  • Ineligible and unauthenticated customer sessions do not receive an admin token.
  • A protected request with an invalid admin cookie clears it and returns to the denial flow.
  • Cross-hop request-id continuity and distributed rate limiting are not implied.

Failure modes#

  • No customer cookie — the handoff page renders guidance only.
  • Customer session rejected — the Admin route returns a visible 401 error.
  • No operator record — the BFF returns 403 and no admin cookie is set.
  • BFF unavailable or malformed payload — the signin route returns a failed exchange rather than inventing a session.
  • Unsafe return path — redirect falls back to the home workspace.
  • Expired or malformed admin cookie — middleware deletes it and redirects with invalid-session.
  • Non-admin scopes in a parseable token — the server-session gate rejects Admin-shell entry even if middleware accepted the token shape.
  • Shared-NAT burst in production — the per-instance IP counter may return 429.
  • Unauthorized-page loop — its root link is not currently a direct handoff link.
  • Correlation overclaim — the request id entering the launcher is not forwarded by requestAdminSessionHandoff.

E2E coverage#

Coverage is strong across middleware, Admin route, and BFF layers but not one browser-driven exchange. No current Playwright case seeds a customer cookie, clicks the launcher, observes the BFF handoff, and lands in the target workspace.

Per-view files touched by this journey#

Cross-references#

  • review-cycle-admin.md — one protected target.
  • apps/oshun/admin/src/middleware.ts — redirect, request-id, and rate-limit behavior.
  • apps/oshun/admin/src/app/handoff/page.tsx and HandoffLauncher.tsx — entry UI.
  • apps/oshun/admin/src/app/api/admin/signin/route.ts — exchange and cookie boundary.
  • apps/oshun/admin/src/lib/bff-session-client.ts — BFF request and response validation.
  • apps/oshun/admin/src/lib/session-cookie.ts — non-authoritative middleware claim parsing.

Open questions#

  • Should the unauthorized page link directly to /handoff with its sanitized return path?
  • Should the Admin signin route forward x-request-id to the BFF?
  • Should returnTo be checked against the registered route model rather than only local-path rules?
  • Which shared store should enforce the production rate limit across replicas?
  • Should Playwright cover the full customer-cookie → click → workspace exchange?
  • How are production JWT signing keys, revocation, and session rotation operated?