from __future__ import annotations

import json
import re
import subprocess
from pathlib import Path

import pytest

from ops import verify_teleo_v3_epistemic_contract as verifier

REPO_ROOT = Path(__file__).resolve().parents[1]
MIGRATION_SQL = REPO_ROOT / "ops" / "teleo_v3_epistemic_contract.sql"
ROLLBACK_SQL = REPO_ROOT / "ops" / "rollback_teleo_v3_epistemic_contract.sql"
SECRET_STARTUP_MARKER = "secret-startup-marker"


def test_install_migration_is_additive_and_legacy_compatible() -> None:
    sql = MIGRATION_SQL.read_text(encoding="utf-8").lower()

    assert "add column if not exists" in sql
    assert "create table if not exists public.claim_evidence_assessments" in sql
    assert "admission_state text not null default 'legacy'" in sql
    assert "admission_state = 'legacy'" in sql
    assert "admission_state = 'admitted'" in sql
    assert "accepted_by_proposal_id" in sql
    assert "accepted_from_proposal_id" in sql
    assert "teleo_v3_require_linked_insert" in sql
    assert (
        "create or replace function kb_stage.teleo_v3_require_accepted_proposal()\nreturns trigger\nlanguage plpgsql\nsecurity definer"
        in sql
    )
    assert (
        "create or replace function kb_stage.teleo_v3_enforce_apply_contract_cutover()\n"
        "returns trigger\nlanguage plpgsql\nsecurity definer" in sql
    )
    assert "alter function kb_stage.teleo_v3_require_accepted_proposal() owner to kb_gate_owner" in sql
    assert "revoke all on function kb_stage.teleo_v3_require_accepted_proposal()" in sql
    assert "alter function kb_stage.teleo_v3_enforce_apply_contract_cutover() owner to kb_gate_owner" in sql
    assert "revoke all on function kb_stage.teleo_v3_enforce_apply_contract_cutover()" in sql
    assert "from public, kb_apply, kb_review" in sql
    assert "security definer trigger invariants failed" in sql
    assert "kb_gate_owner must be nologin noinherit and unprivileged" in sql
    for attribute in (
        "not role.rolcanlogin",
        "not role.rolinherit",
        "not role.rolsuper",
        "not role.rolcreatedb",
        "not role.rolcreaterole",
        "not role.rolreplication",
        "not role.rolbypassrls",
    ):
        assert attribute in sql
    assert "teleo_v3_reject_delete" in sql
    assert "teleo_v3_proposal_apply_receipt_check" in sql
    assert "create or replace trigger teleo_v3_claim_immutable" in sql
    assert "create or replace trigger teleo_v3_guard_linked_proposal_decision" in sql
    assert "'status', 'admission_state'" in sql
    assert "'updated_at', 'accepted_by_proposal_id'" in sql
    assert "legacy is reserved for rows present at migration" in sql
    assert "cutover order: deploy the cutover-aware writer" in sql
    assert "alter role kb_apply nologin" in sql
    assert "active kb_apply sessions must exit" in sql
    assert "retains % pending/approved v2 proposal(s) for explicit migration or rejection" in sql
    assert "teleo_v3_00_enforce_apply_contract_cutover" in sql
    assert "teleo_v3_enforce_apply_contract_cutover" in sql
    assert sql.count("create or replace trigger teleo_v3_") == 24
    assert re.search(r"(?m)^\s*create trigger teleo_v3_", sql) is None
    assert "actual.tgenabled = 'o'" in sql
    assert "actual.tgtype = expected.trigger_type" in sql
    assert "actual.update_columns = expected.update_columns" in sql
    assert "actual.when_expression is not distinct from expected.when_expression" in sql
    assert "actual.argument_hex = expected.argument_hex" in sql
    assert "actual.tgconstraint = 0::pg_catalog.oid" in sql
    assert "actual.tgoldtable is null" in sql
    assert "actual.tgnewtable is null" in sql
    assert "actual.tgfoid" in sql
    assert "actual.function_security_definer = expected.function_security_definer" in sql
    assert "actual.function_source_sha256 = expected.function_source_sha256" in sql
    assert "acl.grantee <> procedure.proowner" in sql
    assert "protected role membership drift must be removed" in sql
    assert "teleo_v3_contract_postflight_query_begin" in sql
    assert "alter function %i.%i() owner to kb_gate_owner" in sql
    assert "jsonb_typeof(new.payload->'apply_payload'->'contract_version') = 'number'" in sql
    assert "migrate or reject it" in sql
    assert "for share" in sql
    assert "source_content_hash" in sql
    assert "locator_json" in sql
    assert "relation_type in ('supports', 'challenges', 'depends_on', 'contradicts')" in sql
    assert "preexisting v3 schema objects lack installation ownership" in sql
    assert "create table if not exists kb_stage.teleo_v3_installation_ownership" in sql
    assert "installation_token = 'collision-free-install-v1'" in sql
    assert "alter table kb_stage.teleo_v3_installation_ownership owner to kb_gate_owner" in sql

    destructive_patterns = (
        r"\bdrop\s+",
        r"\btruncate\b",
        r"\bdelete\s+from\b",
        r"\bupdate\s+public\.",
        r"\balter\s+type\b",
    )
    for pattern in destructive_patterns:
        assert re.search(pattern, sql) is None, pattern


def test_rollback_refuses_silent_v3_data_loss_before_dropping_contract() -> None:
    sql = ROLLBACK_SQL.read_text(encoding="utf-8").lower()

    guard_position = sql.index("teleo_v3 rollback refused")
    first_drop_position = sql.index("drop trigger")
    assert guard_position < first_drop_position
    assert "claim_evidence_assessments contains v3 data" in sql
    assert "claims contains admitted or proposal-linked v3 data" in sql
    assert "drop column if exists proposition" in sql
    assert "drop function if exists kb_stage.teleo_v3_require_accepted_proposal" in sql
    assert "drop function if exists kb_stage.teleo_v3_require_linked_insert" in sql
    assert "drop function if exists kb_stage.teleo_v3_reject_delete" in sql
    assert "drop function if exists kb_stage.teleo_v3_acquire_protected_relation_locks" in sql
    assert "drop function if exists kb_stage.teleo_v3_enforce_apply_contract_cutover" in sql
    assert "drop constraint if exists teleo_v3_proposal_apply_receipt_check" in sql
    assert "installation ownership ledger is not exact" in sql
    assert "v3-named objects lack exact installation ownership" in sql
    assert "drop table if exists kb_stage.teleo_v3_installation_ownership" in sql


@pytest.mark.parametrize(
    ("logs", "probe_returncode", "probe_stdout", "expected"),
    (
        (verifier.POSTGRES_READY_LOG_LINE, 0, "1\n", False),
        (f"{verifier.POSTGRES_READY_LOG_LINE}\n{verifier.POSTGRES_READY_LOG_LINE}", 2, "", False),
        (f"{verifier.POSTGRES_READY_LOG_LINE}\n{verifier.POSTGRES_READY_LOG_LINE}", 0, "", False),
        (f"{verifier.POSTGRES_READY_LOG_LINE}\n{verifier.POSTGRES_READY_LOG_LINE}", 0, "1\n", True),
    ),
)
def test_postgres_final_startup_requires_second_transition_and_target_database(
    logs: str,
    probe_returncode: int,
    probe_stdout: str,
    expected: bool,
) -> None:
    probe = subprocess.CompletedProcess(["psql"], probe_returncode, stdout=probe_stdout, stderr="")

    assert verifier.postgres_final_startup_ready(logs, probe) is expected


def _startup_test_postgres() -> verifier.DisposablePostgres:
    postgres = object.__new__(verifier.DisposablePostgres)
    postgres.docker = "docker"
    postgres.name = "teleo-v3-contract-test"
    postgres.password = SECRET_STARTUP_MARKER
    postgres.started = True
    postgres.cleanup_required = True
    postgres.environment = {}
    return postgres


@pytest.mark.parametrize("as_bytes", (False, True))
def test_startup_detail_redacts_secret_before_tail_limit(as_bytes: bool) -> None:
    postgres = _startup_test_postgres()
    postgres.password = "K8VN3PQ7RM2TX6ZC9WB4HJ5DF1GS0LAE8YU3IO2N"
    context = "context=database-unavailable|"
    trailer = "|stage=target_database_probe|kind=timeout"
    suffix_length = 500 - len(context) - len("<redacted>")
    suffix = ("x" * (suffix_length - len(trailer))) + trailer
    diagnostic = context + postgres.password + suffix
    value: str | bytes = diagnostic.encode() if as_bytes else diagnostic

    assert len(diagnostic) > 500
    assert len(diagnostic) - 500 > len(context)

    detail = postgres._redacted_startup_detail(value)

    assert detail.startswith(f"{context}<redacted>")
    assert detail.endswith(trailer)
    assert postgres.password not in detail
    assert all(postgres.password[offset : offset + 4] not in detail for offset in range(len(postgres.password) - 3))


def test_docker_run_timeout_is_secret_safe_and_reconciles_owned_side_effect(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    postgres = _startup_test_postgres()
    postgres.password = "K8VN3PQ7RM2TX6ZC9WB4HJ5DF1GS0LAE8YU3IO2N"
    postgres.started = False
    postgres.cleanup_required = False
    owned_container_id = "a" * 64
    owned_container_exists = [True]
    calls: list[tuple[list[str], dict[str, str] | None]] = []
    context = "context=docker-daemon-accepted-request|"
    trailer = "|stage=docker_run|kind=timeout"
    suffix_length = 500 - len(context) - len("<redacted>")
    timeout_stderr = context + postgres.password + ("x" * (suffix_length - len(trailer))) + trailer

    def fake_run(
        arguments: list[str],
        *,
        input_text: str | None = None,
        check: bool = True,
        timeout: float = 120,
        environment: dict[str, str] | None = None,
    ) -> subprocess.CompletedProcess[str]:
        del input_text, check
        calls.append((list(arguments), environment))
        if arguments[0] == "run":
            assert postgres.cleanup_required is True
            assert postgres.started is False
            assert postgres.password not in " ".join(arguments)
            assert environment is not None
            assert environment["POSTGRES_PASSWORD"] == postgres.password
            secret_bearing_command = ["docker", *arguments, f"adjacent={postgres.password}"]
            raise subprocess.TimeoutExpired(
                secret_bearing_command,
                timeout,
                stderr=timeout_stderr,
            )
        if arguments[:2] == ["container", "ls"] and arguments[-1] == "{{.ID}}":
            stdout = f"{owned_container_id}\n" if owned_container_exists[0] else ""
            return subprocess.CompletedProcess(arguments, 0, stdout=stdout, stderr="")
        if arguments[:2] == ["rm", "--force"]:
            assert arguments == ["rm", "--force", owned_container_id]
            owned_container_exists[0] = False
            return subprocess.CompletedProcess(arguments, 0, stdout=owned_container_id, stderr="")
        if arguments[0] == "inspect":
            return subprocess.CompletedProcess(
                arguments,
                0 if owned_container_exists[0] else 1,
                stdout="[]" if owned_container_exists[0] else "",
                stderr="" if owned_container_exists[0] else "not found",
            )
        if arguments[:2] == ["container", "ls"] and arguments[-1] == "{{.Names}}":
            stdout = f"{postgres.name}\n" if owned_container_exists[0] else ""
            return subprocess.CompletedProcess(arguments, 0, stdout=stdout, stderr="")
        raise AssertionError(f"unexpected docker arguments: {arguments}")

    monkeypatch.setattr(postgres, "run", fake_run)
    monkeypatch.setattr(verifier.time, "sleep", lambda _seconds: None)

    with pytest.raises(verifier.VerificationError) as exc_info:
        postgres.start()
    cleanup = postgres.cleanup()

    error = str(exc_info.value)
    assert "launch state is ambiguous; cleanup_required=true" in error
    assert "stage=docker_run kind=timeout timeout_seconds=120" in error
    assert error.endswith(trailer)
    assert exc_info.value.__suppress_context__ is True
    assert postgres.password not in error
    assert all(postgres.password[offset : offset + 4] not in error for offset in range(len(postgres.password) - 3))
    assert postgres.started is False
    assert cleanup["cleanup_reconciliation_attempted"] is True
    assert cleanup["remove_attempted"] is True
    assert cleanup["remove_returncodes"] == [0]
    assert cleanup["owned_container_ids_observed"] == [owned_container_id]
    assert cleanup["container_absent"] is True
    assert cleanup["name_readback_clear"] is True
    assert cleanup["instance_label_readback_clear"] is True
    assert cleanup["stable_absence_readback"] is True
    ownership_call = next(arguments for arguments, _environment in calls if arguments[-1] == "{{.ID}}")
    assert f"name=^/{postgres.name}$" in ownership_call
    assert f"label={verifier.CONTAINER_LABEL}" in ownership_call
    assert f"label=livingip.canary.instance={postgres.name}" in ownership_call


def test_docker_run_normal_launch_marks_cleanup_before_execution(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    postgres = _startup_test_postgres()
    postgres.started = False
    postgres.cleanup_required = False
    container_id = "b" * 64
    waited_for_startup: list[bool] = []

    def fake_run(
        arguments: list[str],
        *,
        input_text: str | None = None,
        check: bool = True,
        timeout: float = 120,
        environment: dict[str, str] | None = None,
    ) -> subprocess.CompletedProcess[str]:
        del input_text, check, timeout
        if arguments[0] == "run":
            assert postgres.cleanup_required is True
            assert postgres.started is False
            assert postgres.password not in " ".join(arguments)
            assert environment is not None
            assert environment["POSTGRES_PASSWORD"] == postgres.password
            return subprocess.CompletedProcess(arguments, 0, stdout=f"{container_id}\n", stderr="")
        assert arguments == ["inspect", postgres.name]
        inspected = [
            {
                "Config": {
                    "Image": verifier.POSTGRES_IMAGE,
                    "Labels": {
                        "livingip.canary": "teleo-v3-epistemic-contract",
                        "livingip.canary.instance": postgres.name,
                    },
                },
                "HostConfig": {
                    "NetworkMode": "none",
                    "Tmpfs": {"/var/lib/postgresql/data": "rw,nosuid,nodev,size=384m"},
                },
                "Image": "sha256:postgres-image",
                "Mounts": [],
            }
        ]
        return subprocess.CompletedProcess(arguments, 0, stdout=json.dumps(inspected), stderr="")

    def fake_wait_for_final_startup() -> None:
        assert postgres.cleanup_required is True
        assert postgres.started is True
        waited_for_startup.append(True)

    monkeypatch.setattr(postgres, "run", fake_run)
    monkeypatch.setattr(postgres, "_wait_for_final_startup", fake_wait_for_final_startup)

    environment = postgres.start()

    assert waited_for_startup == [True]
    assert postgres.started is True
    assert postgres.cleanup_required is True
    assert environment["container_name"] == postgres.name
    assert environment["network_mode"] == "none"
    assert environment["tmpfs_data_dir"] is True
    assert environment["docker_volume_mounts"] == []


def test_cleanup_never_removes_foreign_exact_name_without_instance_labels(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    postgres = _startup_test_postgres()
    postgres.started = False
    postgres.cleanup_required = True
    calls: list[list[str]] = []

    def fake_run(
        arguments: list[str],
        *,
        input_text: str | None = None,
        check: bool = True,
        timeout: float = 120,
        environment: dict[str, str] | None = None,
    ) -> subprocess.CompletedProcess[str]:
        del input_text, check, timeout, environment
        calls.append(list(arguments))
        if arguments[:2] == ["container", "ls"] and arguments[-1] == "{{.ID}}":
            return subprocess.CompletedProcess(arguments, 0, stdout="", stderr="")
        if arguments[0] == "inspect":
            return subprocess.CompletedProcess(arguments, 0, stdout="[]", stderr="")
        if arguments[:2] == ["container", "ls"] and arguments[-1] == "{{.Names}}":
            has_instance_filter = f"label=livingip.canary.instance={postgres.name}" in arguments
            stdout = "" if has_instance_filter else f"{postgres.name}\n"
            return subprocess.CompletedProcess(arguments, 0, stdout=stdout, stderr="")
        raise AssertionError(f"unexpected docker arguments: {arguments}")

    monkeypatch.setattr(postgres, "run", fake_run)
    monkeypatch.setattr(verifier.time, "sleep", lambda _seconds: None)

    cleanup = postgres.cleanup()

    assert not any(arguments[:2] == ["rm", "--force"] for arguments in calls)
    assert cleanup["remove_attempted"] is False
    assert cleanup["foreign_name_collision_detected"] is True
    assert cleanup["container_absent"] is False
    assert cleanup["name_readback_clear"] is False
    assert cleanup["instance_label_readback_clear"] is True
    assert cleanup["stable_absence_readback"] is False


@pytest.mark.parametrize("hung_stage", ("docker_logs", "target_database_probe"))
def test_postgres_startup_commands_are_capped_to_remaining_deadline(
    monkeypatch: pytest.MonkeyPatch,
    hung_stage: str,
) -> None:
    postgres = _startup_test_postgres()
    now = [100.0]
    observed_timeouts: list[float] = []
    ready_logs = f"{verifier.POSTGRES_READY_LOG_LINE}\n{verifier.POSTGRES_READY_LOG_LINE}\n"

    def fake_run(
        arguments: list[str],
        *,
        input_text: str | None = None,
        check: bool = True,
        timeout: float = 120,
    ) -> subprocess.CompletedProcess[str]:
        del input_text, check
        assert arguments == ["logs", postgres.name]
        if hung_stage == "docker_logs":
            observed_timeouts.append(timeout)
            now[0] += timeout
            raise subprocess.TimeoutExpired(arguments, timeout, stderr=SECRET_STARTUP_MARKER)
        return subprocess.CompletedProcess(arguments, 0, stdout=ready_logs, stderr="")

    def fake_psql(
        sql: str,
        *,
        check: bool = True,
        timeout: float = 120,
    ) -> subprocess.CompletedProcess[str]:
        del check
        assert sql == "select 1;"
        observed_timeouts.append(timeout)
        now[0] += timeout
        raise subprocess.TimeoutExpired(["psql"], timeout, stderr=SECRET_STARTUP_MARKER)

    monkeypatch.setattr(verifier.time, "monotonic", lambda: now[0])
    monkeypatch.setattr(postgres, "run", fake_run)
    monkeypatch.setattr(postgres, "psql", fake_psql)

    with pytest.raises(verifier.VerificationError) as exc_info:
        postgres._wait_for_final_startup(startup_timeout=3.0, probe_timeout=120.0, poll_interval=0)

    assert observed_timeouts == [3.0]
    assert f"stage={hung_stage} kind=timeout timeout_seconds=3" in str(exc_info.value)
    assert SECRET_STARTUP_MARKER not in str(exc_info.value)


@pytest.mark.parametrize(
    ("failed_stage", "expected_context"),
    (
        ("docker_logs", "stage=docker_logs kind=nonzero returncode=17 detail=daemon <redacted>"),
        (
            "target_database_probe",
            "stage=target_database_probe kind=nonzero returncode=2 detail=database missing <redacted>",
        ),
    ),
)
def test_postgres_startup_failure_reports_sanitized_terminal_context(
    monkeypatch: pytest.MonkeyPatch,
    failed_stage: str,
    expected_context: str,
) -> None:
    postgres = _startup_test_postgres()
    now = [200.0]
    ready_logs = f"{verifier.POSTGRES_READY_LOG_LINE}\n{verifier.POSTGRES_READY_LOG_LINE}\n"

    def fake_run(
        arguments: list[str],
        *,
        input_text: str | None = None,
        check: bool = True,
        timeout: float = 120,
    ) -> subprocess.CompletedProcess[str]:
        del input_text, check, timeout
        assert arguments == ["logs", postgres.name]
        if failed_stage == "docker_logs":
            return subprocess.CompletedProcess(
                arguments,
                17,
                stdout="",
                stderr=f"daemon {SECRET_STARTUP_MARKER}",
            )
        return subprocess.CompletedProcess(arguments, 0, stdout=ready_logs, stderr="")

    def fake_psql(
        sql: str,
        *,
        check: bool = True,
        timeout: float = 120,
    ) -> subprocess.CompletedProcess[str]:
        del check, timeout
        assert sql == "select 1;"
        return subprocess.CompletedProcess(
            ["psql"],
            2,
            stdout="",
            stderr=f"database missing {SECRET_STARTUP_MARKER}",
        )

    def fake_sleep(seconds: float) -> None:
        now[0] += seconds

    monkeypatch.setattr(verifier.time, "monotonic", lambda: now[0])
    monkeypatch.setattr(verifier.time, "sleep", fake_sleep)
    monkeypatch.setattr(postgres, "run", fake_run)
    monkeypatch.setattr(postgres, "psql", fake_psql)

    with pytest.raises(verifier.VerificationError) as exc_info:
        postgres._wait_for_final_startup(startup_timeout=0.25, probe_timeout=10.0, poll_interval=0.25)

    error = str(exc_info.value)
    assert expected_context in error
    assert "within 0.25s after 1 attempt(s)" in error
    assert SECRET_STARTUP_MARKER not in error


@pytest.mark.skipif(not verifier.docker_available(), reason="Docker daemon is required")
def test_preexisting_v3_named_objects_are_never_adopted_or_rolled_back() -> None:
    postgres = verifier.DisposablePostgres()
    cleanup: dict[str, object] = {}
    try:
        postgres.start()
        postgres.psql(verifier.BOOTSTRAP_SQL)
        postgres.psql(
            """
alter table public.claims
  add column owner_agent_id uuid,
  add column proposition text,
  add column body_markdown text,
  add column scope text,
  add column access_scope text,
  add column admission_state text,
  add column revision_criteria text,
  add column revision_kind text,
  add column supersedes_id uuid,
  add column accepted_by_proposal_id uuid;
update public.claims
   set owner_agent_id = '11111111-1111-4111-8111-111111111111'::uuid,
       proposition = 'claims.proposition',
       body_markdown = 'claims.body_markdown',
       scope = 'claims.scope',
       access_scope = 'claims.access_scope',
       admission_state = 'claims.admission_state',
       revision_criteria = 'claims.revision_criteria',
       revision_kind = 'claims.revision_kind',
       supersedes_id = '20000000-0000-4000-8000-000000000002'::uuid,
       accepted_by_proposal_id = '30000000-0000-4000-8000-000000000003'::uuid
 where id = '20000000-0000-4000-8000-000000000001'::uuid;

alter table public.sources
  add column canonical_url text,
  add column storage_uri text,
  add column content_hash text,
  add column access_scope text,
  add column ingestion_origin text,
  add column provenance_status text,
  add column source_class text,
  add column auto_promotion_policy text,
  add column accepted_by_proposal_id uuid;
update public.sources
   set canonical_url = 'sources.canonical_url',
       storage_uri = 'sources.storage_uri',
       content_hash = 'sources.content_hash',
       access_scope = 'sources.access_scope',
       ingestion_origin = 'sources.ingestion_origin',
       provenance_status = 'sources.provenance_status',
       source_class = 'sources.source_class',
       auto_promotion_policy = 'sources.auto_promotion_policy',
       accepted_by_proposal_id = '30000000-0000-4000-8000-000000000003'::uuid
 where id = '20000000-0000-4000-8000-000000000003'::uuid;

alter table public.claim_evidence
  add column excerpt text,
  add column locator_json jsonb,
  add column source_content_hash text,
  add column rationale text,
  add column polarity text,
  add column accepted_from_proposal_id uuid;
update public.claim_evidence
   set excerpt = 'claim_evidence.excerpt',
       locator_json = '{"sentinel":"claim_evidence.locator_json"}'::jsonb,
       source_content_hash = 'claim_evidence.source_content_hash',
       rationale = 'claim_evidence.rationale',
       polarity = 'claim_evidence.polarity',
       accepted_from_proposal_id = '30000000-0000-4000-8000-000000000003'::uuid
 where id = '20000000-0000-4000-8000-000000000004'::uuid;

alter table public.claim_edges
  add column relation_type text,
  add column rationale text,
  add column scope_or_conditions text,
  add column accepted_by_proposal_id uuid;
update public.claim_edges
   set relation_type = 'claim_edges.relation_type',
       rationale = 'claim_edges.rationale',
       scope_or_conditions = 'claim_edges.scope_or_conditions',
       accepted_by_proposal_id = '30000000-0000-4000-8000-000000000003'::uuid
 where id = '20000000-0000-4000-8000-000000000005'::uuid;

create table public.claim_evidence_assessments (
  id uuid primary key,
  legacy_marker text
);
"""
        )
        state_sql = """
select jsonb_build_object(
  'claims', (
    select to_jsonb(row_data) from (
      select owner_agent_id, proposition, body_markdown, scope, access_scope, admission_state,
             revision_criteria, revision_kind, supersedes_id, accepted_by_proposal_id
        from public.claims
       where id = '20000000-0000-4000-8000-000000000001'::uuid
    ) row_data
  ),
  'sources', (
    select to_jsonb(row_data) from (
      select canonical_url, storage_uri, content_hash, access_scope, ingestion_origin,
             provenance_status, source_class, auto_promotion_policy, accepted_by_proposal_id
        from public.sources
       where id = '20000000-0000-4000-8000-000000000003'::uuid
    ) row_data
  ),
  'claim_evidence', (
    select to_jsonb(row_data) from (
      select excerpt, locator_json, source_content_hash, rationale, polarity, accepted_from_proposal_id
        from public.claim_evidence
       where id = '20000000-0000-4000-8000-000000000004'::uuid
    ) row_data
  ),
  'claim_edges', (
    select to_jsonb(row_data) from (
      select relation_type, rationale, scope_or_conditions, accepted_by_proposal_id
        from public.claim_edges
       where id = '20000000-0000-4000-8000-000000000005'::uuid
    ) row_data
  ),
  'assessment_columns', (
    select jsonb_agg(column_name order by ordinal_position)
      from information_schema.columns
     where table_schema = 'public' and table_name = 'claim_evidence_assessments'
  ),
  'assessment_rows', (select count(*) from public.claim_evidence_assessments),
  'ownership_ledger', to_regclass('kb_stage.teleo_v3_installation_ownership')::text
)::text;
"""
        before = postgres.psql_json(state_sql)

        install = postgres.apply_file(MIGRATION_SQL, check=False)
        rollback = postgres.apply_file(ROLLBACK_SQL, check=False)
        after = postgres.psql_json(state_sql)

        assert install.returncode != 0
        assert "preexisting V3 schema objects lack installation ownership" in install.stderr
        assert rollback.returncode != 0
        assert "V3-named objects lack exact installation ownership" in rollback.stderr
        assert before == after
        assert set(before["claims"]) == {
            "owner_agent_id",
            "proposition",
            "body_markdown",
            "scope",
            "access_scope",
            "admission_state",
            "revision_criteria",
            "revision_kind",
            "supersedes_id",
            "accepted_by_proposal_id",
        }
        assert set(before["sources"]) == {
            "canonical_url",
            "storage_uri",
            "content_hash",
            "access_scope",
            "ingestion_origin",
            "provenance_status",
            "source_class",
            "auto_promotion_policy",
            "accepted_by_proposal_id",
        }
        assert set(before["claim_evidence"]) == {
            "excerpt",
            "locator_json",
            "source_content_hash",
            "rationale",
            "polarity",
            "accepted_from_proposal_id",
        }
        assert set(before["claim_edges"]) == {
            "relation_type",
            "rationale",
            "scope_or_conditions",
            "accepted_by_proposal_id",
        }
        assert all(value is not None for value in before["claims"].values())
        assert all(value is not None for value in before["sources"].values())
        assert all(value is not None for value in before["claim_evidence"].values())
        assert all(value is not None for value in before["claim_edges"].values())
        assert before["assessment_columns"] == ["id", "legacy_marker"]
        assert before["assessment_rows"] == 0
        assert before["ownership_ledger"] is None
    finally:
        cleanup = postgres.cleanup()

    assert cleanup["container_absent"] is True
    assert cleanup["name_readback_clear"] is True
    assert cleanup["instance_label_readback_clear"] is True


@pytest.mark.skipif(not verifier.docker_available(), reason="Docker daemon is required")
def test_partial_v3_contract_is_never_adopted_or_rolled_back() -> None:
    postgres = verifier.DisposablePostgres()
    cleanup: dict[str, object] = {}
    try:
        postgres.start()
        postgres.psql(verifier.BOOTSTRAP_SQL)
        postgres.psql(
            """
create function kb_stage.teleo_v3_partial_sentinel()
returns text
language sql
immutable
as $$ select 'legacy-partial-sentinel'::text $$;
"""
        )
        state_sql = """
select jsonb_build_object(
  'sentinel_result', kb_stage.teleo_v3_partial_sentinel(),
  'sentinel_definition', pg_get_functiondef('kb_stage.teleo_v3_partial_sentinel()'::regprocedure),
  'ownership_ledger', to_regclass('kb_stage.teleo_v3_installation_ownership')::text
)::text;
"""
        before = postgres.psql_json(state_sql)

        install = postgres.apply_file(MIGRATION_SQL, check=False)
        rollback = postgres.apply_file(ROLLBACK_SQL, check=False)
        after = postgres.psql_json(state_sql)

        assert install.returncode != 0
        assert "partial or altered V3 contract lacks exact installation ownership" in install.stderr
        assert rollback.returncode != 0
        assert "V3-named objects lack exact installation ownership" in rollback.stderr
        assert before == after
        assert before["sentinel_result"] == "legacy-partial-sentinel"
        assert "teleo_v3_partial_sentinel" in before["sentinel_definition"]
        assert before["ownership_ledger"] is None
    finally:
        cleanup = postgres.cleanup()

    assert cleanup["container_absent"] is True
    assert cleanup["name_readback_clear"] is True
    assert cleanup["instance_label_readback_clear"] is True


def test_verifier_has_no_external_database_target_surface(tmp_path: Path) -> None:
    args = verifier.parse_args(["--output", str(tmp_path / "receipt.json")])
    assert args.output == tmp_path / "receipt.json"

    source = Path(verifier.__file__).read_text(encoding="utf-8")
    assert "DATABASE_URL" not in source
    assert "PGHOST" not in source
    assert '"--network",\n            "none"' in source
    assert '"--tmpfs"' in source
    assert 'production_access_attempted": False' in source


def test_failure_receipt_requires_exact_sqlstate() -> None:
    completed = subprocess.CompletedProcess(
        args=["psql"],
        returncode=3,
        stdout="",
        stderr="ERROR:  23514: expected constraint failure\n",
    )
    receipt = verifier.failure_receipt(completed, "23514")

    assert receipt["refused"] is True
    assert receipt["observed_sqlstate"] == "23514"
    assert receipt["expected_sqlstate_observed"] is True


def test_verifier_exercises_concurrent_proposal_downgrade_lock() -> None:
    source = Path(verifier.__file__).read_text(encoding="utf-8")

    assert "proposal_decision_lock_race_check" in source
    assert "teleo_v3_proposal_lock_holder" in source
    assert "set statement_timeout = '750ms'" in source
    assert 'failure_receipt(downgrade, "57014")' in source


def test_verifier_asserts_security_definer_owner_search_path_and_acl() -> None:
    source = Path(verifier.__file__).read_text(encoding="utf-8")

    assert '"owner_name": "kb_gate_owner"' in source
    assert '"security_definer": True' in source
    assert '"config": ["search_path=pg_catalog, pg_temp"]' in source
    assert '"owner_only_execute": True' in source


def test_verifier_cleanup_bypass_is_bounded_to_disposable_superuser_transaction() -> None:
    source = Path(verifier.__file__).read_text(encoding="utf-8")

    assert "set local session_replication_role = replica" in source
    assert '"isolated-disposable-superuser-transaction"' in source
    assert "Production writers must never receive" in source


@pytest.mark.skipif(not verifier.docker_available(), reason="Docker daemon is required")
def test_disposable_postgres_contract_end_to_end(tmp_path: Path) -> None:
    output = tmp_path / "teleo-v3-epistemic-contract-receipt.json"

    receipt = verifier.run_verification(output)

    assert receipt["status"] == "pass", receipt.get("error")
    assert receipt["required_tier"] == "T2_runtime"
    assert receipt["current_tier"] == "T2_runtime_disposable_postgresql"
    assert receipt["production_access_attempted"] is False
    assert receipt["production_migration_shipped"] is False
    assert receipt["environment"]["network_mode"] == "none"
    assert receipt["environment"]["tmpfs_data_dir"] is True
    assert receipt["environment"]["docker_volume_mounts"] == []
    assert len(receipt["checks"]) >= 20
    assert all(receipt["checks"].values()), receipt["checks"]
    assert all(item["refused"] for item in receipt["adversarial"].values())
    assert all(item["expected_sqlstate_observed"] for item in receipt["adversarial"].values())
    assert receipt["rollback_with_data"]["refused"] is True
    assert receipt["cleanup"]["container_absent"] is True
    assert receipt["cleanup"]["instance_label_readback_clear"] is True
    assert json.loads(output.read_text(encoding="utf-8")) == receipt
