Ajoute des justifications anonymes aux votes de L'Urne de l'Agora
Build and deploy / deploy (push) Successful in 35s

Un Citoyen peut désormais laisser un motif facultatif en déposant son
jeton (toujours deux étapes avant l'envoi). Le classement permet de
consulter les justifications reçues par une personne via une nouvelle RPC
urn_vote_reasons() — même principe que wall_notes_today : le contenu est
public, l'auteur ne l'est jamais, ce qui préserve la garantie de L'Urne
que personne (Archontes compris) ne voit qui a voté pour qui.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Valentin ROBIN
2026-08-23 22:48:25 +02:00
parent 0dfd3e7e90
commit e8a9a0ddb9
3 changed files with 199 additions and 38 deletions
+40 -6
View File
@@ -1148,7 +1148,8 @@ grant execute on function public.post_wall_note(text) to authenticated;
-- compris : contrairement à chariot_submissions/wall_notes, les Archontes
-- n'ont ici AUCUNE vision privilégiée sur qui a voté pour qui, seul le total
-- par personne est public. Les Archontes ne peuvent ni voter ni recevoir de
-- jetons.
-- jetons. Chaque vote peut porter une justification facultative, exposée de
-- façon anonyme (urn_vote_reasons) : le contenu est public, jamais l'auteur.
create table if not exists public.urn_votes (
id bigint generated always as identity primary key,
@@ -1157,6 +1158,11 @@ create table if not exists public.urn_votes (
created_at timestamptz not null default now()
);
-- Justification facultative laissée par le votant. Exposée ensuite de façon
-- anonyme via urn_vote_reasons() (voir plus bas) : le contenu est public,
-- jamais son auteur — cohérent avec le reste de la table.
alter table public.urn_votes add column if not exists reason text;
alter table public.urn_votes enable row level security;
revoke insert, update, delete on public.urn_votes from authenticated, anon;
grant select on public.urn_votes to authenticated;
@@ -1194,9 +1200,32 @@ $$;
grant execute on function public.urn_vote_counts() to authenticated;
-- Permet de comprendre pourquoi les gens ont voté pour quelqu'un sans jamais
-- révéler qui a voté quoi (même principe que wall_notes_today : le contenu
-- est exposé, l'identité du votant jamais) — visible par tous depuis le
-- classement, Archontes compris (même vision que pour urn_vote_counts).
create or replace function public.urn_vote_reasons(p_target_id uuid)
returns table (reason text, created_at timestamptz)
language sql
security definer
set search_path = public
as $$
select v.reason, v.created_at
from public.urn_votes v
where v.target_id = p_target_id
and v.reason is not null
order by v.created_at desc;
$$;
grant execute on function public.urn_vote_reasons(uuid) to authenticated;
-- Seul point d'entrée pour voter. Un vote par Citoyen par jour, définitif
-- (aucune RPC de modification/suppression).
create or replace function public.cast_urn_vote(p_target_id uuid)
-- (aucune RPC de modification/suppression). La signature change (ajout de
-- p_reason) : l'ancienne (uuid) est explicitement supprimée, sinon
-- create or replace créerait une 2e surcharge au lieu de remplacer celle-ci.
drop function if exists public.cast_urn_vote(uuid);
create or replace function public.cast_urn_vote(p_target_id uuid, p_reason text default null)
returns public.urn_votes
language plpgsql
security definer
@@ -1207,6 +1236,7 @@ declare
v_target_role text;
v_today date := (now() at time zone 'Europe/Paris')::date;
v_already_voted boolean;
v_reason text := nullif(trim(coalesce(p_reason, '')), '');
v_row public.urn_votes;
begin
if auth.uid() is null then
@@ -1230,6 +1260,10 @@ begin
raise exception 'cannot vote for a judge';
end if;
if v_reason is not null and length(v_reason) > 200 then
raise exception 'justification trop longue';
end if;
select exists (
select 1 from public.urn_votes
where voter_id = auth.uid()
@@ -1239,12 +1273,12 @@ begin
raise exception 'already voted today';
end if;
insert into public.urn_votes (voter_id, target_id)
values (auth.uid(), p_target_id)
insert into public.urn_votes (voter_id, target_id, reason)
values (auth.uid(), p_target_id, v_reason)
returning * into v_row;
return v_row;
end;
$$;
grant execute on function public.cast_urn_vote(uuid) to authenticated;
grant execute on function public.cast_urn_vote(uuid, text) to authenticated;