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>
298 lines
14 KiB
Markdown
298 lines
14 KiB
Markdown
# 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
|
|
```
|