V1 Web PWA · Surface walkthrough

Shell: Auth and session

A per-surface walkthrough of the V1 Web PWA: layout, states, interactions, data, and cross-references.

unspecified
12sections3 minread

On this page

Source: apps/oshun/web/src/proxy.ts (PUBLIC_PATHS at proxy.ts:14; Next 16 — there is no middleware.ts), apps/oshun/web/src/lib/auth-context.tsx, apps/oshun/web/src/lib/providers.tsx (AuthProvider), apps/oshun/bff/src/routes/...auth*, @oshun-web/isis-entitlements (AAA_ONLY_STUDIO_ROUTES, resolveStudioBoundary)

Where auth lives in the customer surface, what guards what, and how a user moves between anonymous / signed-in / role-gated states.

Auth states#

  • Anonymous — no session cookie; can view PUBLIC_PATHS only
  • Signed-in — valid session; standard user; access to customer surface
  • Signed-in + AAA tier — access to AAA_ONLY_STUDIO_ROUTES
  • /operator/* — session-gated only; the proxy has no operator-role gate (a signed-in non-operator is not blocked at the proxy)
  • /(workspace)/* — session-gated only; the proxy has no tenant / workspace-member gate
  • Session expiredproxy.ts redirects to /welcome with ?redirect=...&expired=1 preserving the deep link

Public paths (no auth required)#

From proxy.ts's PUBLIC_PATHS (proxy.ts:14):

  • /opengraph-image, /twitter-image
  • /welcome, /welcome/domains, /welcome/download
  • /welcome/opengraph-image, /welcome/twitter-image
  • /legal/privacy, /legal/terms, /legal/cookies, /legal/accessibility, /legal/ccpa, /legal/dpa
  • /landing, /v3/landing, /legal/lilith, /legal/lilith/privacy, /status
  • /lilith (design system showcase), /system, /system/edge-states, /system/emails, /system/og, /system/verify
  • /studio/generation/living-scene (customer-tier Living Scene)
  • /studio/compose
  • /v2, /v2/wiki, /v2/glossary, /v2/roadmap (V2 public shell + Sophia-backed knowledge surfaces)

PUBLIC_PATHS is 30 exact entries in total. And PUBLIC_PREFIXES (15): /_next, /api, /icons, /images, /fonts, /screenshots, /scene, /studio/compose, /og, /.well-known, /manifest.json, /robots.txt, /sitemap.xml, /favicon, /sw.js.

For each entry above, verify in dev:

  • Anonymous user can load the route (200, not 401)
  • No information that would require auth leaks into the response

Sign-in flow#

  • Entry: /welcome — primary sign-in CTA
  • Magic link — email entry → email sent → click in mail → return to original ?redirect= route (welcome page reads searchParams.redirect, welcome/page.tsx:72)
  • OAuth provider(s) — each available provider button works (Google, Apple, …)
  • Password reset — request → email → reset form → sign-in
  • Sign-up flow — name/email/password → email verification → onboarding
  • Error: invalid credentials — clear message; no email enumeration
  • Error: rate-limited — clear message; backoff communicated
  • Error: provider down — graceful fallback to alt provider or email link

Sign-in success#

  • ?redirect= parameter honored on first nav after sign-in
  • Default landing/ (home) when no ?redirect=
  • Session cookie set with HttpOnly, SameSite=Lax, Secure (in prod)
  • Auth state propagates to all open tabs (BroadcastChannel)

Session refresh#

  • Silent refresh — happens before token expiry; user not interrupted
  • Refresh failure → user signed out cleanly; redirect to sign-in
  • Returning after long idle — session restored if refresh token valid

Sign-out#

  • Profile menu → Sign out — confirms in dialog; clears session; clears IndexedDB / local data
  • Sign-out everywhere — option to invalidate all sessions
  • SW caches — auth-scoped caches cleared on sign-out
  • PWA relaunch target cleared on sign-out

AAA-only studio routes#

From @oshun-web/isis-entitlements.

  • Non-AAA user on AAA route — gated UI with upgrade CTA; URL preserved
  • AAA upgrade flow at /aaa-upgrade — entry from gated routes
  • Post-upgrade — return to originally-attempted route

Role-based gates#

  • Operator routes (/operator/*) — session-gated only in the proxy; no operator-role gate (a role gate appears absent — possible gap vs intended scope)
  • Workspace routes (/(workspace)/*) — session-gated only in the proxy; no tenant / workspace-member gate
  • Studio routes (/studio/*) — base entitlement varies per area; the proxy enforces the §24.11 AAA-only Studio Isis boundary (AAA_ONLY_STUDIO_ROUTES, resolveStudioBoundary)
  • 403 / 404 UI — clean denial; explains why; no info leak

Cross-tab sync#

  • Sign-in in one tab — other tabs update auth state within 1 s
  • Sign-out in one tab — other tabs sign out
  • Token refresh — coordinated; not duplicated per-tab

CookieConsentBanner.tsx — analytics/marketing cookies only.

  • First visit — banner visible at bottom
  • Essential cookies — set regardless of consent (session, csrf)
  • Analytics cookies — set only after accept
  • Reject — only essential cookies present
  • Consent persisted — banner doesn't reappear
  • Re-open consent from profile/settings → Privacy

Cross-references#

Open questions / known gaps#

  • List of OAuth providers actually configured in V1
  • Document the exact AAA entitlement check for each AAA_ONLY_STUDIO_ROUTES entry
  • Confirm tenant-admin auth lives in apps/oshun/tenant-admin only, not in this app