# 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 ```