Add governed form handoffs
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field, replace
|
||||
from datetime import datetime
|
||||
from typing import Mapping
|
||||
from typing import Literal, Mapping
|
||||
|
||||
from govoplan_core.core.institutional import (
|
||||
EvidenceReference,
|
||||
@@ -25,6 +25,84 @@ FORM_INSTANCE_STATUSES = frozenset(
|
||||
"archived",
|
||||
}
|
||||
)
|
||||
FormHandoffState = Literal[
|
||||
"requested",
|
||||
"accepted",
|
||||
"rejected",
|
||||
"outcome_unknown",
|
||||
"reconciled",
|
||||
"compensated",
|
||||
]
|
||||
FORM_HANDOFF_STATES = frozenset(
|
||||
{
|
||||
"requested",
|
||||
"accepted",
|
||||
"rejected",
|
||||
"outcome_unknown",
|
||||
"reconciled",
|
||||
"compensated",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class FormHandoff:
|
||||
tenant_id: str
|
||||
instance_id: str
|
||||
effect_id: str
|
||||
instance_revision: int
|
||||
idempotency_key: str
|
||||
provider_key: str
|
||||
request_sha256: str
|
||||
binding_kind: str
|
||||
binding_reference: str
|
||||
provider_capability: str
|
||||
state: FormHandoffState
|
||||
attempt_count: int
|
||||
requested_at: datetime
|
||||
resolved_at: datetime | None = None
|
||||
target_ref: InstitutionalReference | None = None
|
||||
href: str | None = None
|
||||
evidence: tuple[EvidenceReference, ...] = ()
|
||||
last_error: str | None = None
|
||||
metadata: Mapping[str, object] = field(default_factory=dict)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.state not in FORM_HANDOFF_STATES:
|
||||
raise InstitutionalContextError(
|
||||
f"Unsupported Form handoff state: {self.state!r}."
|
||||
)
|
||||
if self.attempt_count < 0:
|
||||
raise InstitutionalContextError(
|
||||
"Form handoff attempt count cannot be negative."
|
||||
)
|
||||
if self.target_ref is not None and self.target_ref.tenant_id != self.tenant_id:
|
||||
raise InstitutionalContextError("Form handoff target cannot cross tenants.")
|
||||
if any(item.tenant_id != self.tenant_id for item in self.evidence):
|
||||
raise InstitutionalContextError(
|
||||
"Form handoff evidence cannot cross tenants."
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"effect_id": self.effect_id,
|
||||
"instance_id": self.instance_id,
|
||||
"instance_revision": self.instance_revision,
|
||||
"binding_kind": self.binding_kind,
|
||||
"binding_reference": self.binding_reference,
|
||||
"provider_capability": self.provider_capability,
|
||||
"state": self.state,
|
||||
"attempt_count": self.attempt_count,
|
||||
"requested_at": self.requested_at.isoformat(),
|
||||
"resolved_at": self.resolved_at.isoformat() if self.resolved_at else None,
|
||||
"target_ref": self.target_ref.to_dict() if self.target_ref else None,
|
||||
"href": self.href,
|
||||
"evidence": [
|
||||
item.to_dict(include_inspection=False) for item in self.evidence
|
||||
],
|
||||
"last_error": self.last_error,
|
||||
"metadata": dict(self.metadata),
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
@@ -139,4 +217,10 @@ class FormInstance:
|
||||
}
|
||||
|
||||
|
||||
__all__ = ["FORM_INSTANCE_STATUSES", "FormInstance"]
|
||||
__all__ = [
|
||||
"FORM_HANDOFF_STATES",
|
||||
"FORM_INSTANCE_STATUSES",
|
||||
"FormHandoff",
|
||||
"FormHandoffState",
|
||||
"FormInstance",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user