> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Runbook

# Runbook opérateur

Procédures pour démarrer, exploiter, et dépanner la plateforme MSSP SnakySec.

## Sommaire

* [Environnements](#environnements)
* [Démarrage pré-prod](#démarrage-pré-prod)
* [Démarrage production](#démarrage-production)
* [Vault (init, unseal, rotation)](#vault-init-unseal-rotation)
* [Prisma — sync schéma](#prisma--sync-schéma)
* [Matrice de rebuild](#matrice-de-rebuild)
* [Audit local (hors CI)](#audit-local-hors-ci)
* [Dépannage](#dépannage)

***

## Environnements

| Env                      | Mode Vault                          | TLS           | Cible                                                      |
| ------------------------ | ----------------------------------- | ------------- | ---------------------------------------------------------- |
| **Pré-prod** (dev local) | dev mode (`root` token)             | mkcert        | Docker Desktop Windows (aujourd'hui) · MacBook Pro (futur) |
| **Production**           | Shamir seal (5 shares, threshold 3) | Let's Encrypt | VPS OVH (cible)                                            |

## Démarrage pré-prod

```bash theme={null}
cp .env.example .env                 # renseigner APP_DOMAIN, VAULT_ADDR
make preprod                         # compose tous les overlays dev
```

Accès : `https://<APP_DOMAIN>`. Credentials AppRole injectés automatiquement depuis Vault dev.

Logs par service :

```bash theme={null}
make app-logs     # Next.js
make traefik-logs # Traefik
make vault-logs   # Vault
make postgres-logs
```

## Démarrage production

```bash theme={null}
make prod                            # compose tous les overlays prod
vault operator init -key-shares=5 -key-threshold=3   # SEULEMENT à la 1re init
```

**Conserver les 5 key shares** selon la répartition documentée dans [dr/01-keyholders.md](dr/01-keyholders.md) : 3 chez le DR Owner (YubiKey + KeePass + papier coffre) + 2 en enveloppe scellée chez notaire mandaté. Ne jamais commit.

## Vault (init, unseal, rotation)

### Unseal après redémarrage

```bash theme={null}
vault operator unseal <share-1>
vault operator unseal <share-2>
vault operator unseal <share-3>      # threshold = 3
```

### Rotation AppRole

Après `vault operator init` ou ré-init :

```bash theme={null}
vault write -f auth/approle/role/mssp-app/secret-id
vault write -f auth/approle/role/mssp-worker/secret-id
```

Mettre à jour le volume partagé `mssp-approle` (les entrypoints lisent les nouveaux credentials au prochain démarrage container).

### Paths Vault

* `mssp/data/platform` — `auth_secret`, `encryption_key`, `entra_cert_pem`, `entra_cert_private_key`, `gitlab_token`, `postgres_password`, `redis_password`, `sentry_dsn`, `sentry_auth_token`
* `mssp/data/clients/<slug>` — credentials SSO par client (`entra_client_id`, `entra_tenant_id`, `entra_cert_pem`, `entra_cert_private_key`)

## Prisma — sync schéma

Prisma 7 nécessite `prisma.config.ts` à la racine de `platform/`.

Après modification de `schema.prisma`, pousser le schéma via un container éphémère sur le réseau Docker :

```bash theme={null}
docker run --rm --network platform_mssp-net \
  -v "//$PWD/platform://work" -w //work node:22-alpine \
  sh -c "DATABASE_URL='postgresql://mssp:<pw>@postgres:5432/mssp' npx prisma db push"
```

Puis `make app-rebuild` pour rebuild l'image avec le nouveau client Prisma.

## Matrice de rebuild

| Fichier modifié                                  | Commande                                                  |
| ------------------------------------------------ | --------------------------------------------------------- |
| `platform/src/**/*.ts(x)`                        | `make app-rebuild`                                        |
| `platform/prisma/schema.prisma`                  | Container éphémère `prisma db push` + `make app-rebuild`  |
| `platform/package.json`                          | `make app-rebuild`                                        |
| `platform/docker/**`                             | `make preprod-build` (ou service ciblé)                   |
| `.env`                                           | `make app-restart` (recrée le container avec nouveau env) |
| Contrôles framework (`src/frameworks/**/*.json`) | Aucun — chargés au runtime côté CI                        |

## Audit local (hors CI)

Pour tester un contrôle sans déclencher un pipeline GitLab :

```powershell theme={null}
pwsh ./src/runners/Invoke-CISAudit.ps1 `
  -TenantId '<guid>' -TenantName 'Contoso' `
  -ClientId '<app-id>' -AccessToken $token `
  -ProductArea entra
```

Les artefacts schema v3 sont écrits dans `artifacts/audit/`.

## Dépannage

### "No client configured for this domain"

Fallback plateforme actif : vérifier que les secrets Entra sont présents sur `mssp/data/platform`. Si oui, l'admin MSSP doit voir le bouton SSO. Si non, vérifier que `resolveClientFromCookie()` retourne les env vars plateforme.

### JWT session invalidée après redémarrage

`AUTH_SECRET` rotated en Vault → toutes les sessions NextAuth sont invalidées. L'utilisateur doit clear ses cookies et re-login.

### `instrumentation.ts` ne voit pas les secrets Vault

`instrumentation.ts` s'exécute **une fois** au démarrage serveur, pas à chaque requête. Pour propager une modification, `make app-rebuild` (pas juste restart).

### Cert auth Graph échoue

Les secrets `ENTRA_CERT_PEM` + `ENTRA_CERT_PRIVATE_KEY` vivent **uniquement** dans Vault. Vérifier :

```bash theme={null}
vault kv get -field=entra_cert_pem mssp/platform | head -3
```

Doit commencer par `-----BEGIN CERTIFICATE-----`.

### Variables `NEXT_PUBLIC_*` non mises à jour

Bakées au **build time** dans le JS bundle. `make app-rebuild` obligatoire (pas juste restart).

### Webhook GitLab auto-disabled

GitLab désactive un webhook après N échecs consécutifs. Re-enabler manuellement dans l'UI GitLab + vérifier que `/api/webhooks/gitlab` répond en \<10s (import async via `after()` configuré).
