Aller au contenu

PD-272 — Plan d'implementation

1. Synthese

Story simple : 1 migration PostgreSQL ajoutant un trigger BEFORE UPDATE OR DELETE sur vault_secure.legal_composite_proof pour garantir l'immutabilite post-persistance.

Pattern identique a legal_access_event (PD-81) et merkle_trees (PD-237) deja presents dans le codebase.

2. Contraintes techniques

Dependances inter-PD

Story Statut Nature
PD-81 DONE Table legal_composite_proof creee dans 1740400000000-CreateLegalPreTables.ts
PD-237 DONE Pattern trigger merkle_trees_immutable() — reference

Framework de test

  • Runner : Jest (coherent avec le reste du backend)
  • Tests d'integration : avec PostgreSQL reel (migration appliquee)
  • Variables CI : DATABASE_URL requise

Compatibilite ESM/CJS

  • Aucune dependance ESM-only

3. Go/No-Go

Hypothese Verification Resultat
Table legal_composite_proof existe Migration 1740400000000 OK — table creee dans schema vault_secure
Schema vault_secure existe Migration 1740400000000 OK — CREATE SCHEMA IF NOT EXISTS
Pattern trigger existant 1737000300000-CreateMerkleAppendOnlyTriggers.ts OK — pattern repliquable

4. Taches

TASK-1 : Migration PostgreSQL

Fichier : src/database/migrations/1740900000000-PD272-CreateLegalCompositeProofImmutableTrigger.ts

Contenu up() : 1. Creer la fonction vault_secure.legal_composite_proof_immutable() qui RAISE EXCEPTION 2. Creer le trigger trg_legal_composite_proof_immutable BEFORE UPDATE OR DELETE

Contenu down() : 1. DROP TRIGGER IF EXISTS 2. DROP FUNCTION IF EXISTS

Pattern suivi : Identique a vault_secure.legal_access_event_immutable() (PD-81, lignes 190-206 de 1740400000000)

Messages d'erreur contractuels : - UPDATE : legal_composite_proofs: modification interdite — preuve immutable - DELETE : legal_composite_proofs: suppression interdite — preuve immutable

TASK-2 : Test d'integration

Fichier : src/database/migrations/__tests__/PD272-legal-composite-proof-immutable.integration-spec.ts

Tests : - TC-NOM-01 : INSERT autorise - TC-ERR-01 : UPDATE bloque avec message exact - TC-ERR-02 : DELETE bloque avec message exact - TC-NEG-03 : UPDATE no-op (SET proof_version = proof_version) bloque aussi

TASK-3 : Verification Prolog

Apres migration, relancer extract-facts.py pour generer le fact :

table_trigger(legal_composite_proof, trg_legal_composite_proof_immutable, 'BEFORE UPDATE OR DELETE').

Puis verifier que check_proof_immutable_trigger passe a OK.

5. Code contracts

contracts:
  PD-272-migration:
    type: migration
    file: src/database/migrations/1740900000000-PD272-CreateLegalCompositeProofImmutableTrigger.ts
    invariants:
      - INV-272-01: "Toute ligne est immutable apres insertion"
      - INV-272-02: "UPDATE rejete avec message contractuel"
      - INV-272-03: "DELETE rejete avec message contractuel"
      - INV-272-04: "INSERT reste autorise"
      - INV-272-05: "Immutabilite inconditionnelle"
    patterns:
      - "BEFORE UPDATE OR DELETE trigger"
      - "RAISE EXCEPTION avec message metier"
      - "RAISE EXCEPTION messages conformes spec"
    forbidden:
      - "IF/WHEN condition dans le trigger (immutabilite inconditionnelle)"
      - "pg_notify (pas necessaire pour ce cas)"
    reference: "1740400000000-CreateLegalPreTables.ts:190-206"

6. Mapping INV/CA vs taches/tests

Invariant/CA Tache couvrant Test couvrant
INV-272-01 TASK-1 TC-NOM-01 + TC-ERR-01 + TC-ERR-02
INV-272-02 TASK-1 TC-ERR-01
INV-272-03 TASK-1 TC-ERR-02
INV-272-04 TASK-1 TC-NOM-01
INV-272-05 TASK-1 TC-NEG-03
INV-272-08 TASK-3 TC-NOM-02 (Prolog)
CA-272-01 TASK-1 TC-NOM-03 (metadata)
CA-272-02 TASK-1 TC-ERR-01
CA-272-03 TASK-1 TC-ERR-02
CA-272-04 TASK-1 TC-NOM-01
CA-272-05 TASK-3 TC-NOM-02
CA-272-06 TASK-2 TC-NR-01

7. Estimation

Tache Volume Complexite
TASK-1 (migration) ~40 lignes Faible
TASK-2 (tests) ~80 lignes Faible
TASK-3 (Prolog) ~5 min Trivial
Total ~120 lignes Faible