from __future__ import annotations from datetime import UTC, datetime import pytest from pydantic import ValidationError from govoplan_campaign.backend.campaign.mail_profile_boundary import ( campaign_editor_state_for_edit, ) from govoplan_campaign.backend.schemas import ( CampaignVersionResponse, CampaignVersionUpdateRequest, ) @pytest.mark.parametrize( "editor_state", [ {"smtp": {"host": "smtp.example.test", "password": "secret"}}, {"transport": {"imap_password": "secret"}}, { "review_send": { "build_token": "forged", "inspection_complete": True, "reviewed_message_keys": [], "updated_at": "2026-07-21T00:00:00+00:00", "updated_by_user_id": "user-1", } }, ], ) def test_version_updates_reject_arbitrary_or_server_owned_editor_state( editor_state: dict[str, object], ) -> None: with pytest.raises(ValidationError, match="unsupported or transport-owned"): CampaignVersionUpdateRequest(editor_state=editor_state) def test_version_response_omits_legacy_secret_bearing_editor_state() -> None: response = CampaignVersionResponse.model_validate( { "id": "version-1", "campaign_id": "campaign-1", "version_number": 1, "schema_version": "1.0", "editor_state": { "opt_ins": {"inline_guidance": True}, "smtp": {"host": "smtp.internal.example", "password": "provider-secret"}, }, "created_at": datetime.now(UTC), "updated_at": datetime.now(UTC), } ) assert response.editor_state == {"opt_ins": {"inline_guidance": True}} assert "provider-secret" not in repr(response) assert "internal.example" not in repr(response) def test_review_build_token_is_visible_only_in_operator_diagnostics() -> None: value = { "id": "version-1", "campaign_id": "campaign-1", "version_number": 1, "schema_version": "1.0", "editor_state": { "review_send": { "build_token": "internal-build-token", "inspection_complete": True, "reviewed_message_keys": ["entry-1"], "updated_at": "2026-07-21T00:00:00+00:00", "updated_by_user_id": "reviewer-1", } }, "created_at": datetime.now(UTC), "updated_at": datetime.now(UTC), } public = CampaignVersionResponse.model_validate(value) operator = CampaignVersionResponse.model_validate( value, context={"include_diagnostics": True}, ) assert "build_token" not in public.editor_state["review_send"] assert operator.editor_state["review_send"]["build_token"] == "internal-build-token" def test_fork_copy_keeps_only_client_owned_bounded_metadata() -> None: copied = campaign_editor_state_for_edit( { "created_from": "minimal_campaign", "field_overrides": {"department": False}, "review_send": { "build_token": "build-1", "inspection_complete": True, "reviewed_message_keys": ["entry-1"], "updated_at": "2026-07-21T00:00:00+00:00", "updated_by_user_id": "reviewer-1", }, "credentials": {"password": "legacy-secret"}, } ) assert copied == { "created_from": "minimal_campaign", "field_overrides": {"department": False}, } assert "legacy-secret" not in repr(copied)