Files
Jyotisha/frontend/supabase/migrations/20260904010000_read_report_candidate_range.sql
T
Jesse_Chen 7baf230066 fix(report): load candidate ranges through a read-only RPC
Accepted profiles were selecting a revoked rectification table and failing the report before the engine ran. Degrade to a null window when that optional read fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 19:17:14 +08:00

78 lines
2.0 KiB
PL/PgSQL

-- Read-only candidate window for personal reports. Direct table grants on
-- agentic_rectification_cases stay revoked; this RPC is the only service_role
-- path. Failure to find a row returns null. The function never returns any
-- column except start_time / end_time.
begin;
do $migration$
begin
if current_user <> 'schema_owner' then
raise exception 'read_report_candidate_range_requires_schema_owner'
using errcode = '42501';
end if;
end
$migration$;
create or replace function public.read_report_candidate_range(
p_user_id uuid,
p_rectification_case_id uuid default null
)
returns jsonb
language plpgsql
stable
security definer
set search_path = ''
as $$
declare
v_start text;
v_end text;
v_range jsonb;
begin
if p_user_id is null then
return null;
end if;
if p_rectification_case_id is not null then
select to_char(c.candidate_start, 'HH24:MI'), to_char(c.candidate_end, 'HH24:MI')
into v_start, v_end
from public.birth_time_rectification_cases as c
where c.id = p_rectification_case_id
and c.user_id = p_user_id
and c.status in ('confirmed', 'completed')
and c.candidate_start is not null
and c.candidate_end is not null;
if found then
return jsonb_build_object('start_time', v_start, 'end_time', v_end);
end if;
end if;
select c.candidate_range
into v_range
from public.agentic_rectification_cases as c
where c.user_id = p_user_id
and c.status = 'candidate_accepted'
order by c.updated_at desc
limit 1;
if v_range is null then
return null;
end if;
v_start := nullif(btrim(coalesce(v_range->>'start_time', '')), '');
v_end := nullif(btrim(coalesce(v_range->>'end_time', '')), '');
if v_start is null or v_end is null then
return null;
end if;
return jsonb_build_object('start_time', v_start, 'end_time', v_end);
end;
$$;
revoke all on function public.read_report_candidate_range(uuid, uuid)
from public, anon, authenticated;
grant execute on function public.read_report_candidate_range(uuid, uuid)
to service_role;
commit;