Files
Classeo/backend/migrations/Version20260203100000.php
Mathias STRASSER 2ed60fdcc1 feat: Audit trail pour actions sensibles
Story 1.7 - Implémente un système complet d'audit trail pour tracer
toutes les actions sensibles (authentification, modifications de données,
exports) avec immuabilité garantie par PostgreSQL.

Fonctionnalités principales:
- Table audit_log append-only avec contraintes PostgreSQL (RULE)
- AuditLogger centralisé avec injection automatique du contexte
- Correlation ID pour traçabilité distribuée (HTTP + async)
- Handlers pour événements d'authentification
- Commande d'archivage des logs anciens
- Pas de PII dans les logs (emails/IPs hashés)

Infrastructure:
- Middlewares Messenger pour propagation du Correlation ID
- HTTP middleware pour génération/propagation du Correlation ID
- Support multi-tenant avec TenantResolver
2026-02-04 00:11:58 +01:00

66 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Migration pour la table audit_log append-only.
*
* @see Story 1.7 - T1: Schema Event Store
* @see FR90: Tracage actions sensibles
* @see NFR-S7: Audit trail immutable
*/
final class Version20260203100000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Create audit_log table with append-only constraints (Story 1.7)';
}
public function up(Schema $schema): void
{
// T1.1 & T1.2: Create audit_log table
$this->addSql(<<<'SQL'
CREATE TABLE audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
aggregate_type VARCHAR(255) NOT NULL,
aggregate_id UUID,
event_type VARCHAR(255) NOT NULL,
payload JSONB NOT NULL,
metadata JSONB NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
sequence_number BIGSERIAL NOT NULL
)
SQL);
// T1.4: Indexes for efficient querying
$this->addSql("CREATE INDEX idx_audit_tenant ON audit_log((metadata->>'tenant_id'))");
$this->addSql("CREATE INDEX idx_audit_user ON audit_log((metadata->>'user_id'))");
$this->addSql('CREATE INDEX idx_audit_occurred ON audit_log(occurred_at)');
$this->addSql('CREATE INDEX idx_audit_aggregate ON audit_log(aggregate_type, aggregate_id)');
$this->addSql("CREATE INDEX idx_audit_correlation ON audit_log((metadata->>'correlation_id'))");
$this->addSql('CREATE INDEX idx_audit_event_type ON audit_log(event_type)');
// T1.3: Append-only constraints - prevent UPDATE and DELETE
$this->addSql('CREATE RULE audit_no_update AS ON UPDATE TO audit_log DO INSTEAD NOTHING');
$this->addSql('CREATE RULE audit_no_delete AS ON DELETE TO audit_log DO INSTEAD NOTHING');
// Add comment to document the immutability constraint
$this->addSql("COMMENT ON TABLE audit_log IS 'Append-only audit log table. UPDATE and DELETE operations are disabled via PostgreSQL rules for immutability (NFR-S7).'");
}
public function down(Schema $schema): void
{
// Drop rules first
$this->addSql('DROP RULE IF EXISTS audit_no_update ON audit_log');
$this->addSql('DROP RULE IF EXISTS audit_no_delete ON audit_log');
// Drop table (indexes are dropped automatically)
$this->addSql('DROP TABLE IF EXISTS audit_log');
}
}