"""Explicit domain-key mode for durable non-asset approval intents.""" from __future__ import annotations import json import uuid import pytest from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.approval.models import ApprovalSubmissionIntent from app.approval.submission_intents import submit_with_durable_intent from app.core.exceptions import AppException from app.identity.person_models import IdentityPerson class _Provider: def __init__(self) -> None: self.created = 0 async def create_instance(self, *, instance_uuid, **kwargs) -> dict: self.created += 1 return {"instance_code": f"instance-{instance_uuid}"} class _AcceptedThenRaisesProvider: def __init__(self, error: Exception) -> None: self.error = error self.instance_uuids: list[str] = [] async def create_instance(self, *, instance_uuid, **kwargs) -> dict: self.instance_uuids.append(instance_uuid) if len(self.instance_uuids) == 1: raise self.error return {"instance_code": f"instance-{instance_uuid}"} @pytest.mark.asyncio async def test_explicit_keys_allow_multiple_generations_per_applicant( db_session: AsyncSession, ) -> None: person = IdentityPerson( id=uuid.uuid4(), source_system="successfactors", hris_person_id=f"sf-{uuid.uuid4().hex[:8]}", display_name="Explicit intent requester", work_email=f"intent-{uuid.uuid4().hex[:8]}@test.com", employment_status="active", ) db_session.add(person) await db_session.commit() provider = _Provider() async def _submit(key: str, value: str): return await submit_with_durable_intent( db_session, client=provider, scope="explicit-key-test", applicant_id=person.id, intent_key=key, semantic_payload={"value": value}, provider_payload={ "approval_code": "approval-code", "identity_type": "user_id", "identity_value": "feishu-user", "form": "[]", }, finalization_payload={"value": value}, trace_id=f"trace-{key}", ) first = await _submit("request-a", "a") second = await _submit("request-b", "b") replay = await _submit("request-a", "a") assert first.id != second.id assert replay.id == first.id assert first.provider_request_uuid != second.provider_request_uuid assert provider.created == 2 @pytest.mark.asyncio async def test_explicit_and_recovery_key_modes_coexist( db_session: AsyncSession, ) -> None: """The final primitive preserves both independent domain contracts.""" person = IdentityPerson( id=uuid.uuid4(), source_system="successfactors", hris_person_id=f"sf-{uuid.uuid4().hex[:8]}", display_name="Dual-mode intent requester", work_email=f"dual-intent-{uuid.uuid4().hex[:8]}@test.com", employment_status="active", ) db_session.add(person) await db_session.commit() provider = _Provider() common = { "db": db_session, "client": provider, "applicant_id": person.id, "provider_payload": { "approval_code": "approval-code", "identity_type": "user_id", "identity_value": "feishu-user", "form": "[]", }, "finalization_payload": {}, } recovery = await submit_with_durable_intent( **common, scope="recovery-key-mode", recovery_key="provider-a", semantic_payload={"system": "a"}, trace_id="trace-recovery", ) explicit = await submit_with_durable_intent( **common, scope="explicit-key-mode", intent_key="request-a", semantic_payload={"request": "a"}, trace_id="trace-explicit", ) recovery_replay = await submit_with_durable_intent( **common, scope="recovery-key-mode", recovery_key="provider-a", semantic_payload={"system": "a"}, trace_id="trace-recovery-replay", ) explicit_replay = await submit_with_durable_intent( **common, scope="explicit-key-mode", intent_key="request-a", semantic_payload={"request": "a"}, trace_id="trace-explicit-replay", ) assert recovery_replay.id == recovery.id assert explicit_replay.id == explicit.id assert recovery.id != explicit.id assert provider.created == 2 @pytest.mark.parametrize( ("scope", "key_kwargs", "provider_error"), ( ( "ambiguous-json-recovery-key", {"recovery_key": "system-a"}, json.JSONDecodeError("malformed provider response", "", 0), ), ( "ambiguous-value-explicit-key", {"intent_key": "request-a"}, ValueError("provider response post-processing failed"), ), ), ) @pytest.mark.asyncio async def test_unclassified_create_error_replays_same_provider_uuid( db_session: AsyncSession, scope: str, key_kwargs: dict[str, str], provider_error: Exception, ) -> None: """Post-accept decoding failures stay unknown and reuse the UUID.""" person = IdentityPerson( id=uuid.uuid4(), source_system="successfactors", hris_person_id=f"sf-{uuid.uuid4().hex[:8]}", display_name="Ambiguous provider requester", work_email=f"ambiguous-{uuid.uuid4().hex[:8]}@test.com", employment_status="active", ) db_session.add(person) await db_session.commit() provider = _AcceptedThenRaisesProvider(provider_error) async def _submit() -> ApprovalSubmissionIntent: return await submit_with_durable_intent( db_session, client=provider, scope=scope, applicant_id=person.id, semantic_payload={"request": "stable"}, provider_payload={ "approval_code": "approval-code", "identity_type": "user_id", "identity_value": "feishu-user", "form": "[]", }, finalization_payload={"request": "stable"}, trace_id="trace-ambiguous-provider", **key_kwargs, ) with pytest.raises(AppException) as raised: await _submit() assert raised.value.code == "APPROVAL_SUBMISSION_RESULT_UNKNOWN" intent = await db_session.scalar( select(ApprovalSubmissionIntent).where( ApprovalSubmissionIntent.scope == scope, ) ) assert intent is not None assert intent.state == "unknown" assert intent.attempt_count == 1 assert intent.next_attempt_at is not None replay = await _submit() assert replay.id == intent.id assert replay.state == "provider_created" assert provider.instance_uuids == [ intent.provider_request_uuid, intent.provider_request_uuid, ] @pytest.mark.asyncio async def test_explicit_key_rejects_invalid_length( db_session: AsyncSession, ) -> None: with pytest.raises(ValueError, match="1..128"): await submit_with_durable_intent( db_session, client=_Provider(), scope="explicit-key-test", applicant_id=uuid.uuid4(), intent_key="", semantic_payload={}, provider_payload={}, finalization_payload={}, trace_id="trace-invalid", )