Corriger à la main les coordonnées d'un groupe écrit un band_locations avec
geocode_provider='admin' et confiance 1.0 : la donnée la plus autoritaire du
système, saisie par un humain, impossible à régénérer. Elle était pourtant la
moins protégée.
Le trigger de la migration 013 supprime toutes les band_locations d'un groupe
dès que son location_text change — override compris. locked_fields ne couvre
que les colonnes de `bands`, jamais les points : une correction disparaissait
donc silencieusement à la première modification du lieu, y compris quand ce
lieu venait d'être verrouillé par l'admin lui-même.
Trois routes de reset l'effaçaient également. Le code raisonnait explicitement
sur la protection des saisies manuelles pour choisir le statut écrit ('done' et
non 'manual', afin que reset-llm ne les emporte pas), mais ni reset-all ni
requeue-all(include_done) n'excluaient le provider : la protection tenait sur
un bouton et manquait sur les deux autres.
Le trigger épargne désormais les points 'admin', et les trois routes les
excluent. Trois tests d'intégration contre un vrai PostGIS couvrent ce trigger
et celui de la migration 016, qui n'en avaient aucun.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
32 lines
1.4 KiB
PL/PgSQL
32 lines
1.4 KiB
PL/PgSQL
-- 018_protect_admin_locations.sql
|
|
-- Les corrections manuelles de géocodage n'étaient protégées par rien.
|
|
--
|
|
-- Corriger à la main les coordonnées d'un groupe écrit un band_locations avec
|
|
-- geocode_provider='admin' et geocode_confidence=1.0 : la donnée la plus
|
|
-- autoritaire du système, saisie par un humain, impossible à régénérer.
|
|
--
|
|
-- Or le trigger de la migration 013 supprime TOUTES les band_locations d'un
|
|
-- groupe dès que son location_text change — override compris. Et locked_fields
|
|
-- ne protège que les colonnes de `bands`, jamais les points. Une correction
|
|
-- disparaissait donc silencieusement à la première modification du lieu, y
|
|
-- compris quand ce lieu venait d'être verrouillé par l'admin lui-même.
|
|
--
|
|
-- Le trigger épargne désormais les points posés par un admin. Ils restent
|
|
-- supprimables explicitement (DELETE depuis la route, reset-all ciblé), mais
|
|
-- plus par effet de bord.
|
|
|
|
CREATE OR REPLACE FUNCTION bands_geocode_dirty() RETURNS trigger AS $$
|
|
BEGIN
|
|
IF TG_OP = 'UPDATE' AND OLD.location_text IS DISTINCT FROM NEW.location_text THEN
|
|
DELETE FROM band_locations
|
|
WHERE ma_id = NEW.ma_id
|
|
AND COALESCE(geocode_provider, '') <> 'admin';
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_bands_geocode_dirty ON bands;
|
|
CREATE TRIGGER trg_bands_geocode_dirty
|
|
AFTER UPDATE OF location_text ON bands
|
|
FOR EACH ROW EXECUTE FUNCTION bands_geocode_dirty();
|