Customers no longer authenticate with passwords. A POST to the hub's
/portal/request-link mints a 24h customer-scoped JWT and sends it via
email + SMS; the /#/login Vue page sits on top of this and a navigation
guard hydrates the Pinia store from the token on arrival.
Why now: legacy customer passwords are unsalted MD5 from the old PHP
system. Migrating hashes to PBKDF2 would still require a forced reset
for every customer, so it's simpler to drop passwords entirely. The
earlier Authentik forwardAuth attempt was already disabled on
client.gigafibre.ca; this removes the last vestige of ERPNext's
password form from the customer-facing path.
Hub changes:
- services/targo-hub/lib/portal-auth.js (new) — POST /portal/request-link
• 3-requests / 15-min per identifier rate limit (in-memory Map + timer)
• Lookup by email (email_id + email_billing), customer id (legacy +
direct name), or phone (cell + tel_home)
• Anti-enumeration: always 200 OK with redacted contact hint
• Email template with CTA button + raw URL fallback; SMS short form
- services/targo-hub/server.js — mount the new /portal/* router
Client changes:
- apps/client/src/pages/LoginPage.vue (new) — standalone full-page,
single identifier input, success chips, rate-limit banner
- apps/client/src/api/auth-portal.js (new) — thin fetch wrapper
- apps/client/src/stores/customer.js — hydrateFromToken() sync decoder,
stripTokenFromUrl (history.replaceState), init() silent Authentik
fallback preserved for staff impersonation
- apps/client/src/router/index.js — PUBLIC_ROUTES allowlist + guard
that hydrates from URL token before redirecting
- apps/client/src/api/auth.js — logout() clears store + bounces to
/#/login (no more Authentik redirect); 401 in authFetch is warn-only
- apps/client/src/composables/useMagicToken.js — thin read-through to
the store (no more independent decoding)
- PaymentSuccess/Cancel/CardAdded pages — goToLogin() uses router,
not window.location to id.gigafibre.ca
Infra:
- apps/portal/traefik-client-portal.yml — block /login and
/update-password on client.gigafibre.ca, redirect to /#/login.
Any stale bookmark or external link lands on the Vue page, not
ERPNext's password form.
Docs:
- docs/roadmap.md — Phase 4 checkbox flipped; MD5 migration item retired
- docs/features/billing-payments.md — replace MD5 reset note with
magic-link explainer
Online appointment booking (Plan B from the same discussion) is queued
for a follow-up session; this commit is Plan A only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
183 lines
11 KiB
Markdown
183 lines
11 KiB
Markdown
# 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) | migrating → id.gigafibre.ca |
|
|
| Authentik SSO (clients) | [id.gigafibre.ca](https://id.gigafibre.ca) | Federated from auth.targo.ca |
|
|
| DocuSeal | [sign.gigafibre.ca](https://sign.gigafibre.ca) | Contract signing |
|
|
| n8n | [n8n.gigafibre.ca](https://n8n.gigafibre.ca) | Workflow automation |
|
|
| Oktopus | [oss.gigafibre.ca](https://oss.gigafibre.ca) | TR-369 CPE controller |
|
|
| GenieACS | internal `10.5.2.115:7557` | TR-069 NBI |
|
|
| 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
|