feat(records): define archive transfer provider contract
This commit is contained in:
@@ -4,10 +4,16 @@ from datetime import UTC, datetime
|
||||
import unittest
|
||||
|
||||
from govoplan_core.core.records import (
|
||||
RecordArchiveProviderState,
|
||||
RecordArchiveReceipt,
|
||||
RecordArchiveTransferRequest,
|
||||
RecordContractError,
|
||||
RecordFilingRequest,
|
||||
RecordSourceLocator,
|
||||
RecordSourceReference,
|
||||
RecordTransferPackage,
|
||||
record_archive_capabilities,
|
||||
record_archive_capability,
|
||||
record_source_capabilities,
|
||||
record_source_capability,
|
||||
)
|
||||
@@ -15,7 +21,12 @@ from govoplan_core.core.records import (
|
||||
|
||||
class _Registry:
|
||||
def capability_names(self) -> tuple[str, ...]:
|
||||
return ("mail.delivery", "records.source.cases", "records.source.files")
|
||||
return (
|
||||
"mail.delivery",
|
||||
"records.archive.simulation",
|
||||
"records.source.cases",
|
||||
"records.source.files",
|
||||
)
|
||||
|
||||
|
||||
class RecordsContractTests(unittest.TestCase):
|
||||
@@ -84,6 +95,72 @@ class RecordsContractTests(unittest.TestCase):
|
||||
record_source_capabilities(_Registry()),
|
||||
)
|
||||
|
||||
def test_archive_contract_is_digest_bound_and_discoverable(self) -> None:
|
||||
package = RecordTransferPackage(
|
||||
tenant_id="tenant-1",
|
||||
package_id="package-1",
|
||||
record_id="record-1",
|
||||
record_revision=3,
|
||||
profile="govoplan-simulation-v1",
|
||||
manifest_sha256="a" * 64,
|
||||
manifest={"record_id": "record-1", "items": []},
|
||||
)
|
||||
request = RecordArchiveTransferRequest(
|
||||
package=package,
|
||||
purpose="archive appraisal",
|
||||
idempotency_key="transfer-1",
|
||||
)
|
||||
state = RecordArchiveProviderState(
|
||||
provider_id="simulation",
|
||||
label="Archive simulation",
|
||||
profiles=("govoplan-simulation-v1",),
|
||||
authority_modes=("linked_reference",),
|
||||
healthy=True,
|
||||
checked_at=datetime(2026, 8, 6, tzinfo=UTC),
|
||||
simulated=True,
|
||||
)
|
||||
|
||||
self.assertEqual("package-1", request.package.package_id)
|
||||
self.assertTrue(state.simulated)
|
||||
self.assertEqual(
|
||||
"records.archive.simulation",
|
||||
record_archive_capability("simulation"),
|
||||
)
|
||||
self.assertEqual(
|
||||
("records.archive.simulation",),
|
||||
record_archive_capabilities(_Registry()),
|
||||
)
|
||||
|
||||
def test_unknown_archive_outcome_cannot_be_retry_safe(self) -> None:
|
||||
with self.assertRaisesRegex(RecordContractError, "retry-safe"):
|
||||
RecordArchiveReceipt(
|
||||
provider_id="archive-1",
|
||||
package_id="package-1",
|
||||
outcome="outcome_unknown",
|
||||
observed_at=datetime(2026, 8, 6, tzinfo=UTC),
|
||||
receipt_sha256="b" * 64,
|
||||
retry_safe=True,
|
||||
)
|
||||
|
||||
def test_archive_provider_runtime_values_are_validated(self) -> None:
|
||||
with self.assertRaisesRegex(RecordContractError, "invalid authority mode"):
|
||||
RecordArchiveProviderState(
|
||||
provider_id="archive",
|
||||
label="Archive",
|
||||
profiles=("profile",),
|
||||
authority_modes=("untrusted",), # type: ignore[arg-type]
|
||||
healthy=True,
|
||||
checked_at=datetime.now(UTC),
|
||||
)
|
||||
with self.assertRaisesRegex(RecordContractError, "outcome is invalid"):
|
||||
RecordArchiveReceipt(
|
||||
provider_id="archive",
|
||||
package_id="package-1",
|
||||
outcome="maybe", # type: ignore[arg-type]
|
||||
observed_at=datetime.now(UTC),
|
||||
receipt_sha256="a" * 64,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user