Files
decision/crates/ld-server/migrations/0008_objections_typos_messages.sql
T
YvvandClaude Opus 5.5 4d4adcc281
ci/woodpecker/push/app Pipeline was successful
ci/woodpecker/push/maquette Pipeline was successful
v3 : relecture de cd7e683 — coquilles, objections et retraits
- Le revirement de l'auteur sur une coquille (reprendre une correction appliquée,
  valider une correction refusée) ne s'écrit que sur une version encore ouverte :
  Settle porte while_open ; et la garde de statut de write_text marche enfin
  (?9 restait NULL, le statut est le 8e paramètre).
- 0008 lève les signalements debout dont un côté est déjà retiré.
- Une seule objection debout par personne et par paire (index unique partiel) ;
  envoyée plusieurs fois à la fois, les autres reçoivent objection_exists.
- Un retrait relance l'adoption : la version que l'objection retenait entre aussitôt.

Tests vus rouges d'abord. Boucle : 230 tests Rust, svelte-check 0, 55 vitest,
e2e 35 / 35.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 10:00:29 +01:00

107 lines
5.9 KiB
SQL

-- Objections « redit » / « contredit », typo fixes validated, and the messages
-- of trustinWallet (2026-10-31, lot F, ADR 0010). Additive only: nothing is
-- dropped, nothing is rewritten that an older image needs.
--
-- The contradiction signals of before become objections « contredit », in the
-- same table: an older image (rollback) still reads them as signals, and every
-- lifting still writes `lifted_at` / `lifted_by` as before.
ALTER TABLE signals ADD COLUMN kind TEXT NOT NULL DEFAULT 'contredit'; -- redit | contredit
ALTER TABLE signals ADD COLUMN held_id TEXT; -- the version held back (not votable): the latest arrival, never one in force
ALTER TABLE signals ADD COLUMN phase TEXT NOT NULL DEFAULT 'author'; -- author | objector | lifted
ALTER TABLE signals ADD COLUMN cycle INTEGER NOT NULL DEFAULT 1; -- a reiteration opens the next
ALTER TABLE signals ADD COLUMN due_at TEXT; -- phase objector: lifted by itself at this time
ALTER TABLE signals ADD COLUMN answered_at TEXT; -- the last answer of the author
ALTER TABLE signals ADD COLUMN answer TEXT; -- revision | other | proposal
ALTER TABLE signals ADD COLUMN answer_id TEXT; -- the version revised, or the proposal linked
ALTER TABLE signals ADD COLUMN lift TEXT; -- objector | admin | deadline | withdrawn | revision
-- The signals of before that were lifted stay lifted: by their author, by an
-- administrator, or because the text changed (the rule of before).
UPDATE signals SET phase = 'lifted', lift = CASE
WHEN lifted_by = 'revision' THEN 'revision'
WHEN lifted_by = author_id THEN 'objector'
ELSE 'admin' END
WHERE lifted_at IS NOT NULL;
-- A standing one whose other side left (withdrawn, or never submitted) ends: a
-- withdrawal ends the objection, which the rule of before did not do.
UPDATE signals SET phase = 'lifted', lift = 'withdrawn', lifted_by = 'withdrawn',
lifted_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
WHERE lifted_at IS NULL AND EXISTS (
SELECT 1 FROM proposals p
WHERE p.id IN (signals.proposal_id, signals.target_proposal_id) AND p.status NOT IN ('open', 'in_force'));
-- The standing ones wait for the author of the version they now hold back: the
-- latest arrival of the two (submitted last; the same instant: written last),
-- unless it is in force — then the other. Both in force: none is held.
UPDATE signals SET held_id = (
SELECT CASE
WHEN a.status = 'in_force' AND b.status = 'in_force' THEN NULL
WHEN (IFNULL(a.submitted_at, a.created_at), a.rowid, a.id) > (IFNULL(b.submitted_at, b.created_at), b.rowid, b.id)
THEN CASE WHEN a.status = 'in_force' THEN b.id ELSE a.id END
ELSE CASE WHEN b.status = 'in_force' THEN a.id ELSE b.id END
END
FROM proposals a, proposals b
WHERE a.id = signals.proposal_id AND b.id = signals.target_proposal_id)
WHERE lifted_at IS NULL;
CREATE INDEX signals_proposal ON signals(proposal_id);
CREATE INDEX signals_target ON signals(target_proposal_id);
CREATE INDEX signals_due ON signals(phase, due_at);
-- One person, one standing objection on a pair, whichever way it was written
-- (relecture of cd7e683: sent four times at once, four stood).
CREATE UNIQUE INDEX signals_one_standing
ON signals(author_id, min(proposal_id, target_proposal_id), max(proposal_id, target_proposal_id))
WHERE lifted_at IS NULL;
-- A proposal written to answer an objection (« modifier l'article visé »).
ALTER TABLE proposals ADD COLUMN objection_id TEXT;
-- A typo fix written by someone other than the one who answers for the version:
-- it waits for them (or for the deadline), then applies — or not.
CREATE TABLE typos (
id TEXT PRIMARY KEY,
proposal_id TEXT NOT NULL REFERENCES proposals(id),
doc_id TEXT NOT NULL REFERENCES documents(id),
writer_id TEXT NOT NULL REFERENCES identities(id), -- who wrote the fix
answerer_id TEXT, -- the author of the version, who answers; NULL = administrators (no author)
revision INTEGER NOT NULL, -- the revision it was written over
base_title TEXT NOT NULL, -- the text it was written over
base_body TEXT NOT NULL,
title TEXT NOT NULL, -- the fix
body TEXT NOT NULL,
status TEXT NOT NULL, -- pending | applied | refused | stale
created_at TEXT NOT NULL,
due_at TEXT NOT NULL, -- applied by itself then, if nobody answered
settled_at TEXT,
settled_by TEXT -- identity id, 'deadline', or 'changed' (stale)
);
CREATE INDEX typos_proposal ON typos(proposal_id, status);
CREATE INDEX typos_due ON typos(status, due_at);
-- The revision a validated fix wrote, or the one that took it back (kind 'revert'),
-- and who let it in: the identity that validated it, or 'deadline'.
ALTER TABLE revisions ADD COLUMN typo_id TEXT;
ALTER TABLE revisions ADD COLUMN answered_by TEXT;
-- The messages of trustinWallet: one person, one box. The text is told by the
-- interface from the subject (in the language of the reader); the gestures
-- follow the subject's state, so a message dealt with offers none.
CREATE TABLE messages (
id TEXT PRIMARY KEY,
recipient_id TEXT NOT NULL REFERENCES identities(id),
doc_id TEXT NOT NULL REFERENCES documents(id),
topic TEXT NOT NULL, -- objection | typo
subject_id TEXT NOT NULL, -- signals.id | typos.id
kind TEXT NOT NULL, -- objection_raised | objection_reiterated | objection_answered | typo_pending
cycle INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL,
due_at TEXT,
read_at TEXT,
done_at TEXT,
outcome TEXT -- answered | lifted | reiterated | deadline | admin | withdrawn | applied | refused | stale
);
CREATE INDEX messages_box ON messages(recipient_id, created_at);
CREATE INDEX messages_subject ON messages(topic, subject_id);