Backend services: - targo-hub: extract deepGetValue to helpers.js, DRY disconnect reasons lookup map, compact CAPABILITIES, consolidate vision.js prompts/schemas, extract dispatch scoring weights, trim section dividers across 9 files - modem-bridge: extract getSession() helper (6 occurrences), resetIdleTimer(), consolidate DM query factory, fix duplicate username fill bug, trim headers (server.js -36%, tplink-session.js -47%, docker-compose.yml -57%) Frontend: - useWifiDiagnostic: extract THRESHOLDS const, split processDiagnostic into 6 focused helpers (processOnlineStatus, processWanIPs, processRadios, processMeshNodes, processClients, checkRadioIssues) - EquipmentDetail: merge duplicate ROLE_LABELS, remove verbose comments Documentation (17 → 13 files, -1,400 lines): - New consolidated README.md (architecture, services, dependencies, auth) - Merge ECOSYSTEM-OVERVIEW into ARCHITECTURE.md - Merge MIGRATION-PLAN + ARCHITECTURE-COMPARE + FIELD-GAP + CHANGELOG → MIGRATION.md - Merge COMPETITIVE-ANALYSIS into PLATFORM-STRATEGY.md - Update ROADMAP.md with current phase status - Delete CONTEXT.md (absorbed into README) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 KiB
Gigafibre FSM -- Architecture
1. Service Map
┌──────────────────┐
│ Authentik SSO │
│ auth.targo.ca │
└────────┬─────────┘
│ forwardAuth
▼
┌──────────────────┐
│ Traefik │
│ :80 / :443 │
│ Let's Encrypt │
└──┬───┬───┬───┬───┘
┌──────────────────┘ │ │ └───────────────────┐
▼ ▼ ▼ ▼
┌────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Ops App │ │ ERPNext v16 │ │ targo-hub │
│ /ops/ (nginx) │ │ erp.gigafibre.ca│ │ msg.gigafibre.ca│
└───────┬────────┘ └───────┬──────────┘ └──┬───┬───┬──────┘
│ /api/* proxy │ │ │ │
│ (token injected) │ │ │ │
└───────────────────┘ │ │ │
│ │ │
┌────────────────────────────────────┘ │ └──────┐
▼ ▼ ▼
┌──────────────────┐ ┌────────────────┐ ┌─────────┐
│ GenieACS NBI │ │ Twilio API │ │ Stripe │
│ 10.5.2.115:7557 │ │ SMS + Voice │ │ Payments│
└───────┬──────────┘ └────────────────┘ └─────────┘
│ CWMP (TR-069)
▼
┌──────────────────┐ ┌──────────────────┐
│ CPE / ONT │◀──────│ modem-bridge │
│ TP-Link XX230v │ HTTPS │ :3301 (internal)│
│ Raisecom HT803G │ │ Playwright │
└──────────────────┘ └──────────────────┘
Docker networks: proxy (Traefik-facing services), erpnext (ERPNext cluster + targo-hub).
2. Docker Containers
Host: 96.125.196.67 (Proxmox VM, Ubuntu 24.04). All services on one Docker host.
| Container | Image | Port | Network | Purpose |
|---|---|---|---|---|
| ops-frontend | nginx:alpine | 80 | proxy | Ops SPA + ERPNext API proxy |
| targo-hub | node:20-alpine | 3300 | proxy, erpnext | API gateway: SSE, SMS, devices, dispatch |
| erpnext-frontend-1 | frappe/erpnext | 8080 | erpnext | ERPNext web + API |
| erpnext-backend | frappe/erpnext | 8000 | erpnext | Frappe worker |
| erpnext-db-1 | postgres:16 | 5432 | erpnext | ERPNext + targo_cache DBs |
| modem-bridge | node:20-slim+Chromium | 3301 | proxy | Headless browser for ONU web GUI |
| oktopus-acs-1 | oktopusp/acs | 9292 | oktopus | USP/TR-369 controller |
| oktopus-mongo-1 | mongo:7 | 27017 | oktopus | Oktopus datastore |
| fn-routr | fonoster/routr-one | -- | fonoster | VoIP SIP routing |
| fn-asterisk | fonoster/asterisk | -- | fonoster | PBX media server |
| fn-postgres | postgres:16 | -- | fonoster | Fonoster DB |
| authentik-* | goauthentik | -- | authentik | SSO provider (staff + client) |
| apps-www-gigafibre-1 | nginx | -- | proxy | Marketing website |
3. Ops App (Quasar v2 / Vue 3 / Vite)
Served from /opt/ops-app/ via ops-frontend nginx at erp.gigafibre.ca/ops/.
Directory Structure
| Directory | Files | Content |
|---|---|---|
api/ |
10 | ERPNext CRUD, dispatch, offers, presets, SMS, traccar, OCR, auth, reports |
components/ |
23 .vue | customer/, dispatch/, shared/, layout/ |
composables/ |
41 | Domain-specific reactive logic (see below) |
modules/dispatch/components/ |
13 | Timeline, calendar, map, modals, context menus |
pages/ |
16 | Routed page views |
stores/ |
2 | Pinia: auth, dispatch |
config/ |
8 | erpnext, nav, dispatch, ticket-config, hub, table-columns |
Pages (16)
DashboardPage, ClientsPage, ClientDetailPage, TicketsPage, DispatchPage, EquipePage, NetworkPage, TelephonyPage, RapportsPage, SettingsPage, OcrPage, AgentFlowsPage, ReportARPage, ReportRevenuPage, ReportTaxesPage, ReportVentesPage
Composables (41) -- grouped by domain
| Domain | Composables |
|---|---|
| Scheduling | useScheduler, useDragDrop, useBottomPanel, usePeriodNavigation, useAutoDispatch, useBestTech, useJobOffers, useAbsenceResize, useSelection, useUndo, useContextMenus, useTechManagement |
| Map / GPS | useMap, useGpsTracking, useAddressSearch |
| Phone / SMS | usePhone, useConversations |
| Data | useClientData, useDeviceStatus, useSSE, useInlineEdit, useEquipmentActions, usePaymentActions, useSubscriptionActions, useSubscriptionGroups, useLegacySync, useCustomerNotes, usePermissions, usePermissionMatrix, useUserGroups |
| UI | useHelpers, useFormatters, useStatusClasses, useDetailModal, useResourceFilter, useTagManagement, useUnifiedCreate, useScanner, useWifiDiagnostic, useWizardCatalog, useWizardPublish |
4. Targo-Hub (Node.js)
Container targo-hub | msg.gigafibre.ca | Port 3300 | 40 modules in lib/
Modules (top 15 by size)
| Module | Lines | Purpose |
|---|---|---|
| payments.js | 1374 | Stripe checkout, PPA cron, webhooks |
| network-intel.js | 1221 | Network topology, outage correlation |
| ai.js | 719 | Gemini AI integration (tool-calling) |
| acceptance.js | 672 | Service acceptance workflows |
| outage-monitor.js | 601 | Uptime-Kuma alerts |
| reports.js | 572 | Analytics and report generation |
| tech-mobile.js | 562 | Lightweight mobile page for technicians |
| devices.js | 551 | GenieACS proxy, device summary, poller |
| contracts.js | 548 | Contract generation |
| oktopus.js | 545 | TR-369/USP controller proxy |
| agent.js | 529 | AI SMS agent with tool-calling |
| conversation.js | 499 | Conversation persistence |
| voice-agent.js | 457 | Inbound voice IVR + WebSocket media |
| olt-snmp.js | 419 | OLT SNMP polling, ONU state tracking |
| checkout.js | 399 | Customer checkout / catalog API |
Plus 25 smaller modules: server, twilio, pbx, dispatch, provision, auth, telephony, ical, modem-bridge, config, helpers, sse, email, otp, magic-link, traccar, vision, device-extractors, device-hosts, oktopus-mqtt, tech-absence-sms, address-search, email-templates, project-templates.
Endpoints -- grouped by domain
SSE / Real-time
| Method | Path | Purpose |
|---|---|---|
| GET | /sse?topics=... |
SSE stream (customer, conversations, sms-incoming) |
| POST | /broadcast |
Push event to SSE clients |
SMS / Voice / Telephony
| Method | Path | Purpose |
|---|---|---|
| POST | /send/sms |
Send SMS via Twilio |
| POST | /webhook/twilio/sms-incoming |
Inbound SMS |
| POST | /webhook/twilio/sms-status |
Delivery status |
| GET | /voice/token |
Twilio voice JWT |
| POST | /voice/twiml, /voice/status |
TwiML + call status |
| POST | /voice/inbound, /voice/gather, /voice/connect-agent |
IVR voice agent |
| WS | /voice/ws |
Twilio Media Streams (WebSocket) |
| POST | /webhook/3cx/call-event |
3CX call events |
| * | /telephony/* |
Fonoster/Routr SIP CRUD |
Devices / Network
| Method | Path | Purpose |
|---|---|---|
| GET | /devices/lookup?serial=X |
GenieACS device search (3 fallback strategies) |
| GET | /devices/summary |
Fleet statistics |
| GET | /devices/:id/hosts |
Connected clients + mesh mapping |
| POST | /devices/:id/tasks |
Send task (reboot, refresh) |
| * | /acs/* |
ACS config export |
| * | /modem/* |
Proxy to modem-bridge |
| * | /olt/* |
OLT SNMP stats, ONU lookup, registration |
| * | /oktopus/* |
TR-369 USP proxy |
| * | /network/* |
Network intelligence / topology |
Dispatch / Scheduling -- /dispatch/* (CRUD, iCal token + feed)
Auth / Customer / Payments -- /auth/* (RBAC), /magic-link/*, /api/checkout|catalog|otp|order|address (customer flow), /payments/* + /webhook/stripe (Stripe + PPA cron), /accept/*, /contract/*
AI / Vision -- /ai/* (Gemini), /agent/* (SMS agent), /vision/barcodes|equipment, /conversations/*
Other -- /traccar/* (GPS), /provision/* (OLT), /reports/*, /t/:token (tech mobile), /webhook/kuma (outage), /health
5. Modem-Bridge (Playwright/Chromium)
Internal-only service on port 3301. Provides REST access to TP-Link ONU web GUIs via headless Chromium. Required because XX230v firmware uses GDPR-encrypted communication (RSA key exchange, AES session, encrypted JSON on /cgi_gdpr?9). Playwright lets the modem's own JavaScript handle all crypto natively rather than re-implementing the protocol.
| Method | Path | Purpose |
|---|---|---|
| POST | /session/login |
Authenticate to modem (ip, user, pass) |
| GET | /session/list |
List active browser sessions |
| DELETE | /session/:ip |
Close session |
| GET | /modem/:ip/status |
Device status summary |
| GET | /modem/:ip/dm/:oid |
Data manager GET |
| GET | /modem/:ip/screenshot |
PNG screenshot (debug) |
Constraints: ~450MB disk (node + Chromium), ~80MB idle + 150MB per session, 512MB Docker limit, sessions auto-expire after 5 min. Bearer token auth, private IP restriction, read-only operations only.
6. Secondary Apps
| App | Stack | URL | Purpose |
|---|---|---|---|
Field App (apps/field/) |
Vue 3 / Quasar PWA | -- | Tech mobile: daily tasks, barcode scanner, device diagnostics, offline sync |
Client Portal (apps/client/) |
Vue 3 / Quasar PWA | client.gigafibre.ca | Self-service: invoices, subscriptions, tickets, catalog. Auth via Authentik |
Website (apps/website/) |
React / Vite / Tailwind | www.gigafibre.ca | Marketing: products, eligibility check, online ordering, FAQ |
7. Data Model (ERPNext Doctypes)
Customer
├── Service Location (LOC-#####)
│ ├── Address + GPS coordinates
│ ├── OLT port, VLAN, network config
│ ├── Service Equipment (EQP-#####)
│ │ ├── Type: ONT / Router / Switch / AP / Decodeur
│ │ ├── Serial + MAC + manage IP + firmware
│ │ └── Status: Active / Inactive / En stock / Defectueux / Retourne
│ └── Service Subscription (SUB-#####)
│ ├── Plan: Internet / IPTV / VoIP / Bundle
│ └── Status: pending → active → suspended → cancelled
└── Sales Invoice → Payment Entry
Dispatch Job
├── Customer + Service Location
├── Dispatch Technician (assigned + assistants)
├── Dispatch Tag Link (tag + level 1-5 + required flag)
├── Schedule: date, time, duration, recurrence (RRULE)
└── Equipment Items / Materials Used
Dispatch Technician
├── weekly_schedule (JSON), extra_shifts (JSON)
└── Dispatch Tag Link (skill level per tag)
Custom fields on standard doctypes: Customer (stripe_id, is_commercial, ppa_enabled), Subscription (actual_price, service_location), Issue (linked dispatch jobs), Sales Invoice (QR code, portal link).
8. External Integrations
| Service | Purpose | Connection |
|---|---|---|
| GenieACS (10.5.2.115) | TR-069 CPE management | NBI REST, LAN, no auth |
| Twilio | SMS + voice | REST API, Basic auth |
| Stripe | Payments, checkout | API + webhooks |
| Mapbox | Maps, geocoding, routing | JS SDK + Directions API |
| Gemini AI | OCR, SMS agent, AI tools | REST, Bearer token |
| Traccar | GPS tech tracking | REST API, Basic auth |
| 3CX PBX | Call history | REST API poller (30s) |
| Fonoster/Routr | SIP trunking | Direct PostgreSQL |
| Authentik | SSO (staff + client) | Traefik forwardAuth + API |
| n8n | Workflow automation | HTTP webhooks |
| Uptime-Kuma | Outage monitoring | Webhook to targo-hub |
| Cloudflare | DNS for gigafibre.ca | REST API |
9. Data Flows
Device Diagnostic
Ops App → EquipmentDetail.vue → GET /devices/lookup?serial=X
→ targo-hub → GenieACS NBI (3 fallback strategies) → summarizeDevice()
→ {interfaces, mesh, wifi, opticalStatus, ethernet}
GET /devices/:id/hosts?refresh
→ 2 tasks to CPE (connection_request) → read GenieACS cache
→ clientNodeMap: MAC → {nodeName, band, signal, speed}
→ UI: clients grouped by mesh node (basement, hallway, etc.)
Dispatch Auto-Assign
New job with required tags (e.g., Fibre level 3)
→ useAutoDispatch → useBestTech
→ Filter techs: tag level >= required, available in time slot
→ Sort: lowest adequate skill level first (preserve experts)
→ Assign → SSE broadcast → timeline updates
SMS Notification
Compose in ChatterPanel → POST /send/sms → targo-hub
→ Twilio API → delivery
→ /webhook/twilio/sms-status → SSE broadcast (conv:{token})
→ UI updates delivery status in thread
Inbound SMS → /webhook/twilio/sms-incoming
→ conversation.js (persist) → SSE broadcast (sms-incoming)
→ agent.js (optional AI auto-reply with tool-calling)
Customer Onboarding
Website → /api/address (eligibility check) → /api/catalog
→ /api/checkout (Stripe session) → /webhook/stripe (payment confirmed)
→ ERPNext: create Customer + Service Location + Subscription
→ /api/otp (SMS verification) → magic-link auth
→ provision.js: OLT pre-auth → GenieACS auto-provision on connect