feat: complete verifiable birth-time rectification flow
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
begin;
|
||||
|
||||
alter table public.chat_sessions
|
||||
add column if not exists session_type text not null default 'consultation'
|
||||
check (session_type in ('consultation', 'birth_time_rectification')),
|
||||
add column if not exists rectification_case_id uuid
|
||||
references public.birth_time_rectification_cases(id) on delete set null;
|
||||
|
||||
grant insert (session_type, rectification_case_id)
|
||||
on table public.chat_sessions to authenticated;
|
||||
grant update (session_type, rectification_case_id)
|
||||
on table public.chat_sessions to authenticated;
|
||||
|
||||
create index if not exists chat_sessions_rectification_case_idx
|
||||
on public.chat_sessions (user_id, rectification_case_id)
|
||||
where rectification_case_id is not null;
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,97 @@
|
||||
-- Complete conversational rectification with a saved range when evidence can
|
||||
-- no longer justify additional questions. This deliberately does not update
|
||||
-- the account's active birth minute.
|
||||
|
||||
create or replace function public.complete_conversational_rectification_with_range(
|
||||
p_user_id uuid,
|
||||
p_case_id uuid,
|
||||
p_expected_version bigint,
|
||||
p_action_id uuid,
|
||||
p_turn jsonb,
|
||||
p_evidence jsonb,
|
||||
p_validation_receipt jsonb,
|
||||
p_private_candidate jsonb,
|
||||
p_command_fingerprint text default null
|
||||
)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
declare
|
||||
v_active_turn jsonb;
|
||||
v_response jsonb;
|
||||
v_expected_actions jsonb;
|
||||
begin
|
||||
v_expected_actions := case
|
||||
when p_turn -> 'pendingConsultationQuestion' = 'null'::jsonb then '[]'::jsonb
|
||||
else '["continue_original_question"]'::jsonb
|
||||
end;
|
||||
if public.conversational_rectification_valid_public_turn(p_turn) is not true
|
||||
or p_turn ->> 'status' is distinct from 'completed'
|
||||
or p_turn #>> '{candidate,status}' is distinct from 'pending_validation'
|
||||
or p_turn -> 'evidenceRequest' is distinct from 'null'::jsonb
|
||||
or p_turn -> 'actions' is distinct from v_expected_actions then
|
||||
raise exception 'conversational_action_conflict' using errcode = 'P0001';
|
||||
end if;
|
||||
|
||||
-- Reuse the established append-only evidence, candidate and idempotency
|
||||
-- transaction. The terminal projection is applied below in the same SQL
|
||||
-- transaction, so no active intermediate state can escape to another client.
|
||||
v_active_turn := pg_catalog.jsonb_set(p_turn, '{status}', '"active"'::jsonb, false);
|
||||
v_active_turn := pg_catalog.jsonb_set(v_active_turn, '{actions}', '[]'::jsonb, false);
|
||||
v_response := public.save_conversational_rectification_turn(
|
||||
p_user_id,
|
||||
p_case_id,
|
||||
p_expected_version,
|
||||
p_action_id,
|
||||
v_active_turn,
|
||||
p_evidence,
|
||||
p_validation_receipt,
|
||||
p_private_candidate,
|
||||
p_command_fingerprint
|
||||
);
|
||||
|
||||
update public.birth_time_rectification_turns
|
||||
set narrative = p_turn ->> 'narrative',
|
||||
evidence_request = null,
|
||||
actions = p_turn -> 'actions'
|
||||
where case_id = p_case_id
|
||||
and turn_version = p_expected_version + 1;
|
||||
if not found then
|
||||
raise exception 'conversational_stale_turn' using errcode = 'P0001';
|
||||
end if;
|
||||
|
||||
update public.birth_time_rectification_cases
|
||||
set status = 'completed',
|
||||
turn_state = p_turn,
|
||||
journey_snapshot = p_turn,
|
||||
updated_at = pg_catalog.now()
|
||||
where id = p_case_id
|
||||
and user_id = p_user_id
|
||||
and turn_version = p_expected_version + 1;
|
||||
if not found then
|
||||
raise exception 'conversational_stale_turn' using errcode = 'P0001';
|
||||
end if;
|
||||
|
||||
v_response := public.conversational_rectification_case_projection(p_user_id, p_case_id);
|
||||
update public.birth_time_rectification_action_receipts
|
||||
set response = v_response
|
||||
where case_id = p_case_id
|
||||
and action_id = p_action_id
|
||||
and user_id = p_user_id
|
||||
and action_kind = 'save_turn'
|
||||
and expected_turn_version = p_expected_version;
|
||||
if not found then
|
||||
raise exception 'conversational_action_conflict' using errcode = 'P0001';
|
||||
end if;
|
||||
return v_response;
|
||||
end;
|
||||
$$;
|
||||
|
||||
revoke all on function public.complete_conversational_rectification_with_range(
|
||||
uuid, uuid, bigint, uuid, jsonb, jsonb, jsonb, jsonb, text
|
||||
) from public, anon;
|
||||
grant execute on function public.complete_conversational_rectification_with_range(
|
||||
uuid, uuid, bigint, uuid, jsonb, jsonb, jsonb, jsonb, text
|
||||
) to authenticated, service_role;
|
||||
Reference in New Issue
Block a user