from __future__ import annotations from dataclasses import dataclass from typing import Any, Mapping from .canonical import canonical_json, sha256_hex @dataclass(frozen=True) class CandidateAct: actor: str workload_id: str subject_id: str operation: str resource_id: str requested_attributes: tuple[str, ...] purpose: str recipient: str destination: str jurisdiction_context: str policy_epoch: int nonce: str finality_sink: str def to_dict(self) -> dict[str, Any]: return { "actor": self.actor, "workload_id": self.workload_id, "subject_id": self.subject_id, "operation": self.operation, "resource_id": self.resource_id, "requested_attributes": sorted(set(self.requested_attributes)), "purpose": self.purpose, "recipient": self.recipient, "destination": self.destination, "jurisdiction_context": self.jurisdiction_context, "policy_epoch": self.policy_epoch, "nonce": self.nonce, "finality_sink": self.finality_sink, } def canonical_bytes(self) -> bytes: return canonical_json(self.to_dict()) def digest(self) -> str: return sha256_hex(self.canonical_bytes()) @dataclass(frozen=True) class ValidationGrant: act_digest: str vi_commitment: str permitted_attributes: tuple[str, ...] selected_values: Mapping[str, Any] purpose: str recipient: str destination: str policy_epoch: int nonce: str finality_sink: str @dataclass(frozen=True) class SignedPermit: payload: Mapping[str, Any] signature_b64: str def to_dict(self) -> dict[str, Any]: return {"payload": dict(self.payload), "signature_b64": self.signature_b64}