Add a real signup path instead of the accidental one
SAAS_PLAN.md 2.2: there was no /signup page. The only self-serve path was Google sign-in on /login, which auto-provisions a Firebase account with no role or org claim at all - previously that meant "viewer role, full read access" the moment the AuthProvider cookie logic (previous commit) let it through. That's closed now regardless; this commit is the other side of it - giving people an actual way in. app/signup/page.tsx: email/password (createUserWithEmailAndPassword) or Google, same visual language as /login. It only creates the Firebase account - org naming is deliberately not on this page, so every path that produces an account with no org (this one, and Google-via-/login) converges on the same next screen. app/onboarding/page.tsx: that screen. Shown to any signed-in user with no orgId (ChromeSwitcher's redirect, previous commit), collects an org name, calls the new c2api.signup() -> POST /auth/signup (routers/links.py, already shipped), then refreshClaims() to force-refetch the ID token so orgId picks up immediately and the same redirect effect sends them on to /dashboard - no manual reload needed. lib/c2api.ts also gained getOrg/updateOrg and the enrollment-token mint/list/revoke calls (routers/org.py, already shipped on the backend) and joinWaitlist (routers/waitlist.py) - none consumed yet, wired in ahead of the settings/legal commits that use them so this stays one add per concept rather than scattering client additions across later commits. /login gained a "Don't have an account? Sign up" link to /signup. This is signup plumbing, not marketing copy - pricing/plan copy (app/pricing, lib/billing.ts) is untouched in this pass, that's a separate, still-open decision (SAAS_PLAN.md section 6). Typecheck: clean (tsc --noEmit via the WSL-native ~/drb-frontend copy). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c7f985df42
commit
2a1d52b7af
@@ -222,4 +222,35 @@ export const c2api = {
|
||||
// Session recording — called on each explicit sign-in
|
||||
recordSession: () =>
|
||||
request<{ ok: boolean }>("/auth/session", { method: "POST" }),
|
||||
|
||||
// Org provisioning (SAAS_PLAN.md B4) — called once from /onboarding right
|
||||
// after a Firebase account exists but before it has an org_id claim.
|
||||
signup: (orgName: string) =>
|
||||
request<{ org_id: string; org_name: string; already_provisioned: boolean }>("/auth/signup", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ org_name: orgName }),
|
||||
}),
|
||||
|
||||
// Organization profile
|
||||
getOrg: () =>
|
||||
request<{ org_id: string; name: string; created_at: string }>("/org"),
|
||||
updateOrg: (name: string) =>
|
||||
request<{ ok: boolean; name: string }>("/org", { method: "PATCH", body: JSON.stringify({ name }) }),
|
||||
|
||||
// Per-org enrollment tokens (SAAS_PLAN.md B2b)
|
||||
listEnrollmentTokens: () =>
|
||||
request<{ token_id: string; label: string; created_at: string; revoked: boolean; uses: number }[]>(
|
||||
"/org/enrollment-tokens"
|
||||
),
|
||||
mintEnrollmentToken: (label: string) =>
|
||||
request<{ token_id: string; token: string; label: string }>("/org/enrollment-tokens", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ label }),
|
||||
}),
|
||||
revokeEnrollmentToken: (tokenId: string) =>
|
||||
request(`/org/enrollment-tokens/${tokenId}`, { method: "DELETE" }),
|
||||
|
||||
// Public waitlist — no auth, see routers/waitlist.py
|
||||
joinWaitlist: (body: { email: string; org_name?: string; note?: string }) =>
|
||||
request<{ ok: boolean }>("/waitlist", { method: "POST", body: JSON.stringify(body) }),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user