Email-only auth · localStorage · session restore
User sees Jeremy's portrait and taps "Start Consultation"
If localStorage.prosenet_user exists → auto-login. Otherwise prompt for email. POST /api/user/login returns user_id.
POST /api/user/load restores collectedData + doc progress. POST /api/sign/all hydrates SIGNATURES_CACHE. POST /api/stripe/is-paid checks paywall status.
If ?stripe_session_id= present → auto-verify payment. If returning user with saved state → "Welcome back" message.
phase: intake · Claude Sonnet 4.6 extraction · auto-save to DB
Jeremy asks each of the 12 intake questions. Every user message → POST /api/chat → chat_intake() calls Claude with system prompt + history. Claude returns JSON with extracted value + field_complete flag.
4 fields have stop conditions: irretrievable_breakdown, no_children, no_property, both_cooperate. If triggered, session enters "stopped" phase with recovery option.
After every field update, userSaveSession() debounces 800ms then POST /api/user/save writes to sessions table.
Each response's collected object paints the intake checklist with green checks + filled values.
Animated clearance · matrix rain · green eligibility banner
When all 12 fields collected OR Jeremy's message matches completion phrases ("everything we need", "all set", "you qualify") → showEligible() fires (guarded by eligibleFired).
12 rows fade in one at a time, status flips from VERIFYING... (gold) to CLEARED ✓ (green). Progress bar fills to 100%.
Matrix fades, left panel swaps to Document Roadmap, UD-1 build auto-triggers.
phase: roadmap + doc_intake · client-side generators · terminal animations
Builds immediately from collectedData. Terminal animates on left panel. Preview button opens full 4-page UD-1 in new tab with watermark + scrape protection.
User says "next" → startDocIntake('ud3') → server enters doc_intake phase → Jeremy asks 9 UD-3 fields naturally (server name, age, address, service date/time/location, ID method, defendant description, military status). Each field extracted by Claude and saved to collectedData.
User says "next" after each. UD-6 triggers another hand-holding (1 field: residency basis A/B/C for DRL §230). All other forms build immediately from existing data.
Each generator is a JS function generateUDxHtml(d) that returns a full HTML document with embedded CSS, print styles, and signature line placeholders.
phase: doc_intake (signatures) · 3 magic links · Pillow image pipeline
After UD-12 builds, Jeremy enters sig_intake and asks for 3 emails: plaintiff, server, defendant.
POST /api/sign/request-tokens creates 3 secure tokens in sig_tokens table, returns 3 URLs like /sign?t=xxx. Links shown in chat.
/tmp/send_sig_invites.py looks up unused tokens and sends personalized emails from jeremy@prosenetwork.org.
Each party opens their link on any device. /sign.html offers canvas draw pad OR photo upload. On submit → POST /api/sign/upload (multipart).
process_signature_image() runs: EXIF orientation fix → grayscale → dark-pixel threshold → alpha mask (ink opaque, bg transparent) → bounding box trim → 10px pad → PNG export. Stored as base64 keyed by (user_id, role).
Next time the user previews a doc, sigLine(label, role) checks SIGNATURES_CACHE[role] and injects <img src="data:image/png;base64,..."> above the signature line.
phase: roadmap (paid) · Stripe Checkout · clean preview mode
4s after signature collection completes → Jeremy shows the gold "UNLOCK FILING PACKAGE — $19.99" button in chat.
Button click → POST /api/stripe/create-checkout → server calls Stripe API with price_data inline ($19.99 USD) → returns hosted URL → browser redirects.
User pays via Stripe's hosted page → Stripe redirects back to /divorce-intake.html?stripe_session_id=cs_xxx.
Frontend detects query param → POST /api/stripe/verify → server calls Stripe GET session → if payment_status === 'paid' updates payments table → returns ok.
userIsPaid = true → openDocPreview() skips the watermark injection → clean previews → "Payment received" message.
phase: post-paid · 9 PDFs emailed to plaintiff
/tmp/send_filing_package.py confirms payments.status = 'paid', pulls collectedData + signatures from DB.
Renders all 9 UD forms via the same JS generators (headless in production) or Python weasyprint fallback. Each PDF has the user's collected data + injected signatures.
Builds one email from jeremy@prosenetwork.org to plaintiff_email with all 9 PDFs as attachments. Instructions for filing with the NY Supreme Court included in the body.
User has everything they need to file. Session marked complete. Upsell (optional: pay $20 more for Jeremy to file on their behalf) tabled for phase 7.