TradeForce migration docs

#Sign-in and account access

Module id: MOD-AUTH
Doc profile: system

Platform auth for TradeForce: email/password registration, verification, sign-in, and password reset, plus the post-auth redirects that send each role into onboarding or their home surface. Target stack is Supabase Auth with a profiles row; Bubble native LogIn / SignUp / SendPasswordResetEmail / ResetPassword are the evidence for behavior, not the runtime provider.

#Purpose

Contractors and companies must be able to create an account, prove email ownership, sign in, and recover a forgotten password so every later authenticated journey can run. Admins sign in on the same surface and go straight to the admin home. This module owns the public auth UI on / and /reset-password, the session client, profile defaults used for routing, and the redirect matrix. It does not own onboarding wizard content, workspace chrome, or shift/marketplace pages.

#Scope boundaries

In scope Out of scope
Index auth modes: sign-in, sign-up, reset request, verify message panel Onboarding step content and uploads (MOD-ONBOARDING)
Reset-password confirm page Header / side menus (MOD-SHELL)
Supabase Auth cutover + profiles fields used for redirects Social IdPs not evidenced on index / reset_pw
Post-login and already-logged-in PageLoaded redirects from / Company / contractor / admin product pages after landing
ACC-AUTH-SURFACE preserve-vs-replace activation decision (ADR) Inventing a third activation path beyond that ADR

#Actors

Actor System behavior
Visitor (signed out) Sees auth modes on / via nav (signin default, signup, reset, verify). Can register as Contractor or Company only.
Contractor After active + onboarding complete, lands on contractor shifts; incomplete onboarding goes to onboarding.
Company After onboarding complete, lands on company shifts. PageLoaded company home does not require active; post-login still sends inactive users to the verify panel first.
Admin PageLoaded or post-login with role admin → admin home. Admin is not offered in the signup role dropdown.
Session client Browser Supabase client (anon key only) + session helpers; never ships service-role secrets.

#Auth composition

Auth is one public surface with mode switching, not four separate apps. The index page is a split layout (branding + form column). Mode is the nav query param from NavigationIndex. Casing matters: the source writes and compares the option displaySignIn | SignUp | Reset | Verify — not the lowercase db_value; every index visibility condition is GetParamFromUrl("nav") = OptionValue(navigationindex, …):display, and MOD-ONBOARDING follows the same convention with nav=Contractor|Company. Mode names are written lowercase below as internal mode ids; the target must parse nav case-insensitively so live links from Bubble emails and bookmarks keep working, whichever casing it emits. Primary submit shares one button; its workflow branches on nav. After credentials succeed, redirects read profiles.active, profiles.onboarding_complete, and profiles.role.

flowchart TB subgraph public["Public auth"] Index["Index / — nav modes"] ResetPw["Reset password page"] end subgraph session["Session"] Auth["Supabase Auth"] Profiles["profiles row"] end subgraph homes["Post-auth landings"] Verify["Verify panel on index"] Onboard["Onboarding"] Co["Company shifts"] Ct["Contractor shifts"] Adm["Admin"] end Index -->|"sign in / sign up / reset request"| Auth Auth --> Profiles Profiles --> Verify Profiles --> Onboard Profiles --> Co Profiles --> Ct Profiles --> Adm ResetPw -->|"update password"| Auth ResetPw --> Onboard

Bubble evidence for composition and redirects is listed under Traceability / IR evidence.

#Primary journeys

Journeys are reconstructed from index and reset_pw workflows (triggers → auth actions → ChangePage / SendEmail). Where activation continues on the onboarding page, that page body is out of this module’s implement scope but the activation contract is named here because signup email deep-links into it.

#J1 — Sign in and route by profile

  1. Visitor opens / (default or nav=signin) and sees Sign In with Email, Password, Forgot Password?, and Sign Up link.
  2. Visitor submits valid email and password; the app calls sign-in and loads the profile used for routing.
  3. If the profile is inactive, the app stays on / with nav=verify; if active and onboarding incomplete, it goes to onboarding; otherwise it routes by role to company shifts, contractor shifts, or admin.
  4. Invalid credentials show an inline/page error and do not navigate.

#J2 — Sign up, verify email, and activate

  1. Visitor opens /?nav=signup, chooses Contractor or Company (Admin excluded), enters email and a password of at least 8 characters, and submits.
  2. The app creates the auth user, stores role on the profile with approved false and active false, sends the verification email, and shows the verify panel (nav=verify, signup tab copy).
  3. Visitor follows the activation link from the email (onboarding URL with active=yes and role in nav when preserving Bubble semantics, or the ADR-chosen Supabase confirm path when replacing).
  4. Password shorter than 8 characters or signup failure blocks success and keeps the user on the form with a clear error.
  1. Visitor opens /?nav=reset, enters email, and chooses Send reset link; the app requests a reset email and shows the reset-specific verify panel.
  2. Visitor opens /reset-password from the email with a recovery session and enters New password and Confirm new password.
  3. When both fields match, the app updates the password and navigates to onboarding (not back to sign-in).
  4. Mismatched passwords or expired recovery show a clear error and do not change the password.

#J4 — Already signed-in visit to the auth index

  1. A user who already has a session opens /.
  2. PageLoaded rules redirect: non-admin with active and onboarding incomplete → onboarding; admin → admin; contractor with active and onboarding complete → contractor shifts; company with onboarding complete → company shifts (company rule does not require active).

URL values below are internal mode ids; on the wire the source spells them SignIn / SignUp / Reset / Verify (option display) — see Auth composition.

Label / trigger Behavior
Default / or nav=signin Sign In mode: email + password; hide role dropdown and verify panel.
Sign Up link Sets nav=signup.
Forgot Password? Sets nav=reset.
Already have an account? / Back to login Sets nav=signin.
After successful signup nav=verify and signup tab → “Verify your email” / activate-account body.
After reset request nav=verify and reset tab → “Reset Password” / reset-link body.
Post-login inactive nav=verify (and verify tab) on index.
Recovery email Lands on /reset-password; success → /onboarding.

#Vertical slices (decompose)

Item Product outcome
AUTH-FOUNDATION Supabase Auth + profiles (role, active, onboarding_complete, approved), RLS own-row, session helpers; ACC-AUTH-SURFACE ADR for provider cutover and signup activation preserve vs replace. Infrastructure enabler — not a user journey by itself.
AUTH-SIGNIN Sign-in form, password reveal, Forgot/Sign Up mode links, post-login redirect matrix, already-logged-in PageLoaded redirects.
AUTH-SIGNUP Role dropdown (Contractor | Company), password length gate, signUp + profile fields, verify panel after signup, verification email per ACC-AUTH-SURFACE.
AUTH-RESET Reset request on index, reset verify copy, /reset-password confirm-when-match, then onboarding.

#Side-effect contracts

Trigger Side effect Owner
Sign in success Session JWT; redirect from profile flags/role AUTH-SIGNIN
Sign up success Auth user + profiles row (active false, approved false, role set); verification email; verify panel AUTH-SIGNUP + AUTH-FOUNDATION
Activation (preserve) Email deep-link to onboarding with active=yes; onboarding PageLoaded sets active true when param present and currently inactive ACC-AUTH-SURFACE + MOD-ONBOARDING page load
Activation (replace) Supabase confirm-email / ADR-named flip of profiles.active ACC-AUTH-SURFACE ADR
Reset request Reset email with redirectTo /reset-password; verify panel AUTH-RESET
Reset confirm (match) Password update; navigate to onboarding AUTH-RESET
Index PageLoaded while logged in ChangePage to onboarding / admin / contractor / company per predicates below AUTH-SIGNIN

#Post-login redirect matrix (after LogIn)

Ordered from the login workflow actions:

  1. active false → index with verify nav/tab
  2. active true and onboarding incomplete → onboarding
  3. role company and onboarding complete → company shifts
  4. role contractor and onboarding complete → contractor shifts
  5. role admin → admin

#PageLoaded predicates on index (already logged in)

Rule Predicate (product terms) Destination
Onboarding gate logged in, role ≠ admin, onboarding incomplete, active true Onboarding
Admin role = admin Admin
Contractor home logged in, active true, role contractor, onboarding complete Contractor shifts
Company home logged in, role company, onboarding complete (no active check) Company shifts

#Style and fidelity

Auth uses the auth_flow shell (section → container → form card). Transcribe visible copy and data-bubble-id on migrated roots (page, form card, primary button, reset card). Shared tokens come from the app-level stylesheet that SHELL-LAYOUT (MOD-SHELL) delivers out of IR styles (ir/slices/styles____part_all.json — 49 styles, 8 color tokens, 1 font token); this cycle's module map has no separate design-system module, so do not defer a token to one. Narrow layout: center the auth column around ≤640px on index; tighten padding around ≤768px on reset.

#Failure modes

Case Expected behavior
Wrong password / unknown user User-visible error; stay on sign-in; no redirect.
Signup duplicate email / provider error User-visible error; do not open verify panel.
Password < 8 characters on signup Block submit; show “Password must be at least 8 characters long.”
Reset email failure Error on reset form; do not pretend success.
Confirm passwords differ Do not call update password; show validation error.
Expired recovery session Message + path back to /?nav=reset.
Inactive user signs in Verify panel, not a role home.
ACC-AUTH-SURFACE undecided Implement blocked on activation and credential cutover (HQ-1).

#Needs human clarification

Id Question Why unclear (plain + IR) Impact
HQ-1 For ACC-AUTH-SURFACE, do we preserve Bubble signup activation (confirm email off + custom Verify email deep-link to onboarding with active=yes) or replace it with Supabase Auth confirm-email, and what is the cutover plan for existing Bubble passwords? Plain: Behavior of signup, verify email, and when profiles.active becomes true is encoded clearly in the export, but the target provider and cutover are a product/platform choice the metadata cannot make. IR: SignUp sets send_confirm_email false and writes role + approve false only (bTHpx1); SendEmail subject “Verify” body links onboarding?nav={role}&active=yes (bTHqT1); onboarding PageLoaded sets active true when param active=yes and currently inactive (bTHsZ1 / bTHse1). ACC-AUTH-SURFACE is a needs_adr decision (preserve vs replace + forced reset / dual-run / IdP cutover), not catalog evidence; the record is docs/adr/ADR-002-acc-auth-surface.md, status open. blocks_implement

#Traceability

Product concept Target (route / component) Bubble evidence
Auth index page /, AuthIndexPage bTGYf
Reset password page /reset-password, ResetPasswordPage AAL
Sign-in submit SignInForm + session signIn Workflow bTHjl1 / action bTHop1 (LogIn)
Post-login redirects postLoginRedirect Actions bTNMx0, bTHov1, bTNNE0, bTNNJ0, bTNNL0
Sign-up submit SignUpForm + signUp Workflow bTHDg0 / bTHpx1 (SignUp)
Verify email send Edge or Auth templates per ADR bTHqT1 (SendEmail)
After signup → verify panel /?nav=verify bTHqJ1
Reset request ResetRequestForm Workflow bTHjd1 / bTHqz1
Reset confirm ResetPasswordForm Workflow bTHrF1 / bTHrP1bTHrQ1 → onboarding
PageLoaded redirects Index load guards bTHqV1, bTKna, bTKnB, bTKnO
Nav modes navMode / ?nav= (parse case-insensitively) navigationindex — db_values signin/signup/reset/verify, URL carries displays SignIn/SignUp/Reset/Verify
Roles profiles.role enum role / bTHAB0 contractor, bTHAC0 company, bTIrk admin
Profile flags profiles.active, onboarding_complete, approved active__boolean, onboarding_boolean, approve1_boolean, role_option_role
Auth provider cutover ADR ACC-AUTH-SURFACE (needs_adr) bTHpx1, bTHqT1, bTHsZ1 / bTHse1 (activation chain); cutover options are ADR-only

#IR evidence

#Module evidence roots

Supporting segments: ir/slices/bTGbC____root.json, ir/slices/AAW____root.json.

#Path-key ↔ inventory id aliases

Prefer inventory ids in evidence_refs; path keys are locators when chasing the sanitized export.

Path key / pointer Inventory id Notes
/pages/bTGbC bTGYf index
/pages/AAW AAL reset_pw
/pages/bTGbC/workflows/bTHoj1 bTHjl1 Sign-in ButtonClicked (nav not signup/reset/verify)
/pages/bTGbC/workflows/bTHjk1 bTHDg0 Sign-up ButtonClicked
/pages/bTGbC/workflows/bTHjj1 bTHjd1 Reset-request ButtonClicked
/pages/AAW/workflows/bTHrK1 bTHrF1 Confirm when passwords equal
/pages/bTGbC/workflows/bTHqZ1 bTHqV1 PageLoaded → onboarding
/pages/bTGbC/workflows/bTKnh bTKna PageLoaded → admin
/pages/bTGbC/workflows/bTKnN bTKnB PageLoaded → contractor shifts
/pages/bTGbC/workflows/bTKnZ bTKnO PageLoaded → company shifts
/pages/bTHDr0/workflows/bTHsd1 bTHsZ1 / action bTHse1 Activation sets active__boolean true (MOD-ONBOARDING page; cited for ACC chain only)

#Signup activation (chased)

#Privacy & authorization

#Option sets used for routing / UI

Generated from the repository at 2026-09-22 15:55 UTC · source of truth is docs/ in the workspace, not this site.