- HANDOFF.md: refreshed for 2026-05-14. PR #166 + #168 merged. Bug-pending-capture item from 2026-05-12 likely resolved by PR #168 (dashboard CTA dead-link + welcome step-2 PSA confusion); confirm with user next session. Stripe/EIN blocker carried forward. Issues #171 (WelcomeStep2 connect-now test coverage) and #172 (gitignore core dumps + agent .remember/ state) noted. - CURRENT_TASK.md: added entries for PR #166, #167, #168 to "Recently shipped" with full narrative of the three bundled threads on #168 (session expiration, dashboard CTA fix, welcome step-2 reshape). - SESSION_LOG.md: appended detailed 2026-05-14 entry covering the bug-fix design conversation, the FOCUS_START_SESSION_EVENT pattern, the welcome step-2 Connect-now-bug catch (link never persisted primary_psa), CI gating on PR #168, and the two filed issues. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9.4 KiB
HANDOFF.md
Last updated: 2026-05-14
Active task: Phase O cutover for self-serve signup. All code blockers remain closed on main. Still blocked on Stripe live-mode activation — root cause is EIN, not code. User does not yet have an EIN for ResolutionFlow, LLC; Stripe requires a tax ID for live-mode activation. EIN application via IRS.gov was scheduled for 2026-05-13 — confirm status at next session start. Mailing-address decision (carried forward from 2026-05-12): user enters home address into Stripe's private business profile temporarily so live-mode isn't blocked on the P.O. Box; public ContactPage/PoliciesPage mailing-address TODOs stay "available on request" until the P.O. Box is purchased. Stripe accepts an address update later without re-verification. Apex DNS at Namecheap is still missing (separate user-side issue, only matters once Stripe runs site-verification). Nothing on the code side blocks live-mode flip.
Bug-pending-capture item (2026-05-12) — likely resolved: Prior session noted "user reported finding a bug, will send screenshot next session." This session surfaced two concrete UX bugs that were fixed and merged (PR #168): the dashboard "Start a session" CTA was a dead link, and welcome step-2's PSA setup had a near-invisible "Connect now →" link that didn't even persist primary_psa. Confirm with user at next session start whether the screenshot bug was one of these or something else still pending.
Where this session ended
Two PRs merged into main:
- PR #166 (
fe0e692) — docs/handoff doc updates from prior session. Squash-merged 2026-05-14. - PR #168 (
3a35121) — session expiration policy + dashboard NextStep CTA fix + welcome step-2 PSA CTA reshape. Merge-committed 2026-05-14. Three notable additions:feat(dashboard)8d79dd9— The "Start a session" CTAs on NextStepCard and SetupChecklist used toLink-navigate to/, leaving the user on the same page (the StartSessionInput lives on the dashboard) with no visible response. Replaced with aFOCUS_START_SESSION_EVENTwindow event the StartSessionInput listens for: scrolls input to viewport top (scrollIntoView({block:'start'})), focuses the textarea (withpreventScroll:trueso it doesn't fight the smooth scroll), pulses argba(96,165,250,…)ring for 900ms. NextStepCard hides itself via locallocallyHiddenstate on click so the user isn't double-prompted while typing. SetupChecklist gets the same event-dispatch treatment for itsran_sessionrow.feat(welcome)dc88797— Welcome step-2 PSA CTA reshaped. Selecting a real PSA now swaps the single Continue + tiny "Connect now →" link for an explicit two-button choice:Connect <PSA> now(primary, blue — savesprimary_psathen routes to/account/integrations) andConnect later(secondary outlined — savesprimary_psathen continues to step 3). Important pre-existing bug fixed: the old subtle Link never actually persistedprimary_psabefore navigating away. Both new buttons do. "No PSA yet" and no-selection states still show the original single Continue. Skip-this-step and Skip-the-rest unchanged. Existing tests pass without edits (testidswelcome-step-2-connect-nowandwelcome-step-2-continuereused).docs:e5b2624— addeddocs/plans/2026-05-13-public-landing-routing-refactor.md,docs/architecture/reports (god-node map + report 2026-05-06, workflows.json/html, workflows-analysis.html),docs/tutorials/build-a-page.md, andabc-feat-self-serve-signup-phase-2-design-20260507-112020.mdat repo root.
tsc --project tsconfig.app.json --noEmit clean across all changes. Local vitest blocked by root-owned node_modules/.vite-temp (same env issue noted in prior handoffs); CI ran the suite green.
Two issues filed for session leftovers:
- Issue #171 — Test coverage for the new welcome step-2 "Connect now" path (existing tests still pass but don't exercise the new button's save + redirect-to-integrations behavior).
- Issue #172 — Repo hygiene: gitignore
core.[0-9]*+**/.remember/, and delete the existing 20MB core dumps (core.144926,core.145678,docs/architecture/core.1392564) anddocs/architecture/.remember/. Carried forward across multiple sessions.
Working tree clean except those persistent untracked items (intentionally left for issue #172).
Single alembic head: 4ce3e594cb87 (no schema changes this session).
Resume point
First thing next session:
- Confirm with user whether the "bug-pending-capture" screenshot bug from 2026-05-12 was one of the two PR #168 fixes or something else still pending.
- Check EIN application status (filed 2026-05-13 via IRS.gov). If granted, unblocks the Phase O Stripe live-mode setup chain.
After that — Phase O manual ops, all user-side, all gated on EIN landing first:
- EIN application status check (user, applied 2026-05-13).
- Stripe Dashboard live-mode (once EIN is in hand):
- 3 Products (Starter, Pro, Enterprise). Monthly Prices for Starter ($19.99) + Pro ($29.99). No Prices on Enterprise (sales-led).
- Customer Portal with plan-switching disabled.
- Webhook at
https://api.resolutionflow.com/api/v1/webhooks/stripewith 5 events. Save live signing secret. - Business profile fields: Customer service URL
https://resolutionflow.com/contact. Refund/cancellation policy URLhttps://resolutionflow.com/policies. Termshttps://resolutionflow.com/terms. Privacyhttps://resolutionflow.com/privacy. Phone(470) 949-4131. Mailing address = user's home address temporarily (private Stripe field; swap to P.O. Box later without re-verification). EIN = the newly-issued tax ID.
- Apex DNS fix at Namecheap (re-add
@ALIAS →c9g7uku8.up.railway.app, or re-add apex as a Railway custom domain). Becomes the next blocker once Stripe runs site-verification. - Railway prod env:
STRIPE_SECRET_KEY=sk_live_...,STRIPE_WEBHOOK_SECRET,STRIPE_PUBLISHABLE_KEY+VITE_STRIPE_PUBLISHABLE_KEY(frontend redeploy required — Vite bake-at-build, Lesson 60),OAUTH_REDIRECT_BASE=https://resolutionflow.com,SELF_SERVE_ENABLED=false(still false at this point),INTERNAL_TESTER_EMAILS=<allowlist>, prod Google + Microsoft OAuth credentials. - Bootstrap prod super-admin via
create_site_admin.py(PR #167) — already done end-to-end on prod per 2026-05-12 user confirmation. Re-runnable if needed. - Sync Stripe → DB:
railway run python -m scripts.sync_stripe_plan_ids(or viarailway ssh). Verifyplan_billingrows havesk_live_*price IDs. - Internal validation (Phase O Task 46): 9 scenarios with internal testers whose emails match
INTERNAL_TESTER_EMAILS. - Flag flip (Task 47): email pilots, set
SELF_SERVE_ENABLED=true+VITE_SELF_SERVE_ENABLED=true(frontend redeploy). PostHog signup-funnel dashboard + Sentry alert at >1/hour Stripe webhook errors.
Open issues from prior session (non-code, user-side)
- Apex DNS missing.
resolutionflow.com(apex) returns no A/CNAME at the authoritative DNS (Namecheap). Whenwwwwas reconfigured in Railway, the apex record got dropped from the zone.wwwworks (cert provisioned 2026-05-08 01:40 UTC). User to re-add apex record at Namecheap (ALIAS@→c9g7uku8.up.railway.app) or re-add the apex as a Railway custom domain. Railway path is more durable. - Edge HSTS sticky state on user's machine. Browser remembers the earlier broken-cert visit. Fix:
edge://net-internals/#hsts(deleteresolutionflow.comandwww.resolutionflow.com) +#dnsclear host cache +#socketsflush.
Carry-forward
- Annual pricing intentionally NOT implemented — user wants exit flexibility. Schema columns preserved as nullable.
sync_stripe_plan_ids.pyleaves annual fields NULL. INTERNAL_TESTER_EMAILSparsed comma-separated → normalized lowercase list. Anonymous callers always see the global flag — allowlist never leaks via unauthenticated request content (regression test enforces).- Office-hours design doc now at
docs/root (abc-feat-self-serve-signup-phase-2-design-20260507-112020.md) as of this session. NOT yet adopted as roadmap — gated on 3 cold calls with external Directors of Onboarding. - Mailing address fill-in: search for
TODO: replace with full mailing addressinfrontend/src/pages/ContactPage.tsxandfrontend/src/pages/PoliciesPage.tsx(one each) once P.O. Box is purchased. backend/scripts/create_site_admin.pyis the durable site-admin bootstrap tool — idempotent. Three modes:--send-reset,--print-reset,--promote-only. Run from inside the deployed backend container viarailway ssh.- Bot-crawlability of legal pages: still SPA-rendered. Stripe didn't enforce content scraping last time (issue was DNS). If a future vendor review flags it, pre-render with
vite-plugin-prerender-spa(~half day). - Frontend env additions for cutover:
VITE_SELF_SERVE_ENABLED,VITE_GOOGLE_CLIENT_ID,VITE_MS_CLIENT_ID,VITE_OAUTH_REDIRECT_BASE,VITE_CALENDLY_URL,VITE_STRIPE_PUBLISHABLE_KEY. - Branch hygiene note (process learning): PR #168 ended up bundling unrelated work — session expiration policy (the original scope of
feat/session-expiration-policy) plus dashboard CTA fixes plus welcome step-2 reshape. The mixed scope was deliberate (user wanted it on the same PR), but worth flagging for future PRs: if onboarding-UX work continues, branch it separately from auth/session work.