# Gigafibre FSM — Roadmap

> Live phase tracker. For onboarding or architecture context see
> [README.md](README.md). Historical status snapshots live under
> [archive/status-snapshots/](archive/status-snapshots/).

**Last refreshed:** 2026-04-22

---

## Modules in production — quick links

Everything in this table is reachable from a browser today (Authentik
SSO for staff surfaces, Stripe Checkout for customer ones).

### Ops app — `https://erp.gigafibre.ca/ops/`

| Module | URL | Purpose |
|---|---|---|
| Dashboard | [/ops/#/](https://erp.gigafibre.ca/ops/#/) | Home |
| Clients | [/ops/#/clients](https://erp.gigafibre.ca/ops/#/clients) | Customer list + detail |
| Dispatch | [/ops/#/dispatch](https://erp.gigafibre.ca/ops/#/dispatch) | Timeline, drag-drop, map |
| Tickets | [/ops/#/tickets](https://erp.gigafibre.ca/ops/#/tickets) | Issue management |
| Équipe | [/ops/#/equipe](https://erp.gigafibre.ca/ops/#/equipe) | Technician directory |
| Rapports | [/ops/#/rapports](https://erp.gigafibre.ca/ops/#/rapports) | Revenu / Ventes / Taxes / AR |
| OCR | [/ops/#/ocr](https://erp.gigafibre.ca/ops/#/ocr) | Invoice OCR (Gemini) |
| Téléphonie | [/ops/#/telephony](https://erp.gigafibre.ca/ops/#/telephony) | PBX + SIP |
| Agent flows | [/ops/#/agent-flows](https://erp.gigafibre.ca/ops/#/agent-flows) | Flow editor |
| Réseau | [/ops/#/network](https://erp.gigafibre.ca/ops/#/network) | GenieACS / OLT / TR-069 |
| Settings | [/ops/#/settings](https://erp.gigafibre.ca/ops/#/settings) | Config |

### Tech mobile (same app, mobile layout) — `/j/*`

| Page | URL | Purpose |
|---|---|---|
| Tasks | [/ops/#/j](https://erp.gigafibre.ca/ops/#/j) | Tech's assigned jobs |
| Scan | [/ops/#/j/scan](https://erp.gigafibre.ca/ops/#/j/scan) | Camera scanner, auto-link |
| Device | `/ops/#/j/device/:serial` | Equipment detail + relationships |
| Diagnostic | [/ops/#/j/diagnostic](https://erp.gigafibre.ca/ops/#/j/diagnostic) | ONT/OLT/SNMP probe |

### Customer portal — `https://portal.gigafibre.ca`

| Page | URL | Purpose |
|---|---|---|
| Dashboard | [/](https://portal.gigafibre.ca) | Balance + quick actions |
| Account | [/#/me](https://portal.gigafibre.ca/#/me) | Profile + cards (Stripe Billing Portal) |
| Invoices | [/#/invoices](https://portal.gigafibre.ca/#/invoices) | History + pay (Stripe Checkout + Klarna) |
| Tickets | [/#/tickets](https://portal.gigafibre.ca/#/tickets) | Open tickets |
| Messages | [/#/messages](https://portal.gigafibre.ca/#/messages) | SMS / email thread with support |
| Catalog | [/#/catalog](https://portal.gigafibre.ca/#/catalog) | Add-on purchases |

### Admin surfaces (non-ops)

| Service | URL | Stack |
|---|---|---|
| ERPNext | [erp.gigafibre.ca](https://erp.gigafibre.ca) | Frappe v16 / PostgreSQL |
| Authentik SSO (staff) | [auth.targo.ca](https://auth.targo.ca) | OAuth provider for ERPNext + ForwardAuth for ops/n8n/Gitea |
| Authentik SSO (clients) | [id.gigafibre.ca](https://id.gigafibre.ca) | Customer portal — separate instance, not federated |
| DocuSeal | [sign.gigafibre.ca](https://sign.gigafibre.ca) | Contract signing |
| n8n | [n8n.gigafibre.ca](https://n8n.gigafibre.ca) | Workflow automation |
| GenieACS | internal `10.5.2.115:7557` | TR-069 NBI — sole CPE controller (Oktopus decommissioned May 2026) |
| Traccar | [tracker.targointernet.com](https://tracker.targointernet.com) | GPS tracking |
| Website | [www.gigafibre.ca](https://www.gigafibre.ca) | Marketing + address lookup |

---

## Phase 1 — Foundation (Done, March 2026)
- [x] ERPNext v16 + PostgreSQL
- [x] Custom FSM doctypes (Service Location, Equipment, Subscription) → see [architecture/data-model.md](architecture/data-model.md)
- [x] Dispatch doctypes (Job, Technician, Tag with skill levels)
- [x] Dispatch PWA with timeline, drag-drop, Mapbox map → [/ops/#/dispatch](https://erp.gigafibre.ca/ops/#/dispatch)
- [x] GPS tracking (Traccar hybrid REST + WebSocket)
- [x] Authentik SSO (forwardAuth)
- [x] ERPNext API proxy (nginx same-origin)
- [x] Legacy migration (6,667 customers, 21K subs, 115K invoices, 242K tickets)

## Phase 2 — Ops App (Done, March 2026)
- [x] Unified ops PWA → [erp.gigafibre.ca/ops/](https://erp.gigafibre.ca/ops/)
- [x] Client list/detail with inline editing → [/ops/#/clients](https://erp.gigafibre.ca/ops/#/clients)
- [x] Dispatch module + ticket management → [/ops/#/dispatch](https://erp.gigafibre.ca/ops/#/dispatch), [/ops/#/tickets](https://erp.gigafibre.ca/ops/#/tickets)
- [x] Equipment tracking with OLT/SNMP diagnostics → [/ops/#/network](https://erp.gigafibre.ca/ops/#/network)
- [x] SMS/Email notifications (Twilio + Mailjet)
- [x] Invoice OCR — migrated from Ollama Vision to Gemini 2.5 Flash via targo-hub (2026-04-22, no GPU on ops VM). See [features/vision-ocr.md](features/vision-ocr.md) → [/ops/#/ocr](https://erp.gigafibre.ca/ops/#/ocr)
- [x] Field tech mobile → [/ops/#/j](https://erp.gigafibre.ca/ops/#/j) (unified into ops app, see Phase 2.7)
- [x] Authentik federation (staff → client SSO)
- [x] Modem-bridge (Playwright headless for TP-Link ONU diagnostics)
- [x] WiFi diagnostic panel (mesh topology, client signal, packet loss)

## Phase 2.5 — Remote Architecture Transition (In Progress)
- [x] Deprecate local `frappe_docker` development dependencies
- [x] Consolidate architecture and ecosystem documentation (this reorg, 2026-04-22)
- [ ] Decouple API/Auth (Token-based auth instead of session for frontend apps)
- [ ] Set up dev proxy (Vite) to bridge local env to remote ERPNext API (bypassing CORS)
- [ ] Establish secure PostgreSQL tunnel for `infra-map-vue` development
- [ ] **Sandboxed outbound comms** (required before any scheduler/webhook/Twilio/Mailjet E2E test) — prevents test runs from reaching real customers while legacy still bills
- [ ] Subscription → Sales Invoice scheduler: keep `pause_scheduler=1` until cutover event. Legacy PHP is authoritative until then.

## Phase 2.6 — Quotation + DocuSeal (Shipped 2026-04-18)
- [x] DocuSeal container → [sign.gigafibre.ca](https://sign.gigafibre.ca)
- [x] Hub routes: `/accept/generate`, `/accept/docuseal-webhook`, `/accept/confirm`
- [x] Quotation custom fields: `custom_docuseal_signing_url`, `custom_docuseal_envelope_id`, `custom_quote_type`
- [x] Billing Frequency Custom Field on Item + Quotation/Sales Invoice/Sales Order Item (fetch_from item_code)
- [x] Print Format "Soumission TARGO" with split Recurring / One-time sections and QR → signing URL
- [x] Wizard flow: ProjectWizard → `/accept/generate` → DocuSeal submission → signed webhook → `acceptQuotation()`
- [ ] Register DocuSeal webhook in UI (Settings → Webhooks, `form.completed` → hub endpoint) — **manual**
- [ ] First end-to-end signed acceptance on a real customer quote

## Phase 2.7 — Field ↔ Ops unification at /j (In Progress, started 2026-04-22)

Collapse `apps/field` into `apps/ops/src/modules/tech` so there is one
PWA, one deploy, one auth surface. See [features/vision-ocr.md](features/vision-ocr.md)
for the scan pipeline this depends on.

**Step 1 — scan + device (Shipped 2026-04-22, commit `e50ea88`)**
- [x] Invoice OCR on Gemini 2.5 Flash via hub `/vision/invoice` — ops VM no longer needs a GPU
- [x] Ollama proxy blocks removed from ops + field nginx configs
- [x] Offline store (`apps/ops/src/stores/offline.js`) — mutation queue + vision queue, time-driven retries, idb-keyval persistence
- [x] Unified scanner composable (`useScanner.js`) with Mode A (barcodes, 8s timeout + queue) and Mode B (equipment label, sync)
- [x] TechScanPage → [/ops/#/j/scan](https://erp.gigafibre.ca/ops/#/j/scan) — camera, 3-tier lookup (serial → barcode → MAC), auto-link to Dispatch Job context, create/link dialogs
- [x] TechDevicePage at `/j/device/:serial` — 7 cards surfacing full ERPNext relationship graph (Equipment, Customer, Location, Subscription, Issues, Dispatch Jobs, OLT)
- [x] Documentation: [features/vision-ocr.md](features/vision-ocr.md) (pipeline, §10 relationship graph, §8.1 secrets/rotation)

**Step 2 — PWA hardening**
- [ ] Quasar service worker runtime caching scoped to `/j/*` (stale-while-revalidate for reads, network-first for mutations)
- [ ] Precache the tech route manifest so a cold install with no signal still boots `/j/`

**Step 3 — Auth unification**
- [ ] Collapse logout URL to `id.gigafibre.ca` (currently ops points to `auth.targo.ca`)
- [ ] Decide whether `/j/*` stays behind Authentik forwardAuth or moves to magic-link only

**Step 4 — Magic-link tech access**
- [ ] Traefik skip Authentik on `/j/{jwt-token}` route
- [ ] targo-hub `/otp/tech-link` — mint short-lived JWT bound to technician + job
- [ ] JWT validation in TechTasksPage → populate tech context without an SSO session
- [ ] SMS delivery of the link (reuse existing Twilio path)

**Step 5 — Flow runtime integration**
- [ ] Wire `flow-runtime` to persist pending steps through `offline.queue` so a tech mid-flow survives a dead zone
- [ ] Surface queued flow state in TechTasksPage ("3 actions en attente de sync")

**Step 6 — Remove apps/field**
- [ ] `git rm -r apps/field` once `/j/*` has parity and has run in production for ≥2 weeks
- [ ] Remove field build + deploy from CI
- [ ] Redirect `*.field.gigafibre.ca` (if any) → `erp.gigafibre.ca/ops/#/j/`
- [ ] Update [architecture/overview.md](architecture/overview.md) service table (drop field row)

## Phase 3 — Workflows & Automation (In Progress)
- [ ] Tag technicians with skills (46 techs to tag) → [/ops/#/equipe](https://erp.gigafibre.ca/ops/#/equipe)
- [ ] Wire auto-dispatch (cost-optimization matching)
- [ ] Issue → Dispatch Job creation (triggered from [/ops/#/tickets](https://erp.gigafibre.ca/ops/#/tickets))
- [ ] Job completion → equipment status + close ticket
- [ ] Equipment swap → inventory log
- [x] Flow editor (v1 shipped) → [/ops/#/agent-flows](https://erp.gigafibre.ca/ops/#/agent-flows) — see [features/flow-editor.md](features/flow-editor.md)
- [ ] n8n escalation workflows → [n8n.gigafibre.ca](https://n8n.gigafibre.ca)
- [ ] Twilio 10DLC production upgrade
- [ ] SLA tracking

## Phase 4 — Customer Portal (Largely Shipped)

Portal Vue SPA lives at [portal.gigafibre.ca](https://portal.gigafibre.ca).
All 16 `/payments/*` hub endpoints ship; see
[features/billing-payments.md](features/billing-payments.md) for the full flow.

- [x] Self-service app → [portal.gigafibre.ca](https://portal.gigafibre.ca) (13 pages: Dashboard, Invoices, Account, Tickets, Messages, Catalog, Cart, …)
- [x] Stripe payments → pay-balance, pay-invoice, save-card, Billing Portal, refund, PPA auto-pay cron (daily 06:00 EST). Klarna BNPL supported on invoice payments.
- [x] Webhook handler with signature verification (5-min tolerance) → `/webhook/stripe`
- [x] Payment links via SMS + email (`/payments/send-link`)
- [x] Magic-link redirect after Stripe return (`/payments/return` → portal)
- [x] Passwordless portal login (`POST /portal/request-link`, email/SMS, 3/15min rate-limited, anti-enumeration) — ERPNext `/login` retired on `client.gigafibre.ca` (Traefik redirect → `/#/login`). MD5 migration moot.
- [ ] Online appointment booking
- [ ] Real-time tech tracking SMS
- [ ] QR code on modem → subscriber dashboard (`msg.gigafibre.ca/q/{mac}`)

## Phase 5 — Advanced Features
- [ ] Van stock inventory per tech
- [ ] Revenue analytics (MRR, churn, ARPU) → extend [/ops/#/rapports](https://erp.gigafibre.ca/ops/#/rapports)
- [ ] Proactive monitoring (auto-ticketing)
- [ ] Online checkout (e-commerce signup via [www.gigafibre.ca](https://www.gigafibre.ca))
- [ ] Marketing segmentation + campaigns
- [ ] Tech performance dashboards
- [ ] Preventive maintenance scheduling
