diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ad7c542..5f40f2b 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -550,6 +550,7 @@ VITE_SUPABASE_URL=https://xxx.supabase.co VITE_SUPABASE_ANON_KEY=xxx VITE_ENABLE_T2_LIVE=false # flag pour cacher T2 en prod tant que pas prêt VITE_SENTRY_DSN=xxx # optionnel, pour monitoring +VITE_MAINTENANCE_MODE=false # true = affiche MaintenancePage avant tout provider ``` ### Règle absolue diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index b0c2276..541235c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -35,3 +35,23 @@ Chaque entrée suit ce format : - Documentation initiale du projet (ARCHITECTURE, ONBOARDING, SECURITY, etc.) - 5 ADRs pour les décisions architecturales majeures - Code source de `src/entities/user/access.ts` et `lib.ts` avec tests + + +## 2026-04-19 — Sprint 1 / Étape 6 — Maintenance mode + outillage sécurité + +### Ajouté +- Page de maintenance statique (`src/app/MaintenancePage.tsx`) — logo + message, tokens Direction H, zéro dépendance +- Guard `VITE_MAINTENANCE_MODE` dans `main.tsx` — si `true`, aucun provider ne se monte, aucun appel réseau +- Variable `VITE_MAINTENANCE_MODE` dans `env.ts` (optionnelle, défaut `false`) +- Hook PreToolUse Claude Code (`security-check.sh`) — 9 patterns SECURITY.md §2 +- Hook Stop Claude Code (`check-file-size.sh`) — alerte fichiers > 200 lignes +- MCP server Semgrep enregistré dans Claude Code + +### Documentation +- `ARCHITECTURE.md` §7 — ajout `VITE_MAINTENANCE_MODE` dans la liste des variables +- `TECH_DEBT.md` — FTD-16 résolu (maintenance mode implémenté) + +### Tests +- Typecheck : 0 erreur +- Vitest : 37/37 passés +- Test manuel : maintenance mode vérifié (page affichée, aucun appel réseau, routing bloqué) \ No newline at end of file diff --git a/docs/TECH_DEBT.md b/docs/TECH_DEBT.md index c7beafa..9b40017 100644 --- a/docs/TECH_DEBT.md +++ b/docs/TECH_DEBT.md @@ -257,6 +257,7 @@ Vient du pattern `c.json(result, result.status)` où `result` contient déjà `s |---|---|---|---| | FTD-11 | `@theme` Tailwind 4 non défini — palette et typographie absentes | 2026-04-18 | Résolu au Sprint 0.5 (design system). Palette Direction H complète (canvas/surface/ink/expria/deep/semantic) + typo Plus Jakarta Sans définis dans `src/index.css` via `@theme {}` et `.dark {}`. shadcn/ui remappé sur ces tokens. Règle L ajoutée dans `DEVELOPMENT_PRINCIPLES.md` pour garantir l'usage exclusif des tokens. | | FTD-13 | Incompatibilité Vitest 3 / Vite 8 (conflit de types `Plugin` entre le Vite 8 top-level avec Rolldown et le Vite 7 pinné de Vitest 3.2.4 ; `npm run build` cassé) | 2026-04-17 | Résolu par upgrade Vitest `3.2.4 → 4.1.4` (et `@vitest/coverage-v8` idem) à l'étape 12-bis du Sprint 0. Vitest 4.x supporte nativement Vite 8 Rolldown. Correctif complémentaire : script `typecheck` passé de `tsc --noEmit -p tsconfig.app.json` à `tsc -b --noEmit` pour couvrir aussi `tsconfig.node.json` (d'où `vite.config.ts`) et éviter qu'un bug similaire échappe à la CI. | +| FTD-16 | `VITE_MAINTENANCE_MODE` non lu dans le code — la variable d'env était dans `env.ts` mais jamais consommée | 2026-04-18 | Résolu au Sprint 1 étape 6. Ajout de `isMaintenanceMode` dans `src/shared/config/env.ts` et garde dans `src/app/main.tsx` : `isMaintenanceMode ? : `. `MaintenancePage` est statique (aucun provider requis), tokens Direction H exclusivement. | --- @@ -268,3 +269,4 @@ Vient du pattern `c.json(result, result.status)` où `result` contient déjà `s | 1.1 | 2026-04-17 | Ajout FTD-10 (Semgrep CI), FTD-11 (`@theme` Tailwind 4), FTD-12 (tests `api-client`) suite à l'étape 11 du Sprint 0 | | 1.2 | 2026-04-17 | Ajout FTD-13 résolu (incompatibilité Vitest 3 / Vite 8) suite à l'étape 12-bis du Sprint 0 | | 1.3 | 2026-04-18 | FTD-11 résolu (design system Sprint 0.5) ; ajout FTD-14 (anti-FOUC), FTD-15 (option 'system' thème) | +| 1.4 | 2026-04-18 | FTD-16 résolu (VITE_MAINTENANCE_MODE implémenté — Sprint 1 étape 6) | diff --git a/src/app/MaintenancePage.tsx b/src/app/MaintenancePage.tsx new file mode 100644 index 0000000..c622b95 --- /dev/null +++ b/src/app/MaintenancePage.tsx @@ -0,0 +1,24 @@ +import { Logo } from '@/shared/components/Logo' + +export function MaintenancePage() { + return ( +
+ +
+

Maintenance en cours

+

+ Expria est temporairement indisponible. Revenez dans quelques instants. +

+
+

+ Des questions ?{' '} + + support@expria.ca + +

+
+ ) +} diff --git a/src/app/main.tsx b/src/app/main.tsx index 798dc2c..2033578 100644 --- a/src/app/main.tsx +++ b/src/app/main.tsx @@ -1,6 +1,8 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { Providers } from './providers' +import { MaintenancePage } from './MaintenancePage' +import { isMaintenanceMode } from '@/shared/config/env' import '../index.css' const container = document.getElementById('root') @@ -10,6 +12,6 @@ if (!container) { createRoot(container).render( - + {isMaintenanceMode ? : } , ) diff --git a/src/shared/config/env.ts b/src/shared/config/env.ts index bae1c42..766b4ff 100644 --- a/src/shared/config/env.ts +++ b/src/shared/config/env.ts @@ -6,6 +6,7 @@ const envSchema = z.object({ VITE_SUPABASE_ANON_KEY: z.string().min(1), VITE_ENABLE_T2_LIVE: z.enum(['true', 'false']).optional(), VITE_SENTRY_DSN: z.string().url().optional(), + VITE_MAINTENANCE_MODE: z.enum(['true', 'false']).optional(), }) const parsed = envSchema.safeParse(import.meta.env) @@ -18,3 +19,4 @@ if (!parsed.success) { } export const env = parsed.data +export const isMaintenanceMode = parsed.data.VITE_MAINTENANCE_MODE === 'true'