#Role onboarding and credentials
Module id: MOD-ONBOARDING
Doc profile: capability
After sign-up and activation, contractors and companies complete profile setup on /onboarding before entering the shift marketplace. Target stack is a React route with Supabase profiles / documents and a Country State City edge proxy; Bubble page workflows are the behavior evidence, not the runtime.
#Purpose
New Contractor or Company users must finish a first-run wizard: choose the matching role chrome, enter profile and location, upload required contractor documents (or company pay-practice and safety fields), accept terms, and persist profiles.onboarding_complete so later modules can treat them as onboarded. This module owns the onboarding page shell, role panels, CSC location proxy, document uploads for Drivers License and Resume, and the Save writes that mark onboarding complete. It does not own auth forms, workspace chrome, or shift list bodies.
#Scope boundaries
| In scope | Out of scope |
|---|---|
/onboarding route, role nav chrome, welcome popup, logout |
Index auth / reset-password (MOD-AUTH) |
| Contractor general info + Drivers License / Resume uploads | Full docs_type catalog beyond those two uploaders |
| Company profile, pay practices (four concrete trades), safety fields | skill_set option/custom rows (not read/written on this page; later contractor surfaces) |
| CSC states/cities via edge proxy; persist city/state names on profiles | Stripe Connect / KYC (disclaimer copy only on Save footers) |
Set onboarding_complete and post-save navigation per Bubble |
Inventing post-company-save redirect to /company/shifts (first save targets contractor shifts page) |
Activation active=yes branch when AUTH preserves Bubble semantics |
Provider cutover ADR itself (owned by MOD-AUTH / ACC-AUTH-SURFACE) |
#Actors
| Actor | Behavior in this module |
|---|---|
| Contractor (active, not yet onboarded) | Sees contractor panel; fills legal name, phone, emergency contact, skills free-text, state/city; uploads license + resume; accepts terms; Save → contractor shifts. |
| Company (active, not yet onboarded) | Sees company panel; fills company name, rules, location, contact/OSHA/safety/job-site/contact/protocol fields, pay practices; accepts terms; Save → contractor shifts page (Bubble target), with onboarding_complete true. |
| Approved user (any role) | PageLoaded sends them off onboarding to their role home (company → company shifts; contractor → contractor shifts). |
| Anonymous / admin / wrong role | PageLoaded bounces to index; role forms never render. |
| Session client | SPA Supabase client for profiles/documents/storage; CSC API key only on the edge function. |
#Capability composition
Onboarding is one narrow page with two role panels gated by ?nav=Contractor|Company (NavigationOnboarding). Shared location dropdowns call the CSC edge proxy. Contractor document list linkage happens on upload/remove workflows, not on Save; company Save writes company fields on the same profiles row. Activation and approved redirects are PageLoaded gates on the same page.
Bubble evidence for composition is under Traceability / IR evidence.
#Primary journeys
Journeys are reconstructed from onboarding PageLoaded and ButtonClicked / InputChanged workflows (gates → role chrome → CSC-backed fields → Save → ChangePage). Where ACC-AUTH-SURFACE replaces Bubble active=yes, that activation step is skipped; the form journeys still apply after profiles.active is true.
#J1 — Land on onboarding, activate, and role chrome
- An authenticated contractor or company opens
/onboarding(or arrives with emptynav); the app requires a session and bounces anonymous, admin, or other roles to/. - When
navis missing and onboarding is incomplete, the app setsnavfrom the profile role display (Contractor or Company) and shows only that panel. - If the URL has
active=yeswhile the profile is still inactive and unapproved (preserve path), the app setsprofiles.activetrue, strips the param, and shows the Welcome popup. - If the profile is already approved, the app leaves onboarding for the role home (company → company shifts; contractor → contractor shifts).
- Logout clears the session and returns to
/.
#J2 — Contractor completes profile, documents, and save
- Contractor with
nav=Contractorsees General Information and Documents chrome, fills legal names, phone, emergency contact, skills free-text, and picks US state then city from CSC. - Contractor uploads Drivers License and Resume; each creates a typed document and links it on the profile document list (replacing removes the prior row of that type). Remove controls delete the prior document thing.
- Contractor checks Terms; Save stays blocked until terms are accepted.
- On Save, the app updates profile fields only (skills summary, city/state, dependability score 5, onboarding complete, and related name/phone fields) — not the document list — then navigates to
/contractor/shifts. - Upload or Save failure shows a user-visible error and leaves the user on the contractor panel.
#J3 — Company completes profile, pay practices, and save
- Company with
nav=Companysees company name, rules/regulations, state/city, contact area, OSHA, job site / safety / important contact / rules protocol, and pay-practices multi-select (four concrete trades only). - Company selects location via the same CSC helpers and optionally sets a company picture.
- Company checks Terms; Save stays disabled when terms are unchecked or any of these required inputs is empty: company name, state, city, rules/regulations, pay practices (selected count < 1), contact area, OSHA, job site information, safety handbook, important contact information, or rules/protocol.
- On Save, the app updates company fields on
profiles, sets onboarding complete, and navigates to/contractor/shifts(same Bubble ChangePage target as contractor Save — not company shifts on first save). - Save failure shows a user-visible error and stays on the company panel.
#Vertical slices (decompose)
| Item | Product outcome |
|---|---|
| ONB-GATE | /onboarding session/role gates, nav bootstrap, Welcome popup, approved redirect, logout; optional active=yes activation when AUTH preserves Bubble semantics. |
| ONB-CSC | Authenticated edge proxy for US states and cities; SPA client with secrets kept server-side. Infrastructure enabler for location fields. |
| ONB-CONTRACTOR | Contractor form, license/resume uploads (document list linkage), terms gate, profile persist on Save, navigate to contractor shifts. |
| ONB-COMPANY | Company form, pay practices enum multi-select, terms plus full required-field Save disable matrix, profile persist, navigate to contractor shifts per Bubble. |
#Key UI states
| State | When | User sees |
|---|---|---|
| Signed out / wrong role | PageLoaded gate | Redirect to /; no forms. |
nav=Contractor |
Role chrome match | Contractor panel; company panel hidden; General Information / Documents labels. |
nav=Company |
Role chrome match | Company panel; contractor panel hidden. |
| Welcome popup | After active=yes activation |
“Welcome to the TradeForce!” / thank-you body / Close. |
| Terms unchecked | Before Save | Save disabled or blocked (both roles). |
| Company required empties | Company Save button states | Save disabled until every required company field and pay-practices selection is filled (see Failure modes). |
| Save success | After profile write | Navigate to /contractor/shifts. |
| Approved revisit | profiles.approved true |
Redirect to role home (company or contractor shifts). |
| Narrow company layout | Viewport ≤668px | Responsive adjustments on company panel. |
#Style and fidelity
Narrow intentional shell (onboarding column). Transcribe visible labels and stamp data-bubble-id on migrated roots (page, main column, role panels, Save, Welcome popup). 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. Stripe footer sentence is static disclaimer copy only.
#Failure modes
| Case | Expected behavior |
|---|---|
Visit /onboarding signed out |
Redirect to /; never blank forms. |
| Admin or non contractor/company role | Redirect to /. |
| CSC / edge timeout or upstream failure | Domain unavailable; clear UI error; no API key leakage. |
| CSC call without session | Rejected (authz owner). |
| Terms unchecked on Save (either role) | No profile write; no navigation. |
| Company Save required empties | Block Save when company name, state, city, rules/regulations, pay practices count < 1, contact area, OSHA, job site information, safety handbook, important contact information, or rules/protocol is empty; show validation. |
| Document upload or profile Save fails | Inline/page error; stay on current nav panel. |
| Replace Drivers License / Resume | Prior document of that type removed/replaced via upload workflow; no orphan required. |
| ACC-AUTH-SURFACE chose replace | Do not invent a second active=yes handler; activation is AUTH’s confirm path. |
| Approved user on onboarding | Immediate redirect to role home. |
#Traceability
| Product concept | Target (route / component) | Bubble evidence |
|---|---|---|
| Onboarding page | /onboarding, OnboardingPage |
bTHDn0 |
| Main column | OnboardingShell |
bTHDs0 |
| Contractor panel | ContractorOnboardingForm |
bTHGm0 |
| Company panel | CompanyOnboardingForm |
bTHHD0 |
| Nav mode Contractor | Company | navMode / ?nav= |
navigationonboarding, bTHGy0, bTHGz0 |
| Session / wrong-role bounce | gates PageLoaded |
bTHsj1, bTHsl1 |
Bootstrap nav from role |
gates / URL rewrite |
bTNJN0, bTNJP0 |
Activation active=yes |
Welcome + profiles.active |
bTHsZ1, bTHse1, bTHsf1 |
| Welcome popup | WelcomePopup |
bTKXk3, bTKXp3, bTKXv3, bTKXq3, bTKYB3 |
| Approved redirect | Role homes | bTKsL, bTKsN, bTKsR |
| Active incomplete stay | Self ChangePage with nav | bTKYU3, bTKYb3 |
| Logout | signOut → / |
bTKpL, bTKpB |
| CSC API | Edge country-state-city |
external_ns:bTKtr, external_call:bTKtr:bTKts, external_call:bTKtr:bTKvG |
| Contractor Save (profile fields only) | contractorSave → /contractor/shifts |
bTHtH1, bTHtN1, bTKwr1 |
| Document list add/replace/remove | documents + Storage |
bTHKX0, bTKzP1, bTLAz1, bTLBH1, bTHsx1, bTLBN1, docs_type, docs_list_custom_documents |
| Company Save + disable matrix | companySave → /contractor/shifts |
bTHub1, bTHuh1, bTKuL, bTHJb0, element_condition:bTHJb0:0, element_condition:bTHJb0:1, bTHLf0 |
| Company required inputs | form fields | bTHHh0, bTHHt0, bTHHv0, bTHIR0, bTHIL0, bTHIX0, bTHIx0, bTHJD0, bTHJT0, bTHJZ0, bTKwT1 |
| Pay practices | profiles.pay_practices |
pay_practices, bTHuR1, bTHuV1, bTHuW1, bTHuX1 |
| Profile flags / fields | profiles.* |
onboarding_boolean, active__boolean, approve1_boolean, profileimage_image, first_name_text, city_text, state_text, short_summary_about_your_experience_text, dependability_scoup_number, 2__contact_area_text |
#IR evidence
#Module evidence roots
bTHDn0— onboarding page (/pages/bTHDr0): role panels, PageLoaded gates, Save workflows, Welcome popup.
Supporting segments from module-map: ir/slices/bTHDr0____root.json, documents, skill_set (residual — not used on this page), docs_type, external_ns:bTKtr.
#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/bTHDr0 |
bTHDn0 |
onboarding |
/pages/bTHDr0/workflows/bTNJO0 |
bTNJN0 |
PageLoaded bootstrap nav from role |
/pages/bTHDr0/workflows/bTHud1 |
bTHub1 |
Company Save ButtonClicked |
/pages/bTHDr0/workflows/bTHtJ1 |
bTHtH1 |
Contractor Save ButtonClicked |
/pages/bTHDr0/workflows/bTHtJ1/actions/0 |
bTHtN1 |
ChangeThing profile fields (no docs_list_custom_documents) |
/pages/bTHDr0/workflows/bTHtJ1/actions/1 |
bTKwr1 |
ChangePage → contractor shifts (bTHMg) |
/pages/bTHDr0/workflows/bTHud1/actions/1 |
bTKuL |
ChangePage → contractor shifts (bTHMg) |
/pages/bTHDr0/workflows/bTHKb0 |
bTHKX0 |
Drivers License InputChanged (list linkage) |
/pages/bTHDr0/workflows/bTLBM1 |
bTLAz1 |
Resume InputChanged (list linkage) |
/pages/bTHDr0/elements/.../bTHLv0/states/0 |
element_condition:bTHJb0:0 |
Company Save required-field disable |
/pages/bTHDr0/elements/.../bTHLv0/states/1 |
element_condition:bTHJb0:1 |
Company Save terms disable |
/pages/bTHDr0/workflows/bTHsd1 |
bTHsZ1 / bTHse1 |
Activation sets active__boolean |
#Gate and activation matrix (chased)
bTHsj1: not logged in or role neither contractor nor company → ChangePage index.bTNJN0: logged in, onboarding incomplete, role ≠ admin,navempty → set URLnavfrom role display.bTHsZ1/bTHse1: URLactive=yesand currently inactive (and unapproved per decompose) → setactive__booleantrue, strip param, show Welcome.bTKsL:approve1_booleantrue → company → company shifts page; contractor → contractor shifts page.bTKYU3: active true, approved false, active param empty → stay on onboarding withnav.bTKpL: LogOut → index.
#Contractor Save vs document list (chased)
bTHtH1gated by terms checkbox (bTHLF0).bTHtN1ChangeThing CurrentUser writes profile image, names, phone, emergency contact, skills free-text (short_summary_about_your_experience_text), city/state from CSC names,dependability_scoup_numberliteral 5,onboarding_booleantrue, andfull_name__search__text. It does not writedocs_list_custom_documents.bTKwr1ChangePage →bTHMg(contractor shifts).- Document list add/replace: InputChanged
bTHKX0(Drivers License) andbTLAz1(Resume) run NewThing + MakeChangeCurrentUser ondocs_list_custom_documents(bTKzP1/bTLBH1) withdocs_typedriver_s_license/resume(bTKzH1,bTKzC1). Remove controlsbTHsx1/bTLBN1DeleteThing the prior document.
#Company Save button-state matrix (chased)
- Terms gate:
element_condition:bTHJb0:1— checkboxbTHLf0not checked →button_disabled. - Required fields gate:
element_condition:bTHJb0:0— Save (bTHJb0) disables when any of these is empty (OR chain), or pay-practices count < 1:
| Input | Product field |
|---|---|
bTHHh0 |
Company name |
bTHHt0 |
State (CSC name) |
bTHHv0 |
Rules / regulations |
bTHIR0 |
Pay practices (count < 1) |
bTHIL0 |
Contact area |
bTHIX0 |
OSHA |
bTHIx0 |
Safety information / Safety Handbook |
bTHJD0 |
Job site information |
bTHJT0 |
Important contact information |
bTHJZ0 |
Rules / Protocol |
bTKwT1 |
City (CSC name) |
- Workflow
bTHub1/ ChangeThingbTHuh1then writes company name intofirst_name_text, plus contact/OSHA/pay_practices/rules/safety fields, city/state,onboarding_booleantrue. bTKuLChangePage →bTHMg(contractor shifts) — same exit as contractor first save; approved-company redirect to company dashboard remainsbTKsLonly.
#Location API (chased)
external_ns:bTKtrCountry State City; callsbTKts(states) andbTKvG(cities) used private headers in Bubble — target edge must keep the key server-side.- State/city UI on both panels (
bTHEd0/bTKwT1and related dropdowns); persist display names oncity_text/state_text.
#Residual: skill_set
- Option set / custom type
skill_setexists in the catalog but this page never reads or writes it. Contractor “skills” here are free-textskills_summary. Owned by later contractor profile/shift surfaces (MOD-CONTRACTOR-SHIFTS).
#Privacy & authorization
- Target: RLS owner read/write on
profilesanddocuments; Storage owner policies for avatars/docs. - CSC edge: valid user JWT required; no anon public proxy.
- Bubble
documentsprivacy roles (admin/company/user select) inform later admin views; onboarding writes are owner-scoped.
#Option sets used on this page
navigationonboarding:contractor|company(display Contractor | Company).pay_practices:concrete_carpenter,concrete_walls,concrete_laborer,concrete_finisher.docs_type: onlydriver_s_licenseandresumerequired as upload affordances here (full enum lives in DATA-MODEL).