Document vivant — mis à jour le 03/08/2026.
| Domaine | État | Preuve |
|---|---|---|
| Dépendances | npm audit → 0 vulnérabilité |
lint + build verts sur main |
| Bot de dépendances | Renovate seul actif ; Dependabot désactivé (PR fermée, Automated security fixes off) | dashboard/package.json overrides + renovate.json |
| Exposition anon (contacts, settings, sales…) | Fermée — anon bloqué (HTTP 401), seul contact_urls (200) et RPC capture_contact restent |
vérifié en direct |
| Inscription publique | Désactivée (disable_signup: true) |
vérifié en direct |
| Multi-utilisateur | user_id sur toutes les tables, RLS par propriétaire (auth.uid()), contacts « claim-on-edit » |
hardening_multi_user_rls.sql appliqué |
| En-têtes HTTP | CSP, HSTS, X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy, X-Powered-By off |
dashboard/next.config.ts |
| Bootstrap | schema.sql + migrations durcis (nouveaux projets) |
commit 80e465a |
| Extension | dédup via contact_urls, capture via capture_contact, logs PII retirés |
extension/content.js |
Fichier créé avec les valeurs réelles du projet (URL + clé anon publishable), gitignoré. Vérifié : build ✓, npm run dev → /login HTTP 200 ✓.
Rappel :
cd dashboard
cp .env.local.example .env.local
# puis remplir avec les valeurs : Supabase > Project Settings > APIWorker déployé : https://ownpulse-supabase-keepalive.cedric-0bf.workers.dev — PostgREST ping et Health ping vérifiés en 200 via logs. Au passage, le fallback health a été corrigé : Supabase exige le header apikey même sur /auth/v1/health (le « zero-key » documenté n'a jamais fonctionné).
Rappel pour un futur redeploy :
cd keepalive-worker
npx wrangler login
# secrets déjà en place (SUPABASE_URL, SUPABASE_ANON_KEY) — conservés au redeploy
echo "https://qleflestlmwvgicyebey.supabase.co" | npx wrangler secret put SUPABASE_URL
echo "TA_CLE_ANON" | npx wrangler secret put SUPABASE_ANON_KEY
npx wrangler deploy
# vérif : curl "https://ownpulse-supabase-keepalive.<subdomain>.workers.dev/ping" → OKLa clé est publishable (publique par design), mais la rotater invalide tout usage externe :
- Dashboard → Project Settings → API → créer une nouvelle clé publishable
- Mettre à jour avant de révoquer l'ancienne :
extension/content.js(ligne 3),dashboard/.env.local, secret worker (ci-dessus) - Tester (extension : « ✔ Saved to CRM » ; worker :
/ping→ OK) - Révoquer l'ancienne clé dans le dashboard
- Commit
content.js
- Dashboard Supabase → Authentication → Users → Add user (2ᵉ compte)
- Fenêtre privée →
/loginavec le 2ᵉ compte → les pages doivent être vides - Capturer un contact via l'extension → visible par le 2ᵉ compte → l'éditer = le réclamer → il disparaît du compte propriétaire
- Retour propriétaire : ses données sont intactes
⚠️ Comportement voulu : un contact capturé (non réclamé) peut être réclamé par n'importe quel utilisateur authentifié.
- Dashboard Supabase → Authentication → activer Multi-factor Auth (TOTP)
- Compte → Mon profil → Enroll avec une app d'authentification
- Optionnel : forcer MFA pour tous les comptes (Authentication → Settings)
Aujourd'hui la capture anon passe par capture_contact (whitelistée, non réclamée). Une évolution plus propre : l'extension s'authentifie (JWT) et appelle une RPC qui lie le contact au propriétaire (user_id = auth.uid()) — supprimerait le concept de « réclamation ».
- Ne jamais ré-exécuter
supabase/schema.sqlou les migrations sur le projet existant — scripts d'initialisation uniquement (une ré-exécution rouvrirait les grants anon). Pour un projet existant :hardening_security_rls.sqlpuishardening_multi_user_rls.sql(idempotents). - Jamais de clé
service_roledans le repo, le navigateur ou l'extension — uniquement les clés publishable. - Toute nouvelle table :
GRANTexplicite + RLS + policy par propriétaire (voirschema.sql). - Vérifications rapides de l'état verrouillé :
K=TA_CLE_ANON; U=https://qleflestlmwvgicyebey.supabase.co curl -s -o /dev/null -w "%{http_code}\n" "$U/rest/v1/contacts?select=id&limit=1" -H "apikey: $K" -H "Authorization: Bearer $K" # 401 attendu curl -s -o /dev/null -w "%{http_code}\n" "$U/rest/v1/contact_urls?select=id&limit=1" -H "apikey: $K" -H "Authorization: Bearer $K" # 200 attendu