Référence
Architecture
Stack PHP 8.3 + Symfony 7 + Postgres 17 + libsodium. DDD-light : Domain pur, Application use cases, Infrastructure adapters. Pas de Docker, tout tourne en local via Valet + DBngin.
Vue d'ensemble
┌─────────────────────┐ ouvre session ┌──────────────────┐ appose sceau ┌─────────┐
│ Organisation (votre SI) │ ───────────────▶ │ ProofIt │ ◀──────────── │ DocuSign │
│ (API REST + SDK) │ reçoit webhook │ │ artifact │ /Yousign │
│ │ ◀───────────────│ chaîne audit │ hash match │ /... │
└─────────────────────┘ │ append-only │ └─────────┘
│ │ co-signée │
│ │ Ed25519 │
│ télécharge .asice │ │
│ │ │ ancre périodiquement
▼ │ │
┌─────────────────────┐ └──────────────────┘
│ Dossier de preuve │ │ ┌─────────────┐
│ ASiC-E ETSI │ ▼ │ Bitcoin │
│ Art. 25.1 eIDAS │ OpenTimestamps + TSP qualifié │ + TSP eIDAS│
│ │ (best-of-N en parallèle) │ │
└─────────────────────┘ └─────────────┘
Stack technique
| Layer | Choix | Pourquoi |
|---|---|---|
| Langage | PHP 8.3 strict types | Maturité framework, types stricts, libsodium natif |
| Framework | Symfony 7 | DDD-friendly, Doctrine ORM XML, Messenger async |
| DB | PostgreSQL 17 | Triggers PL/pgSQL, JSONB, rôles SQL fine-grained, advisory locks |
| Crypto | libsodium (Ed25519, Argon2id, secretbox) | Crypto courbe-elliptique standard, KDF résistant GPU |
| JWS / JWT | web-token/jwt-framework + HS256 maison | OAuth2 client_credentials JWT bearer |
| Async | Symfony Messenger + Postgres LISTEN/NOTIFY | Anchoring (batch + immédiat à la clôture), webhooks, bundles prêts, checkpoints témoins, purges RGPD quotidiennes. Pas de Redis pour V1. |
| Emails | Symfony Mailer + DKIM signer natif | Mails témoins indépendamment vérifiables |
| Admin UI | Twig + UX Live Components + Tailwind | Pas d'EasyAdmin — on contrôle le UX. Tailwind v4. |
| 2FA admin | scheb/2fa-bundle TOTP | Standard Symfony bundle |
| Doc API | NelmioApiDocBundle (Swagger UI) | Génération OpenAPI 3.0 depuis attributs PHP |
Structure du monorepo
session-proof/
├── api/ Application Symfony
│ ├── src/
│ │ ├── Domain/ Entités pures (sans framework)
│ │ │ ├── Audit/ AuditEntry, EventType, PayloadHash, SequenceNumber
│ │ │ ├── Session/ Session, PlannedManifest (S41), OtpCode
│ │ │ ├── Anchoring/ Anchor, TimestampProvider enum
│ │ │ ├── Notification/ NotificationEmail, EmailType, NotificationGateway
│ │ │ └── ...
│ │ ├── Application/ Use cases (un = une classe avec execute())
│ │ ├── Infrastructure/ Doctrine, libsodium, mailer, OTS, RFC 3161, Crypto
│ │ ├── Http/ Controllers API publique
│ │ └── Admin/ Controllers + Twig de l'admin
│ ├── templates/ Twig admin + consent + emails + docs/
│ ├── migrations/ Doctrine migrations (DDL + GRANTs)
│ └── tests/ Unit + Integration + Functional (190 tests)
├── sdk/
│ ├── php/ Composer @session-proof/php-sdk
│ ├── node/ bun @session-proof/sdk
│ └── python/ pip session-proof-sdk
├── demo/organisation-demo/ React + Express parapheur avec mock DocuSign
├── tools/verify/ CLI Python vérification ASiC-E hors-ligne
├── bruno/ Collection Bruno (tests API manuels)
└── docs/ Doc projet (PROJECT, ROADMAP, SECURITY, etc.)
Sécurité opérationnelle
- 🔐 Rôle SQL
validation_appen runtime — pas le superuserpostgres. Pas de GRANT UPDATE/DELETE suraudit_entry. - 🔐 Master key dérivée Argon2id (MODERATE) depuis un passphrase env. V2 : intégration AWS KMS effective (stub en place).
- 🔐 JWT signing key séparé du master passphrase (domain separation HMAC).
- 🔐 STRICT_SCOPE_ENFORCEMENT env-driven, à activer en prod après notif clients SDK.
- 🔐 BENEFICIARY_EMAIL_KEY 32 octets hex pour le chiffrement at-rest RGPD.
- 🔐 Idempotency-Key obligatoire sur les routes mutantes. Auto-générée par les SDKs. Réutilisée sur les retries 5xx.
- 🔐 CSRF sur tous les POST admin (form_login + tokens).
- 🔐 4 audits sécu reviewer agents (41 findings, tous traités) avant audit externe.