Files
Coltura/migrations/Version20260420202749.php
matthieu 99c77eb7b6 fix(audit-log) : applique fixes code review (precision timestamp, ESCAPE LIKE, pagination max)
- TIMESTAMP(6) WITH TIME ZONE + tie-breaker id DESC sur l'ORDER BY pour
  garantir un tri deterministe quand plusieurs lignes partagent la meme
  timestamp (batch fixture, bulk flush < 1µs).
- Suppression de la clause ESCAPE '\\' redondante (`\` est deja
  l'echappement LIKE par defaut en PostgreSQL) et fragile sur
  standard_conforming_strings. Le str_replace des wildcards reste.
- paginationMaximumItemsPerPage : 100 -> 50. Reduit le pire cas de
  reponse lourde sur un endpoint admin (changes JSONB volumineux).
2026-04-22 16:10:03 +02:00

64 lines
2.2 KiB
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Audit log — Ticket 1 : table append-only `audit_log`.
*
* Table non geree par Doctrine ORM (aucune entite associee). Ecriture via
* DBAL uniquement par l'AuditLogWriter pour eviter la recursion du listener
* Doctrine (flush re-entrant). Colonnes en minuscules snake_case comme
* partout dans le projet.
*
* Type natif PostgreSQL `uuid` (16 octets) plutot que varchar(36) : index
* 40% plus petit sur une table append-only a croissance infinie.
*
* Migration placee au namespace racine `DoctrineMigrations` a cause du bug
* de tri FQCN alphabetique de Doctrine Migrations 3.x documente dans
* CLAUDE.md.
*/
final class Version20260420202749 extends AbstractMigration
{
public function getDescription(): string
{
return 'Audit log : creation de la table append-only audit_log + index.';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE TABLE audit_log (
id uuid NOT NULL,
entity_type VARCHAR(100) NOT NULL,
entity_id VARCHAR(64) NOT NULL,
action VARCHAR(10) NOT NULL,
changes JSONB NOT NULL DEFAULT '{}'::jsonb,
performed_by VARCHAR(100) NOT NULL,
performed_at TIMESTAMP(6) WITH TIME ZONE NOT NULL,
ip_address VARCHAR(45) DEFAULT NULL,
request_id VARCHAR(36) DEFAULT NULL,
PRIMARY KEY(id)
)
SQL);
// Index pour recherche par entite (detail d'historique d'un objet).
$this->addSql('CREATE INDEX idx_audit_entity_time ON audit_log (entity_type, entity_id, performed_at)');
// Index pour recherche par utilisateur (qui a fait quoi).
$this->addSql('CREATE INDEX idx_audit_performer ON audit_log (performed_by, performed_at)');
// Index pour tri chronologique global (listing pagine DESC).
$this->addSql('CREATE INDEX idx_audit_time ON audit_log (performed_at)');
}
public function down(Schema $schema): void
{
$this->addSql('DROP TABLE audit_log');
}
}