The ops tech module at /ops/#/j/* had drifted from the field app in two ways:
1. Scanner — a prior "restoration" re-added html5-qrcode, but the
design has always been native <input capture="environment"> → Gemini
2.5 Flash via targo-hub /vision/barcodes (up to 3 codes) and
/vision/equipment (structured labels, up to 5). Revert useScanner.js
+ ScanPage.vue + TechScanPage.vue to commit e50ea88 and drop
html5-qrcode from both package.json + lockfiles. No JS barcode
library, no camera stream, no polyfills.
2. Equipment UX — TechJobDetailPage.vue was a 186-line stub missing the
Ajouter bottom-sheet (Scanner / Rechercher / Créer), the debounced
SN-then-MAC search, the 5-field create dialog, Type + Priority
selects on the info card, and the location-detail contact expansion.
Port the full UX from apps/field/src/pages/JobDetailPage.vue (526
lines) into the ops module (458 lines after consolidation).
Rebuilt and deployed both apps. Remote smoke test confirms 0 bundles
reference html5-qrcode and the new TechJobDetailPage.1075b3b8.js chunk
(16.7 KB vs ~5 KB stub) ships the equipment bottom-sheet strings.
Docs:
- docs/features/tech-mobile.md — new. Documents all three delivery
surfaces (legacy SSR /t/{jwt}, transitional apps/field/, unified
/ops/#/j/*), Gemini-native scanner pipeline, equipment UX, magic-link
JWT, cutover plan. Replaces an earlier stub that incorrectly
referenced html5-qrcode.
- docs/features/dispatch.md — new. Dispatch board, scheduling, tags,
travel-time optimization, magic-link SMS, SSE updates.
- docs/features/customer-portal.md — new. Plan A passwordless magic-link
at portal.gigafibre.ca, Stripe self-service, file inventory.
- docs/architecture/module-interactions.md — new. One-page call graph
with sequence diagrams for the hot paths.
- docs/README.md — expanded module index (§2) now lists every deployed
surface with URL + primary doc + primary code locations (was missing
dispatch, tickets, équipe, rapports, telephony, network, agent-flows,
OCR, every customer-portal page). New cross-module edge map in §4.
- docs/features/README.md + docs/architecture/README.md — cross-link
all new docs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
19 KiB
Gigafibre FSM — Documentation
Start here. Pick a row by intent, jump to the module index when you need scope, or go straight to the cross-module map when you're chasing a call that hops surfaces.
Last refreshed: 2026-04-22 (expanded module index, added dispatch / customer portal / tech mobile docs, cross-interaction matrix)
1. Quick nav by intent
| I want to… | Open |
|---|---|
| See the plan — what's shipped, what's queued, with clickable links to every live module | roadmap.md |
| Understand the system end-to-end — services, containers, networks, SSO, Traefik routes | architecture/overview.md |
| See who calls who — one-page matrix of every module → module interaction | architecture/module-interactions.md |
| Build a new feature — UI patterns, folder layout, router conventions, Pinia, feature-sliced design | architecture/app-design.md |
| Touch ERPNext data — doctypes, customer → subscription → equipment → invoice, "Lead to Live" flow | architecture/data-model.md |
| Work on dispatch — drag-and-drop scheduling, tech assignment, travel-time optimization, magic-link SMS | features/dispatch.md |
| Work on the tech mobile app — scan-to-identify, equipment install, job status, JWT auth | features/tech-mobile.md |
| Work on the customer portal — passwordless magic-link, invoice + ticket self-service | features/customer-portal.md |
| Work on billing, Stripe, payments — subscription lifecycle, invoice OCR, payment reconciliation, PPA | features/billing-payments.md |
| Touch CPE / modems / ONTs — GenieACS, Oktopus, TR-069 → TR-369 migration, TP-Link XX230v diagnostics | features/cpe-management.md |
| Build or debug the scanner / OCR — Gemini vision pipeline, barcode/equipment/invoice endpoints, offline queue, AI_API_KEY rotation | features/vision-ocr.md |
| Work on agent flows / automation — Flow Template model, trigger wiring, step editor, runtime contract | features/flow-editor.md |
| Audit the wizard's SKU mapping vs legacy | reference/erpnext-item-diff.md |
| Inspect the legacy PHP wizard | reference/legacy-wizard/ |
| Read a historical status snapshot | archive/status-snapshots/ |
2. Module index
Every deployed surface, by app. Each row links to its primary doc and
names the exact code paths so you can grep from here.
2a. Ops SPA (apps/ops/) — https://erp.gigafibre.ca/ops/
Single pane of glass for internal teams. Quasar PWA (SPA mode in dev,
PWA mode in prod), Vue 3 + Pinia, hash router. Wrapped by Authentik via
Traefik forwardAuth on /ops/*. Bottom of the same app hosts the tech
mobile module on /j/* with magic-link auth.
| Module | URL | Purpose | Primary doc | Primary code |
|---|---|---|---|---|
| Dashboard | /ops/#/ |
KPIs (MRR, AR, active tickets), dispatch summary, live SSE feed | — | src/pages/DashboardPage.vue |
| Clients | /ops/#/clients · /clients/:id |
Customer 360: profile, subscriptions, invoices, equipment, tickets, communication timeline | — | src/pages/ClientsPage.vue · ClientDetailPage.vue · src/modules/clients/ |
| Dispatch | /ops/#/dispatch |
Drag-and-drop tech schedule, job board, travel-time optimization, SMS magic-link issuance | features/dispatch.md | src/pages/DispatchPage.vue · src/modules/dispatch/ |
| Tickets | /ops/#/tickets |
Support ticket board, SLA clock, linked equipment + jobs | — | src/pages/TicketsPage.vue · src/modules/tickets/ |
| Équipe | /ops/#/equipe |
Technician roster, skills/tags, availability, today's jobs | features/dispatch.md §6 | src/pages/EquipePage.vue · src/modules/equipe/ |
| Rapports | /ops/#/rapports + /revenus · /ventes · /taxes · /ar |
Revenue, sales, tax, AR reports (renders in-browser; PDF export via hub) | features/billing-payments.md §9 | src/pages/Rapports*.vue · src/modules/rapports/ |
| OCR | /ops/#/ocr |
Upload scanned supplier bills → Gemini parse → pre-fill Purchase Invoice | features/vision-ocr.md §4 | src/pages/OcrPage.vue |
| Settings | /ops/#/settings |
Feature flags, integration keys, user management (mirror of ERPNext) | — | src/pages/SettingsPage.vue |
| Telephony | /ops/#/telephony |
SIP click-to-dial (Twilio Voice SDK + sip.js fallback), call history | architecture/overview.md §3 | src/pages/TelephonyPage.vue |
| Agent Flows | /ops/#/agent-flows |
Visual editor for Flow Template (automation runtime) | features/flow-editor.md | src/pages/AgentFlowsPage.vue |
| Network | /ops/#/network |
Cytoscape-rendered OLT/ONT topology, live link status from GenieACS | features/cpe-management.md | src/pages/NetworkPage.vue |
2b. Ops tech module (apps/ops/src/modules/tech/) — https://erp.gigafibre.ca/ops/#/j/*
Same SPA, different mount. Techs hit a magic-link SMS, land on /j/:token,
the token redirects to /j with JWT in localStorage. Mobile-first layout
with bottom tab bar.
| Route | Purpose | Primary doc | Primary code |
|---|---|---|---|
/j |
Today's jobs, grouped by status | features/tech-mobile.md §4a | TechTasksPage.vue |
/j/job/:name |
Job detail + equipment management (Ajouter/Scanner/Rechercher/Créer) | features/tech-mobile.md §5 | TechJobDetailPage.vue |
/j/scan |
Standalone scanner (native camera → Gemini) | features/tech-mobile.md §3 | TechScanPage.vue |
/j/device/:serial |
Per-device detail, diagnostic shortcut | — | TechDevicePage.vue |
/j/diagnostic |
In-browser speed test + GenieACS probe | features/cpe-management.md | TechDiagnosticPage.vue |
/j/more |
Settings, token expiry, logout | — | TechMorePage.vue |
/j/:token |
Magic-link handler (last route, accepts any JWT) | features/tech-mobile.md §2 | TechTasksPage.vue (same component, different entry) |
2c. Field PWA (apps/field/) — https://erp.gigafibre.ca/field/
Transitional standalone PWA, retiring. Authentik-protected; byte-for-byte closer to the legacy workflow techs had before the Ops tech module existed. No magic-link — tech logs in via Authentik. Kept alive while the SMS link still points at the hub SSR page (see tech-mobile doc §1).
Same page set as §2b (TasksPage, ScanPage, JobDetailPage, DevicePage,
DiagnosticPage, MorePage), same Gemini-native scanner composable.
apps/field/src/pages/JobDetailPage.vue is the reference implementation
we port from when the Ops tech module drifts.
2d. Customer portal (apps/client/) — https://portal.gigafibre.ca/
Passwordless self-service. Standalone Quasar PWA served by a dedicated
nginx container (client-portal) bind-mounted from /opt/client-app/ on
the Proxmox VM. No Authentik — customers get a magic-link email (HS256
JWT, 24h TTL).
| Module | URL | Purpose | Primary doc | Primary code |
|---|---|---|---|---|
| Login | /#/login |
Email entry → magic-link email send | features/customer-portal.md §3 | src/pages/LoginPage.vue |
| Dashboard | /#/ |
Balance, next invoice, active tickets, recent activity | features/customer-portal.md §4a | DashboardPage.vue |
| Account | /#/account |
Profile, saved payment methods (Stripe PM), address book | features/billing-payments.md §6 | AccountPage.vue |
| Catalog / Cart | /#/catalog · /#/cart |
Shop add-ons (extra mesh, static IP), add to Stripe Checkout | features/billing-payments.md | CatalogPage.vue · CartPage.vue |
| Invoices | /#/invoices · /#/invoices/:name |
List + PDF of all Sales Invoices, Stripe-linked pay button | features/billing-payments.md §8 | InvoicesPage.vue · InvoiceDetailPage.vue |
| Tickets | /#/tickets · /#/tickets/:name |
Create support ticket, reply thread, attach photos | — | TicketsPage.vue · TicketDetailPage.vue |
| Messages | /#/messages |
Unified comm thread (SMS + email) with support | — | MessagesPage.vue |
| Payment flows | /#/payment-success · /payment-cancel · /payment-card-added · /order-success |
Stripe return URL landings | features/billing-payments.md §7 | Payment*.vue · OrderSuccessPage.vue |
2e. Legacy portal (apps/portal/) — retired 2026-04-22
Old ERPNext-embedded customer portal. Host client.gigafibre.ca now 307s
to portal.gigafibre.ca/* via Traefik; see
apps/portal/traefik-client-portal.yml. Codebase retained as historical
reference only. Do not build.
2f. Marketing site (apps/website/) — https://www.gigafibre.ca/
React + Vite marketing site. Self-contained, no ERPNext dependency, no docs beyond its own README.
3. Services (backends)
Everything in services/* is backend infrastructure. Usually you don't
edit these unless you're adding a new endpoint.
| Service | Port | Role | Primary docs |
|---|---|---|---|
services/targo-hub/ |
msg.gigafibre.ca:3300 |
API gateway. Vision (Gemini), magic-link JWT, Twilio SMS, SSE fanout, Stripe webhooks, ACS proxy, Legacy-DB read proxy, tech-mobile SSR | overview.md §3 · vision-ocr.md · customer-portal.md · tech-mobile.md · billing-payments.md |
services/modem-bridge/ |
:3301 (internal) |
Playwright + Chromium wrapper that logs into TP-Link XX230v modems and reads encrypted TR-181 data | cpe-management.md |
services/docuseal/ |
docs.gigafibre.ca:3000 |
Contract signing for commercial quotes + residential service agreements | flow-editor.md §5 (briefly) |
services/legacy-db/ |
:3305 (internal) |
Read-only proxy over the retired MariaDB for lookups that haven't migrated | architecture/overview.md |
ERPNext (erp.gigafibre.ca) is not under services/ — it's a standard
Frappe-Bench install on the VM. See
architecture/data-model.md for the doctype
catalog.
4. Cross-module interactions (one-page map)
Full matrix + sequence diagrams in architecture/module-interactions.md. The summary below is just the high-traffic edges.
┌───────────────────────────────────────┐
│ ERPNext (source of truth) │
│ Customer · Subscription · │
│ Equipment · Dispatch Job · │
│ Sales Invoice · Ticket │
└──┬──────────────┬──────────┬──────────┘
│ │ │
REST+token │ REST+token │ REST+token
│ │ │
┌────────────▼──┐ ┌───────▼────────┐ │
│ targo-hub │ │ Ops SPA │ │
│ (gateway) │◄──┤ apps/ops/ │ │
│ │ └────┬───────────┘ │
│ /vision/* │ │ │
│ /magic-link/* │ │ bundles │
│ /sse │ │ tech module │
│ /sms │ │ at /j/* │
│ /stripe/* │ │ │
│ /acs/* │ └─────────────┘
│ /t/{token} │ │
└──┬──────┬─────┘ │
│ │ │
SMS │ │ email (magic link) │
/SSE │ │ │
▼ ▼ ▼
┌─────────────────┐ ┌────────────────────────┐
│ Tech mobile │ │ Customer portal │
│ (SSR OR Vue) │ │ apps/client/ │
│ /t or /ops/#/j/ │ │ portal.gigafibre.ca │
└─────────────────┘ └────────────────────────┘
Highest-traffic edges (read these docs first if you're chasing one):
| From | To | Via | Where it's documented |
|---|---|---|---|
| Dispatch (Ops) | Tech mobile | Magic-link SMS → hub/magic-link.js → Twilio | dispatch.md §5 + tech-mobile.md §2 |
| Tech mobile scanner | Gemini | POST hub /vision/barcodes + /vision/equipment |
vision-ocr.md §2 + tech-mobile.md §3 |
| Ops OCR page | Gemini | POST hub /vision/invoice |
vision-ocr.md §3 |
| Customer portal | ERPNext | Authenticated via customer JWT → hub proxies /api/resource/* |
customer-portal.md §6 |
| Stripe | ERPNext | Webhook → hub /stripe/webhook → creates Payment Entry |
billing-payments.md §7 |
| Ops dispatch | SSE live updates | hub /sse (tech status, job flip, ETA) |
dispatch.md §4 |
| Agent-flows | Any module | Runtime in hub → triggers any ERPNext op via service token | flow-editor.md §6 |
| GenieACS | Modem-bridge | hub /acs/probe → modem-bridge for TP-Link deep params |
cpe-management.md §4 |
5. Folder map
docs/
├── README.md ← you are here
├── roadmap.md ← phase tracker + live module URLs
│
├── architecture/ ← the system itself
│ ├── overview.md (services, Docker, Traefik, SSO, retirement plan)
│ ├── data-model.md (ERPNext doctypes + "Lead to Live")
│ ├── app-design.md (Vue/Quasar patterns, feature-sliced layout)
│ └── module-interactions.md (full call graph + sequence diagrams)
│
├── features/ ← one doc per business capability
│ ├── README.md (per-doc index)
│ ├── dispatch.md (Ops dispatch board, scheduling, tags, SMS)
│ ├── tech-mobile.md (Gemini-native scanner, equipment UX, JWT)
│ ├── customer-portal.md (Plan A magic-link, Stripe self-service)
│ ├── billing-payments.md (Stripe, invoices, subscriptions, PPA)
│ ├── cpe-management.md (GenieACS, Oktopus, XX230v, modem-bridge)
│ ├── vision-ocr.md (Gemini, scan pipeline, offline queue, keys)
│ └── flow-editor.md (Flow Template, triggers, runtime)
│
├── reference/ ← lookup material
│ ├── erpnext-item-diff.md (new SKUs vs legacy gestionclient)
│ └── legacy-wizard/ (read-only snapshot of the PHP wizard)
│
├── assets/ ← PPTX decks, screenshots, generated diagrams
│
└── archive/ ← frozen docs, do not edit
├── HANDOFF-2026-04-18.md
├── MIGRATION.md
├── LEGACY-ACCOUNTING-ANALYSIS.md
└── status-snapshots/ (dated session reports)
6. Conventions
- Edit in place. Don't copy-paste a section into a new file — link to it instead.
- Module index = source of truth for URLs. If you change a route or a
deployed host, update §2 of this file and the relevant feature doc.
grep -r "erp.gigafibre.ca" docs/should not return stale hostnames. - Cross-doc links use repo-relative paths, e.g.
[features/dispatch.md](features/dispatch.md)— sogit mving a doc surfaces every incoming link. - Code comments that reference a doc use the full repo-relative path,
e.g.
// See docs/features/vision-ocr.md §10— sogrep docs/still surfaces them if we reorganize again. - Dated snapshots go to
archive/status-snapshots/. Don't createSTATUS_YYYY-MM-DD.mdat the root anymore. - The root
README.md(one level up) is the repo introduction for non-technical readers;docs/README.md(this file) is the engineering index.
7. What changed on 2026-04-22
Big reorganization:
- New feature docs added:
dispatch.md,customer-portal.md,tech-mobile.md. The first was missing entirely despite being the most-used surface in Ops; the second codifies the Plan A magic-link cutover; the third replaces a staletech-mobile.mdthat incorrectly referencedhtml5-qrcode(never shipped — scanner has always been native camera + Gemini). - New architecture doc added:
module-interactions.md— the one-page call graph with sequence diagrams for the hot paths (dispatch → SMS → tech scan → equipment install). - Module index (§2 above) now lists every deployed surface, not just the three that had feature docs. Dispatch, Tickets, Équipe, Rapports, Telephony, Network, Agent Flows, OCR, and every customer-portal page now have a named row.
- Customer portal topology clarified.
portal.gigafibre.cais the live SPA;client.gigafibre.ca307s to portal. The legacyapps/portal/tree is retained as historical reference only. - Earlier flattening (still in effect): docs were flattened out of a
single folder into
architecture/,features/,reference/,archive/. Every file move usedgit mvsogit log --followstill works. The old paths (docs/ARCHITECTURE.md,docs/VISION_AND_OCR.md, etc.) no longer exist — if you land on one of those links from an external bookmark, use §1 above to find the new location. Legacy references remain only insidearchive/HANDOFF-2026-04-18.mdandarchive/status-snapshots/*.md, where they're preserved as a frozen historical record.