Local β Dev β Test β Prod Β· Sandbox = parallel Zift/payment testing enclave (not a promotion step). "On Dev" β shipped. Β· All items out-of-band (root iteration, no sprint).Four ways in, one experience out. The app-invite β install β activate tail is entry-point-agnostic β it fires on the contact-group flip that every purchase path hits (#29915), so a buyer gets the same app onboarding no matter which door they came through.
Doors β β‘β’ are self-serve (buyer's phone β capture + FPT Pay embed). β£ manual join enters at Trust-checkout. All four converge on the app-invite tail. QR = same hosted widget, just a location-scoped URL on a poster/front-desk card β near-zero backend.
EPIC: New-Lead β Client "Super Onboarding" experience
Validated token + lead + journey β contact + subscription + charge. The highest-risk, highest-proof piece β mostly reuse.
billing/checkout/purchase-verified β extract shared pipeline from ZiftCheckoutFunction, minus the server-side re-verify MONO public-fpt-functions~1 helper + ~10-line endpoint (see build spec Β§I)ValidatedPaymentMethod β AccountVerificationResponse mapper (Token / ExtendedAccountType / AccountAccessory) MONO~10 lines β FunnelService.Checkout stays unchanged[pay].EmbedConfig table β publishable key β LocationId + gym's Zift account (replace the in-memory demo map) PAYDBmakes verify + charge hit the SAME merchant account/api/verify β ValidatedPaymentMethod) PAYfeature/saq-hardening Β· proven on dev + Zift sandbox this weekFunnelService.Checkout β contact + subscription + charge MONOFpt.Standard/Services/FunnelService.cs β reused as-isPublic calendar β slide-out (desktop) / inline (mobile) signup, gym-skinned, embeddable on the gym's own site.
verify() β trust-checkout endpoint PUBiframe-resizer license decision (v4 MIT / v5 commercial / homegrown) PUB/api/public/locationsSessions) MONOPUBreused as-isThe one genuinely new capability β auto-reserve the clicked class after a successful checkout.
Christian's design (2026-07 Slack, confirmed): a new journey type = lead capture + booking + checkout in the existing New-Journey modal. The gym's session + offer selections live in the journey (step Payload JSON β same pattern as the #29915 invite toggle, no schema change), and the journey generates the widget link. Verified in code: the public calendar has NO visibility flag today (usp_getClassesByDates returns every session) β journey-scoped selection avoids touching it entirely, and gives multi-widget-per-gym for free.
After the sale: get the member into the app, passwordless. Detailed in the Build Spec.
mobile.fitprotracker.com migration β config flip + redirects + email templates (Phase 0) MONOPUBSPAfully spec'd in iliv-fit-migration Β§AβF/kiosk/registrationClass route-parity / redirect on the new domain PUBThe payment foundation everything above rests on. Its own track β the enclave that Feature 1/2 consume.
Feature 1 core. Point the mock's PAY&BOOK at verify() β trust-checkout β a real dev contact + subscription + app-invite lands in app.fitprotracker-dev.com. This is where it becomes real.
Feature 4: new journey type in the existing New-Journey modal β pick sessions β pick sellable offers β journey generates the widget link (Christian's design). Selections in journey Payload JSON, filter enforced server-side. Prereq for any real calendar β gyms must control what publishes.
Features 2+3 β the widget is one embed script with three hosts: a NEW route on the public site (existing /sessions/calendar untouched β true side-by-side), the gym's own website (snippet), and the QR target. New route = thin host page for the same script gyms will paste β dogfoods the embed first. Auto-reserve the clicked class post-checkout. Landing pages / journey checkout not touched at all. β PILOT with one gym; old calendar's Join button retires only after the new route wins.
Feature 5 β with the calendar no longer pointing at iliv.fit, run the iliv.fitβmobile migration + SMS-OTP activation / OTP-login. (Note: register/reset/waiver links also ride ClientAppDomain β calendar unblocks but doesn't finish this.)
Promote #29915 auto-invite DevβTestβProd (built + verified, purely pipeline) Β· SAQ iframe on the existing checkout (Feature 6) Β· both improve production while the core is under construction.
| Level | Item | Iteration | Action |
|---|---|---|---|
| Epic | New-Lead β Client "Super-Onboarding" (umbrella) | root FitProTracker Β· out-of-band | β create (owner: Antonio) β like Epics #28623 / #29816 which already sit at root |
| PBI | #29915 Β· Auto app-invite (on Dev only) | unchanged | π re-parent under the Epic β parent + iteration are independent; keeps Committed state |
| PBI | SAQ / FPT Pay enclave (Feature 6) | root Β· out-of-band | β create (branch-only today β no item exists) |
| PBI | Trust-checkout endpoint + embed wiring (Slice 1 / Features 1β2) | root Β· out-of-band | β create when Slice 1 starts |
| PBI | Booking / admin-builder / hand-off (Features 3β5) | root Β· out-of-band | β³ cut per-slice later, not now |
Out-of-band = Iteration Path stays at root FitProTracker, never β¦\Sprint N. Antonio (CEO/dev) runs this off the sprint cadence to stay nimble; progress is tracked by environment promotion (DevβTestβProd), not sprint burndown.
| ID | Type Β· State | Title | Sprint Β· Owner | Relation to this epic |
|---|---|---|---|---|
| #29915 | PBI Β· Committed Β· Dev only | Auto-send booking-app invite on membership start (+ simplify invite email) | Antonio Β· parentless | β is Feature 1's auto-invite β re-parent under the Epic; on Dev, not yet Prod |
| #29928 | Bug Β· Committed | Booking App β "Sync Email" fails (email-mismatch) | 146 Β· Jennilyn | expected fixed in prod well before this epic β no action |
| #29715 / #29499 | Task/PBI Β· Done | Sessions_CTE perf rewrite | 144 Β· Christian | β NOT our spine β admin margin grid, different from the public calendar |
| β | none found | SAQ / FPT Pay hardening | β | β no work item β tracked only as feature/saq-hardening; needs its own Epic/PBI |
Repo (in C:\FPT\client-onboarding\) | Branch | Carries |
|---|---|---|
| FitProTracker (monolith) | feature/client-onboarding Β· +2 | #29915 auto-app-invite (both commits cherry-picked; also on Dev via PR 23629) |
| FitProTracker.Public | feature/client-onboarding Β· +2 | FPT Pay iframe checkout (SAQ F-1/F-2) cherry-picked from saq branch; widget work lands here |
| FitProTracker.Front-Office | feature/client-onboarding Β· +2 | #29915 location + per-journey toggles (cherry-picked; also on dev via PR 23630) |
| FitProTracker.Mobile | feature/client-onboarding Β· =main | fresh (was 21 behind β pulled current); SMS-OTP / Feature 5 work lands here |
| FitProTracker.Pay | feature/client-onboarding Β· +8 | full FPT Pay enclave incl. the 5 previously-uncommitted files (now committed + pushed to saq branch too) |
Old branches (feature/saq-hardening, feature/sprint145/29915-*, feature/new-lead-signup-embed) stay on origin as history. C:\FPT\saq-hardening\ is safe to retire β verified nothing in the new container worktree-depends on it (monolith/Front-Office parent into the primary C:\FPT\ clones). Move its loose SAQ/FPT-Pages HTML artifacts out before deleting.
FitProTracker (out-of-band β never a sprint), and parent = the umbrella Epic. No placeholders.origin/main; the SAQ enclave work stays on feature/saq-hardening.