# AppShell integration (lynkeduppro-crm)

This app now consumes **`@abe-kap/appshell-sdk`** for authentication, identity, and
(eventually) the data door. The integration follows a **strangler pattern**: the SDK
is wired in everywhere, but every real call is gated behind `isShellConfigured()`. When
the Shell isn't configured (no `NEXT_PUBLIC_SUPABASE_URL`), the app behaves exactly as
before — the existing mock portal and static demo user remain the fallback, so the
deployed demo keeps working until the Shell BFF is live.

## What flips it on

Set these (see `.env.local.example`) and redeploy:

| Var | Purpose |
| --- | --- |
| `NEXT_PUBLIC_SUPABASE_URL` | Presence flips the app from mock → real auth (the `isShellConfigured()` switch). |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Browser-safe publishable anon key. |
| `NEXT_PUBLIC_BFF_BASE_URL` | Where the browser reaches the BFF (default `/shell`). |
| `BFF_ORIGIN` | Deployed Shell BFF origin; the `/shell/*` rewrite proxies here. |
| `NODE_AUTH_TOKEN` | `read:packages` token to install the SDK from GitHub Packages (local + Vercel). |

## How it's wired

- **`src/app/providers.tsx`** — mounts `<AppShellProvider>` app-wide (via the root
  layout). `auth` is passed **only when Supabase is configured**; otherwise the provider
  mounts without auth and `useAuth()` reports `unauthenticated` (never crashes).
- **`next.config.ts`** — `transpilePackages` for the SDK + a `/shell/* → ${BFF_ORIGIN}/api/*`
  rewrite so the HttpOnly session cookie flows same-origin. We use `/shell` (not `/api`)
  to avoid clobbering the existing `/api/geo` route.
- **Login** (`components/portal/login-flow.tsx`) — password sign-in → `login()`,
  social buttons → `loginWithOAuth()` (google/microsoft→azure/apple), and the OAuth
  return is finished with `completeOAuthLogin()`. A resolved ACE goes straight to
  `/dashboard` (Supabase handles MFA server-side; no mock 2-step).
- **Register** (`components/portal/register-flow.tsx`) — email/password sign-ups call
  `register()` on finish. (SSO sign-ups already hold a session from OAuth.)
- **Dashboard gate** (`components/dashboard/auth-gate.tsx`) — bounces unauthenticated
  visitors to the portal; pass-through when the Shell is off.
- **Topbar** (`components/dashboard/topbar.tsx`) — shows the real identity from the
  App Context Envelope (`useAuth().user`), falling back to the static demo user.

## Local build note

`next build` needs Node ≥ 20.9. Installing the SDK needs a GitHub Packages token; for a
token-free local build you can symlink the workspace copy:

```
mkdir -p node_modules/@abe-kap
ln -s /abs/path/to/appshell-sdk node_modules/@abe-kap/appshell-sdk
```

## Not yet wired (follow-ups)

- Register-via-OAuth still uses the mock `startSocial` (login OAuth is real).
- Email/phone OTP steps in register are still mock (SDK has `sendEmailOtp`/`verifyEmailOtp`).
- Passkey enrollment, tenant switcher, logout menu, and the data door (`useQuery`/
  `command`) are available in the SDK but not surfaced in the UI yet.
- Backend integration (frontend ↔ be-crm through the data door) is deliberately deferred.
