begin; create or replace function public.insert_agentic_rectification_tool_receipt( p_user_id uuid, p_case_id uuid, p_turn_id uuid, p_tool_name text, p_public_phase text, p_status text, p_input_fingerprint text, p_result_fingerprint text, p_engine_version text, p_safe_error_code text, p_executed_methods jsonb, p_attempt_id uuid ) returns jsonb language plpgsql security definer set search_path = '' as $$ declare v_attempt public.agentic_rectification_run_attempts%rowtype; v_receipt_id uuid; begin if p_user_id is null or p_case_id is null or p_turn_id is null or p_attempt_id is null or p_tool_name not in ( 'rectification-read-case', 'rectification-set-focus', 'rectification-resolve-focus', 'rectification-record-evidence-batch', 'rectification-propose-evidence', 'rectification-confirm-evidence', 'rectification-revise-evidence', 'rectification-compare-candidates', 'rectification-read-diagnostics', 'rectification-offer-candidates', 'rectification-accept-candidate', 'rectification-confirm-birth-time', 'rectification-close-case' ) or p_public_phase not in ( 'run.started', 'skill.started', 'skill.loaded', 'skill.bound', 'case.loaded', 'intent.classified', 'evidence.proposed', 'evidence.confirmed', 'candidates.comparing', 'candidates.updated', 'diagnostics.completed', 'candidate.accepted', 'birth_time.confirmed', 'answer.composed', 'billing.settled', 'answer.delta', 'run.completed', 'run.failed' ) or p_status not in ('started', 'completed', 'failed', 'skipped') or p_executed_methods is null or jsonb_typeof(p_executed_methods) <> 'array' or exists ( select 1 from jsonb_array_elements_text(p_executed_methods) method(value) where method.value not in ( 'd1-rashi', 'd2-hora', 'd4-chaturthamsha', 'd5-panchamsha', 'd7-saptamsha', 'd9-navamsa', 'd10-dashamsa', 'd11-labhamsha', 'd12-dwadashamsha', 'd24-chaturvimshamsha', 'd30-trimshamsha', 'vimshottari-dasha', 'narayana-dasha', 'gochara', 'ashtakavarga', 'shadbala', 'arudha-pada', 'functional-benefic-malefic' ) ) then raise exception 'agentic_rectification_invalid_input' using errcode = 'P0001'; end if; if not exists ( select 1 from public.agentic_rectification_cases where id = p_case_id and user_id = p_user_id ) then raise exception 'agentic_rectification_case_not_found' using errcode = 'P0001'; end if; if not exists ( select 1 from public.agentic_rectification_turns where id = p_turn_id and case_id = p_case_id ) then raise exception 'agentic_rectification_turn_not_found' using errcode = 'P0001'; end if; select * into v_attempt from public.agentic_rectification_run_attempts where id = p_attempt_id and case_id = p_case_id and turn_id = p_turn_id for update; if not found then raise exception 'agentic_rectification_attempt_not_found' using errcode = 'P0001'; end if; if v_attempt.status <> 'started' then raise exception 'agentic_rectification_attempt_not_started' using errcode = 'P0001'; end if; insert into public.agentic_rectification_tool_receipts ( case_id, turn_id, attempt_id, tool_name, public_phase, status, input_fingerprint, result_fingerprint, engine_version, safe_error_code, executed_methods, completed_at ) values ( p_case_id, p_turn_id, p_attempt_id, p_tool_name, p_public_phase, p_status, p_input_fingerprint, p_result_fingerprint, p_engine_version, p_safe_error_code, p_executed_methods, case when p_status = 'completed' then pg_catalog.now() else null end ) returning id into v_receipt_id; return jsonb_build_object('receipt_id', v_receipt_id, 'attempt_id', p_attempt_id); end; $$; revoke all on function public.insert_agentic_rectification_tool_receipt( uuid, uuid, uuid, text, text, text, text, text, text, text, jsonb, uuid ) from public, anon, authenticated; grant execute on function public.insert_agentic_rectification_tool_receipt( uuid, uuid, uuid, text, text, text, text, text, text, text, jsonb, uuid ) to service_role; commit;