JCT portail client — architecture hébergement et accès

TFD-017 — Architecture du portail client Jackson Creek Tech

Contexte

REQ-CONS-006 (cycle de vie de l'intake client, Axis 3 — "deflection & wiki") a absorbé REQ-EXEC-029 (portail livraison JCT). Il fallait choisir une stack qui :

  • héberge des showpieces HTML autonomes (livrables EA riches en CSS/SVG/JS minimal)
  • offre un accès contrôlé par client sans création de compte côté client
  • s'isole strictement par client (suppression nette en fin de mandat)
  • reste portable si le fournisseur change ses règles
  • tient sous un budget annuel ≤ 25 CAD
  • ouvre la voie à un pattern réplicable (1 client = 1 procédure ≤ 45 min)

Décision

# Décision Note
D1 Cloudflare Pages (déployé sous le nouveau UI unifié Workers) pour l'hébergement statique Gratuit, illimité, CDN mondial, intégré DNS
D2 Cloudflare Access (Zero Trust Free) pour l'authentification — One-time PIN courriel, 24h session Gratuit jusqu'à 50 utilisateurs, aucune création de compte client
D3 1 repo GitHub privé par client (jct-portail-{client}) sous le compte bockbr Isolation totale, démantèlement net
D4 1 sous-domaine par client sur jacksoncreektech.ca ({client}.jacksoncreektech.ca) Hiérarchie claire, sous-domaine = identité de la livraison
D5 Template-driven : repo jct-portail-template clone via gh repo create --template Onboarding nouveau client en ≤ 45 min
D6 HTML/CSS pur (pas de framework), Instrument Serif + warm cream + Trustworthy Blue Stabilité long terme, alignement design system factory
D7 Landing publique jacksoncreektech.ca (repo jct-www) séparée du domaine d'hébergement client Pas de fuite de liste de clients sur la page publique
D8 Domaine défensif jackson-creek-tech.ca (hyphené) acheté en parallèle ~CAD 12/an additionnel, mitigation typo-squatting, redirect 301 → primaire (à configurer)

Alternatives considérées

Option Pourquoi rejetée
Vercel Pages Auth payante (Vercel Authentication = Pro plan, ~20 $/mois). Pas de combo hosting+auth gratuit.
Netlify Identity Identity gratuit limité à 1000 MAU mais nécessite création de compte côté client (friction).
GitHub Pages + Cloudflare Access via tunnel Pages gratuit mais Access ne couvre pas *.github.io. Aurait demandé un tunnel custom. Plus complexe.
Mono-repo avec dossiers par client Suppression d'un client = rebase + force-push. Risque de fuite croisée par mauvaise config Pages. Isolation faible.
SSO Google/Microsoft Force le client à utiliser un IdP spécifique. STM contacts peuvent ne pas vouloir Google. OTP courriel = neutre.
Confluence External Users Coût (licence par utilisateur), interne STM, navigation pauvre pour showpieces HTML riches.

Conséquences

Positives

  • Coût année 1 : ~CAD 15 (domaine .ca primaire) + ~CAD 12 (domaine défensif .ca hyphené) = CAD 27 total (~CAD 2 over budget — accepté pour la protection de marque)
  • Onboarding nouveau client : ~30 min après le premier (Transgesco a pris ~45 min avec exploration UI)
  • Code 100 % statique et standard → portable vers Vercel/Netlify/n'importe quel CDN en 1 h si besoin
  • Le format HTML autonome aligné avec la stratégie "showpieces" du delivery model — pas de nouvelle dépendance d'outillage

Négatives / dette

  • Dette UX dashboard CF : la nouvelle UI unifiée Workers est ambiguë. Onboarding manuel de Pages + Access est sujet à friction. Mitigation : skill /jct:portail-publier à venir (REQ-ENG-XXX) pour automatiser via API.
  • Dépendance Cloudflare sur 2 produits (Pages + Access) — si CF change ses tiers gratuits, migration nécessaire. Mitigé par la portabilité du code statique.
  • DAE-0007 utilise Mermaid via CDN jsdelivr — accepté risque V1 (degraded gracefully). Pour livrables futurs critiques : inliner les dépendances.

Validation (DoD D8)

  • Domaine jacksoncreektech.ca réservé, HTTPS actif
  • jct-www (landing publique) déployée, tagline « Usine à talent »
  • jct-portail-template créé avec design system, READMEs (publier + ajouter client)
  • jct-portail-transgesco instancié, DAE-0007 Portrait TI cible publié
  • transgesco.jacksoncreektech.ca derrière Cloudflare Access (OTP courriel, 24h)
  • Test d'accès réussi avec bruno.bock@stm.info (courriel tiers ≠ admin)
  • Scan secrets : aucun match (équivalent gitleaks via grep patterns)
  • Coût annuel ≤ 27 CAD (cap initial CAD 25 dépassé de CAD 2 pour domaine défensif — accepté)

Follow-on

À scaffolder via /request-create :

  • REQ-ENG-XXX — Skill /jct:portail-publier (automatiser cp + commit + push d'un livrable)
  • REQ-CONS-XXX — Skill /ea:livrable-showpiece (MD agent-ea → showpiece HTML)
  • WO-DESIGN-XXX — Logo JCT final (remplace le wordmark SVG placeholder)
  • REQ-EXEC-XXX — 2e client portail (candidat : STM directement, ou autre client confirmé)
  • CI-XXX — Configurer redirect 301 jackson-creek-tech.ca/*jacksoncreektech.ca/$1 (Bulk Redirect rule Cloudflare)

Références

  • departments/consulting/requests/REQ-CONS-006-client-request-intake-lifecycle/request.md (Axis 3, Implementation track)
  • departments/consulting/requests/REQ-CONS-006-client-request-intake-lifecycle/input/2026-05-13-ceo-design-direction-jct-portal.md (design direction CEO)
  • departments/consulting/requests/REQ-CONS-006-client-request-intake-lifecycle/process/d8-jct-portail-mvp-implementation-plan.md (plan d'implémentation, P0–P6)
  • GitHub : bockbr/jct-www, bockbr/jct-portail-template, bockbr/jct-portail-transgesco (privés)
  • Cloudflare Access app Portail Transgesco (df72cd34-d90f-498c-b625-e31f6c6d8a81)