feat(records): govern lifecycle recovery and transfer evidence

This commit is contained in:
2026-08-06 05:36:18 +02:00
parent f316523a1d
commit df51bb1787
22 changed files with 4954 additions and 66 deletions
+91
View File
@@ -0,0 +1,91 @@
from __future__ import annotations
from datetime import UTC, datetime
import hashlib
import json
from govoplan_core.core.records import (
RecordArchiveProviderState,
RecordArchiveReceipt,
RecordArchiveTransferRequest,
RecordContractError,
)
SIMULATION_PROVIDER_ID = "simulation"
SIMULATION_PROFILE = "govoplan-simulation-v1"
class SimulatedRecordArchiveProvider:
"""Exercise the transfer boundary without claiming archival custody."""
provider_id = SIMULATION_PROVIDER_ID
def state(self) -> RecordArchiveProviderState:
checked_at = datetime.now(UTC)
return RecordArchiveProviderState(
provider_id=self.provider_id,
label="Records transfer simulation",
profiles=(SIMULATION_PROFILE,),
authority_modes=("linked_reference",),
healthy=True,
checked_at=checked_at,
last_success_at=checked_at,
freshness_seconds=0,
limitations=(
"Simulation validates package and receipt handling but does not transfer custody.",
"It is not an xDOMEA or archival conformance profile.",
),
simulated=True,
)
def dispatch(
self,
session: object,
principal: object,
*,
request: RecordArchiveTransferRequest,
) -> RecordArchiveReceipt:
del session, principal
if request.package.profile != SIMULATION_PROFILE:
raise RecordContractError(
"The simulation provider only accepts its declared profile."
)
observed_at = datetime.now(UTC)
receipt_payload = {
"provider_id": self.provider_id,
"package_id": request.package.package_id,
"manifest_sha256": request.package.manifest_sha256,
"profile": request.package.profile,
"outcome": "accepted",
"simulated": True,
}
receipt_sha256 = hashlib.sha256(
json.dumps(
receipt_payload,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
).hexdigest()
return RecordArchiveReceipt(
provider_id=self.provider_id,
package_id=request.package.package_id,
outcome="accepted",
observed_at=observed_at,
receipt_sha256=receipt_sha256,
external_reference=f"simulation:{request.package.package_id}",
retry_safe=True,
simulated=True,
metadata={
"manifest_sha256": request.package.manifest_sha256,
"profile": request.package.profile,
"custody_transferred": False,
},
)
__all__ = [
"SIMULATION_PROFILE",
"SIMULATION_PROVIDER_ID",
"SimulatedRecordArchiveProvider",
]