Files
Jyotisha/tests/test_birth_time_dynamic_persistence_contract.py
T
2026-07-19 07:20:40 +08:00

194 lines
7.9 KiB
Python

import re
from pathlib import Path
MIGRATION = (
Path(__file__).resolve().parents[1]
/ "frontend"
/ "supabase"
/ "migrations"
/ "20260718090000_dynamic_choice_birth_time_rectification.sql"
)
TRANSITIONS_MIGRATION = MIGRATION.with_name(
"20260718091000_dynamic_choice_birth_time_transitions.sql"
)
LEGACY_GUARD_MIGRATIONS = (
MIGRATION.with_name("20260718092000_legacy_scoring_protocol_guards.sql"),
MIGRATION.with_name("20260718093000_legacy_candidate_protocol_guards.sql"),
)
def _sql() -> str:
source = "\n".join(
path.read_text(encoding="utf-8") for path in (MIGRATION, TRANSITIONS_MIGRATION)
)
return re.sub(r"\s+", " ", source.lower()).strip()
def _function(sql: str, name: str, next_name: str | None = None) -> str:
body = sql.split(f"create or replace function public.{name}", 1)[1]
return body.split(
f"create or replace function public.{next_name}" if next_name else "$$;",
1,
)[0]
def test_private_dynamic_state_is_service_role_only_and_bounded() -> None:
sql = _sql()
assert "journey_protocol text not null default 'legacy-guided-v1'" in sql
assert "check (journey_protocol in ('legacy-guided-v1', 'dynamic-choice-v2'))" in sql
assert "create table if not exists public.birth_time_rectification_dynamic_state" in sql
for definition in (
"candidate_model jsonb",
"current_choice_question jsonb",
"choice_answers jsonb not null default '[]'::jsonb",
"choice_evidence jsonb not null default '[]'::jsonb",
"dynamic_control jsonb not null",
"agent_context jsonb not null default '[]'::jsonb",
):
assert definition in sql
assert "jsonb_array_length(choice_answers) <= 50" in sql
assert "jsonb_array_length(choice_evidence) <= 10" in sql
assert "jsonb_array_length(agent_context) <= 10" in sql
assert "birth_time_dynamic_agent_context_valid(agent_context)" in sql
assert "pg_catalog.length(note) > 240" in sql
assert "alter table public.birth_time_rectification_dynamic_state enable row level security" in sql
assert "revoke all on table public.birth_time_rectification_dynamic_state from anon, authenticated" in sql
assert "grant all on table public.birth_time_rectification_dynamic_state to service_role" in sql
def test_dynamic_case_creation_is_one_service_role_transaction() -> None:
sql = _sql()
body = _function(sql, "create_birth_time_dynamic_case", "save_birth_time_dynamic_turn")
assert "security definer" in body
assert "set search_path = ''" in body
assert "insert into public.birth_time_rectification_cases" in body
assert "perform public.persist_birth_time_dynamic_private_state" in body
assert "update public.profiles" in body
assert "raise exception 'birth_time_dynamic_profile_not_found'" in body
assert "revoke all on function public.create_birth_time_dynamic_case" in sql
assert "grant execute on function public.create_birth_time_dynamic_case" in sql
def test_dynamic_case_creation_updates_only_profile_rectification_metadata() -> None:
body = _function(
_sql(), "create_birth_time_dynamic_case", "save_birth_time_dynamic_turn"
)
profile_update = body.split("update public.profiles", 1)[1].split(
"where id = p_user_id", 1
)[0]
assignments = set(re.findall(r"([a-z_]+)\s*=", profile_update))
assert assignments == {
"reported_birth_time",
"birth_time_source",
"birth_time_period",
"birth_time_clue",
"uncertainty_before_minutes",
"uncertainty_after_minutes",
"birth_time_status",
"rectification_confidence",
"rectification_case_id",
}
def test_dynamic_turn_rpc_is_versioned_private_and_replay_safe() -> None:
sql = _sql()
body = _function(sql, "save_birth_time_dynamic_turn", "upgrade_birth_time_legacy_case")
for invariant in (
"security definer",
"set search_path = ''",
"c.user_id = p_user_id",
"v_case.journey_protocol is distinct from 'dynamic-choice-v2'",
"p_action_id = any(v_case.processed_action_ids)",
"v_case.turn_version is distinct from p_expected_version",
"raise exception 'stale_birth_time_dynamic_turn'",
"update public.birth_time_rectification_cases",
"perform public.persist_birth_time_dynamic_private_state",
):
assert invariant in body
assert "revoke all on function public.save_birth_time_dynamic_turn" in sql
assert "grant execute on function public.save_birth_time_dynamic_turn" in sql
def test_dynamic_scoring_rpcs_bind_job_identity_and_replay_state() -> None:
sql = _sql()
for function_name in (
"complete_birth_time_dynamic_scoring_job",
"fail_birth_time_dynamic_scoring_job",
):
body = _function(sql, function_name)
for invariant in (
"security definer",
"set search_path = ''",
"j.case_id = p_case_id",
"j.user_id = p_user_id",
"v_job.evidence_fingerprint is distinct from p_evidence_fingerprint",
"v_job.algorithm_version is distinct from p_algorithm_version",
"v_case.turn_version is distinct from p_expected_version",
"coalesce(v_case.turn_state #>> '{nextaction,kind}', '') not in",
"p_job_id::text",
"perform public.persist_birth_time_dynamic_private_state",
):
assert invariant in body
assert f"revoke all on function public.{function_name}" in sql
assert f"grant execute on function public.{function_name}" in sql
complete = _function(
sql,
"complete_birth_time_dynamic_scoring_job",
"fail_birth_time_dynamic_scoring_job",
)
assert "v_job.status = 'completed'" in complete
assert "v_job.result is distinct from p_candidate_result" in complete
assert "p_candidate_result ->> 'algorithmversion'" in complete
failed = _function(sql, "fail_birth_time_dynamic_scoring_job")
assert "v_job.status = 'failed'" in failed
assert "v_job.failure_code is distinct from p_failure_code" in failed
def test_private_state_upsert_has_one_internal_owner_only_implementation() -> None:
sql = _sql()
body = _function(
sql,
"persist_birth_time_dynamic_private_state",
"create_birth_time_dynamic_case",
)
assert "insert into public.birth_time_rectification_dynamic_state" in body
assert "on conflict (case_id) do update" in body
assert sql.count("insert into public.birth_time_rectification_dynamic_state") == 1
assert "revoke all on function public.persist_birth_time_dynamic_private_state" in sql
def test_legacy_rpc_writes_lock_and_reject_upgraded_cases_atomically() -> None:
source = "\n".join(
path.read_text(encoding="utf-8").lower() for path in LEGACY_GUARD_MIGRATIONS
)
guarded_functions = (
"create_birth_time_scoring_job",
"claim_birth_time_scoring_job",
"complete_birth_time_scoring_job",
"fail_birth_time_scoring_job",
"confirm_birth_time_candidate",
"save_guided_birth_time_candidate",
"confirm_guided_birth_time_candidate",
)
for function_name in guarded_functions:
wrapper = source.split(f"create function public.{function_name}(", 1)[1]
wrapper = wrapper.split("$$;", 1)[0]
assert "journey_protocol = 'legacy-guided-v1' for update" in wrapper
assert "birth_time_legacy_protocol_required" in wrapper
assert f"public.{function_name}_without_protocol_guard" in wrapper
assert (
f"revoke all on function public.{function_name}_without_protocol_guard"
in source
)
def test_new_protocol_guard_migrations_stay_within_review_budget() -> None:
for path in LEGACY_GUARD_MIGRATIONS:
pure_lines = [
line for line in path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.lstrip().startswith("--")
]
assert len(pure_lines) <= 250