# Setup — Account Manager (Phase A) ## Prerequisites - Node.js 18+ (tested on v22) - A reachable PostgreSQL 15+ database, separate from any company app's database - The company app checked out as a sibling (`../` from this directory) — Phase A wires this Manager to exactly one manually-provisioned company ## First-time setup 1. `npm install` 2. `npm run generate-handoff-keys` — generates `keys/handoff-private.pem` (kept here, gitignored, never shared) and `keys/handoff-public.pem` (copy this into every company app's `keys/handoff-public.pem`, referenced by its `HANDOFF_PUBLIC_KEY_PATHS`). 3. Copy `.env.example` to `.env`, fill in a real `DATABASE_URL`, random JWT secrets, and (optional for now) Google/Microsoft OAuth credentials. 4. `npm run prisma:migrate` then `npm run prisma:seed` — seeds one operator `Person` (`joosth2002@icloud.com` / `ChangeMe123!` — change this) and one `Company` row pointing at the company app on `http://localhost:5173` (the frontend, since `/handoff` is a frontend route). 5. `npm run dev` — API on `http://localhost:5100`. 6. `cd client && npm install && npm run dev` — Manager frontend on `http://localhost:5174`. ## Verifying it works - `npm test` — unit tests (handoff token sign/verify, tampering, expiry — no DB required). - `npm run test:integration` — against the real Manager DB: login, list companies, issue a handoff token, reject a handoff to a company with no membership. - The company app has its own integration test (`../tests/integration/handoff.spec.ts`) that mints a token with this Manager's real private key and exchanges it against the real company app DB — proving both sides of the handoff agree, replay is rejected, and a token minted for a different `companySlug` is rejected there. - Manual browser smoke: with both this Manager (`5100`/`5174`) and the company app (`5000`/`5173`) running, open `http://localhost:5174`, sign in with the seeded operator, pick "Demo Company," and confirm you land inside the company app already authenticated (and that `http://localhost:5173/login` no longer exists — it's `/handoff` now). - `GET /health` — basic liveness check. ## Adding a second company (still manual in Phase A) Phase B automates this. Until then: stand up another copy of the company app on a different port/database by hand, then insert matching `Company` and `PersonCompanyMembership` rows here.