# DEPLOY — ORVEX / DOMINIZ Guide de déploiement production/staging pour l’écosystème **ORVEX** (app PWA) et les référentiels **DOM-00** (registry public, révocations, schéma), avec bonnes pratiques de cache, sécurité et vérification. --- ## 1) Pré-requis * Hébergement **HTTP(S)** statique (Nginx/Apache, S3+CloudFront, Netlify, Cloudflare Pages, …). * **TLS** valide (Let’s Encrypt ou équivalent). * Noms de domaine recommandés : * `orvex.` (app) – start URL : `/orvex.html` * `verify.` (vérification publique) – start URL : `/verify.html` * `dom-00.` (référentiels publics) ou `/dom-00/` sous le domaine principal * Pipeline CI (facultatif) pour publier **staging** → **prod**. ## 2) Arborescence à publier ``` / index.html, orvex.html, verify.html, manifest.webmanifest, service-worker.js /assets/ css, js, libs, images, fonts /dom-00/ kid_registry.json, revocations.json, dom-00.schema.json, /keys/*.pem /cli/ dominiz-audit.mjs, dominiz_audit.py /docs/ README.md, DOM-00.md, SIGNATURES.md, DEPLOY.md ``` ## 3) Matrice de cache & stratégies (HTTP + Service Worker) | Ressource | Cache HTTP | Stratégie SW | Notes | | ---------------------------------------------------- | ------------------------------------- | ---------------------------------- | --------------------------------------------------- | | `/assets/**` (CSS/JS/img/libs) | `public, max-age=31536000, immutable` | **stale‑while‑revalidate** | versionnées par `BUILD_ID` dans `service-worker.js` | | Pages (`/index.html`, `/orvex.html`, `/verify.html`) | `no-cache` | **cache‑first + revalidate** | utilisables offline | | `/dom-00/*.json` (registry, revocations, schema) | `no-store` | **network‑first** (fallback cache) | toujours la version la plus fraîche | | `/dom-00/keys/*.pem` | `no-store` | **network‑first** | clés publiques SPKI | | `manifest.webmanifest` | `no-cache` | **cache‑first** | PWA | | `service-worker.js` | `no-cache` | — | MAJ = bump `BUILD_ID` | > **Important** : incrémenter `BUILD_ID` dans `service-worker.js` à chaque release pour purger les anciens caches. ## 4) En-têtes HTTP recommandés ```http # Sécurité générale Content-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none' X-Content-Type-Options: nosniff Referrer-Policy: no-referrer Permissions-Policy: geolocation=(), camera=(), microphone=() Cross-Origin-Resource-Policy: same-origin # PWA Service-Worker-Allowed: / # Caches # Pages HTML Cache-Control: no-cache # JSON & PEM (référentiels DOM-00) Cache-Control: no-store # Assets versionnés Cache-Control: public, max-age=31536000, immutable ``` ## 5) Nginx — configuration type ```nginx server { listen 443 ssl http2; server_name orvex.example.org; root /var/www/orvex; # racine du build index index.html; # TLS (exemple Let’s Encrypt) ssl_certificate /etc/letsencrypt/live/orvex.example.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/orvex.example.org/privkey.pem; # Sécurité (headers) add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always; add_header X-Content-Type-Options nosniff always; add_header Referrer-Policy no-referrer always; add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always; add_header Cross-Origin-Resource-Policy same-origin always; # Pages (no-cache) location ~* \.(html)$ { add_header Cache-Control "no-cache" always; } # DOM-00 JSON/PEM (no-store) location ^~ /dom-00/ { types { } default_type application/json; add_header Cache-Control "no-store" always; try_files $uri =404; } location ~* /dom-00/keys/.*\.pem$ { default_type application/x-pem-file; add_header Cache-Control "no-store" always; try_files $uri =404; } # Assets versionnés (long cache) location ^~ /assets/ { add_header Cache-Control "public, max-age=31536000, immutable" always; try_files $uri =404; } # Service worker & manifest location = /service-worker.js { add_header Cache-Control "no-cache" always; } location = /manifest.webmanifest { add_header Cache-Control "no-cache" always; } } ``` ## 6) Cloudflare Pages / Workers (règles) * Déployer le répertoire statique. * Définir **Rules** : * `/dom-00/*` → `Cache-Control: no-store` * `/assets/*` → `Cache-Control: public, max-age=31536000, immutable` * `/*.html`, `/manifest.webmanifest`, `/service-worker.js` → `no-cache` * **Security Headers** via **Transform Rules** ou **Workers** (si non gérés par l’origin). ## 7) Netlify (fichiers spéciaux) Créer un fichier `_headers` à la racine : ``` /* Content-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none' X-Content-Type-Options: nosniff Referrer-Policy: no-referrer Permissions-Policy: geolocation=(), camera=(), microphone=() Cross-Origin-Resource-Policy: same-origin /dom-00/* Cache-Control: no-store /assets/* Cache-Control: public, max-age=31536000, immutable /index.html Cache-Control: no-cache /orvex.html Cache-Control: no-cache /verify.html Cache-Control: no-cache /manifest.webmanifest Cache-Control: no-cache /service-worker.js Cache-Control: no-cache ``` `_redirects` est généralement inutile (app purement statique). ## 8) S3 + CloudFront (exemple) * S3 : bucket **public** en lecture, **Block Public Access** désactivé (ou via OAC CloudFront). * CloudFront : * Comportements : * `/dom-00/*` → `Cache-Control: no-store` * `/assets/*` → `public, max-age=31536000, immutable` * `/*.html`, `/service-worker.js`, `/manifest.webmanifest` → `no-cache` * Activer **Compression** et **HTTP/2**. ## 9) Processus de release 1. **Bumper** `BUILD_ID` dans `service-worker.js` (ex. `2025.10.18-02`). 2. **Build** (si minification/concat). Vérifier que les chemins `/assets/**` n’ont pas changé. 3. **Publier** en **staging** : `staging.`. 4. Tests **PWA offline** : * Charger `/orvex.html` → Couper le réseau → rafraîchir. * Vérifier que `/verify.html` tente d’abord le réseau pour `/dom-00/*.json` puis passe en cache. 5. **Smoke tests** : hash PDF, génération JSON, signature demo, Verify Online avec clés demo. 6. **Promouvoir** vers **prod** : DNS cutover ou copie des artefacts. ## 10) Monitoring & logs * Activer logs **access/error** côté serveur (Nginx/CloudFront). * Suivre les hits `/dom-00/kid_registry.json` et `/dom-00/revocations.json` (consommation de la norme). * Établir un **tableau de bord** (Grafana/CloudWatch) : disponibilité, latence, taille réponses. ## 11) Sécurité & conformité * Rotation des **KID** tous les 24 mois (minimum) ; publier les nouvelles clés sous `/dom-00/keys/` et mettre à jour `kid_registry.json`. * **Jamais** de clés privées dans le dépôt ou le serveur web. * Gérer la **révocation** en 2 étapes : 1. mettre à jour `revocations.json` en staging ; 2. déployer en prod (visible immédiatement pour Verify Online et les CLI). * Sauvegardes quotidiennes des répertoires `/dom-00/` et des PDF publics. ## 12) Déploiement air‑gapped (mode souverain) * Distribuer l’app (`/orvex.html` + `/assets/**`) sur supports hors-ligne (intranet, clé USB signée). * Fournir les **registres DOM-00** sur un miroir interne (pas d’accès externe). * Les **signatures** se font localement (challenge JCS ↔ JWS). * Vérification publique ultérieure via un **pont contrôlé** (export des JSON signés vers l’externe). ## 13) Tests de validation (checklist) * [ ] `service-worker.js` installé (onglet Application → Service Workers = **activated**) * [ ] PWA : `manifest.webmanifest` chargé (icônes ok) * [ ] Offline : `/orvex.html` fonctionne sans réseau * [ ] Verify : réseau d’abord, fallback cache ; verdicts corrects * [ ] Headers : `Cache-Control` selon matrice ; `CSP` appliquée * [ ] `/dom-00/kid_registry.json` et `/dom-00/revocations.json` accessibles ## 14) Types MIME utiles ```nginx # Nginx (http { ... }) types { application/json json; application/manifest+json webmanifest; application/x-pem-file pem; } ``` ## 15) Rollback * Préserver au moins **deux** versions de build. * En cas de rollback, remettre l’ancienne version et **restaurer** le `BUILD_ID` correspondant pour réaligner le cache SW. --- **Mantra** : publier **vite**, vérifier **hors‑ligne**, et laisser la **vérité** DOMINIZ s’auto‑prouver par les registres publics.