---
path: /handoff
surface: tenant-admin
domain: meta
auth: anon (public path — no tenant session required)
source: apps/oshun/tenant-admin/src/app/handoff/page.tsx
status: drafted
last_walked: '—'
---

# Tenant admin handoff

## Purpose

Public bridge view explaining that the tenant cockpit needs a tenant-scoped
session (`tenant:admin:{tenantId}` claim) and that the identity provider will
issue one and redirect back. It is one of the two `PUBLIC_PATHS` in
`middleware.ts` (with `/unauthorized`) and is reachable without a session.

## Entry points

- `/unauthorized` "return to the handoff" link →
  `/handoff?returnTo=<encoded path>` (see [help.md](./help.md) / middleware
  redirect chain).
- Direct URL `/handoff?from=<origin>` (IdP-orchestrated landing after sign-in).
- Listed in `middleware.ts` `PUBLIC_PATHS` so it renders pre-authentication.

## Layout regions

No `TenantShell` (anonymous, minimal page):

- **Main** (`<main data-testid="tenant-handoff-page">`):
  - `<h1>Tenant admin handoff</h1>`
  - Paragraph: "You arrived from `<strong>{from}</strong>`" + explanation that
    the IdP issues a `tenant:admin:{tenantId}` claim and redirects back.
  - Paragraph with `<Link href="/">Continue to tenant home →</Link>`.

## States

- [ ] **Loading** — N/A; synchronous server render; only reads `searchParams`.
- [ ] **Empty** — when `?from` is absent, `from` defaults to `'unknown'` and the
      sentence reads "You arrived from unknown".
- [ ] **Populated (short)** — `?from=<origin>` renders the provided origin
      verbatim inside `<strong>`.
- [ ] **Populated (long)** — N/A; single static paragraph regardless of params.
- [ ] **Error (recoverable)** — N/A; no query.
- [ ] **Error (unrecoverable)** — no custom handler; render throw → Next
      default.
- [ ] **Offline** — N/A; static server-rendered page, no data.
- [ ] **Gated** — N/A; public path. No session is read and none is required;
      middleware skips auth for `/handoff`.
- [ ] **Standalone PWA** — N/A; no manifest. (verify.)

## Interactions

- [ ] **Continue to tenant home →** (`<Link href="/">`)
  - Function: navigates to `/`. If the IdP has issued a valid
    `oshun-tenant-session` cookie, `/` renders; otherwise middleware redirects
    back to `/unauthorized?reason=missing-session&returnTo=/`.
  - Keyboard: standard link; Enter activates; in tab order.
  - Screen reader: announces "Continue to tenant home, link".
  - Touch target: inline text link — verify ≥ 44×44 px hit area on coarse
    pointers.
  - Mobile (≤ 640 px): inline; no layout delta.
  - Disabled when: never.
  - Offline behavior: standard navigation (no SW).
  - Telemetry: _None._

## Data & contracts

- **Reads**: `searchParams` (`{ from?: string }`) only. No session, no BFF call.
  Note: the `/unauthorized` link passes `returnTo`, but this page reads only
  `from` — `returnTo` is ignored here.
- **Writes**: _None._
- **Realtime**: _None._
- **Caching**: SSR (dynamic; depends on query params).
- **Auth/role check**: none — `middleware.ts` `PUBLIC_PATHS` includes
  `/handoff`; no `getTenantServerSession()` call in the page.

## Cross-references

- Middleware: `apps/oshun/tenant-admin/src/middleware.ts` (`PUBLIC_PATHS`).
- Session issuance note: `apps/oshun/tenant-admin/src/lib/session-cookie.ts`
  (`OSHUN_TENANT_DEV_TOKEN_PREFIX = 'tenant.'`; operator equivalent at
  `apps/oshun/bff/src/routes/admin-session.ts`).
- Sibling routes: `/unauthorized` (the other public path; no file requested),
  [home.md](./home.md).

## Open questions / known gaps

- [ ] The page accepts `?from` but the upstream `/unauthorized` link sends
      `?returnTo`. Document whether `from` is ever populated by a real IdP flow,
      and whether `returnTo` should be honored on "Continue".
- [ ] No actual IdP redirect is implemented in-app; the cookie is issued out of
      band (dev `tenant.` token). Document the production session-issuance path.
