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>
|
||
|---|---|---|
| .. | ||
| architecture | ||
| archive | ||
| assets | ||
| features | ||
| reference | ||
| README.md | ||
| roadmap.md | ||
Gigafibre FSM — Documentation
Start here. Everything you need to understand the system is one or two clicks away. Pick the row that matches why you're here.
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 |
| 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 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/ |
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)
├── features/ ← one doc per business capability
│ ├── billing-payments.md (Stripe, invoices, subscriptions, PPA)
│ ├── cpe-management.md (GenieACS, Oktopus, XX230v)
│ ├── 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)
Conventions
- Edit in place. Don't copy-paste a section into a new file — link to it instead.
- Dated snapshots go to
archive/status-snapshots/. Don't createSTATUS_YYYY-MM-DD.mdat the root anymore. - 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. - The root
README.md(one level up) is the repo introduction for non-technical readers;docs/README.md(this file) is the engineering index.
What changed on 2026-04-22
The docs were flattened out of a single folder into architecture/,
features/, reference/, archive/. Every file move used git mv so
git log --follow still 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 the table above
to find the new location.
The only place old names still appear is inside
archive/HANDOFF-2026-04-18.md and archive/status-snapshots/*.md, where the
links are intentionally preserved as a frozen historical record.