Add encrypted envelope recipient state

This commit is contained in:
2026-07-31 22:48:07 +02:00
parent dc6f81dd33
commit e3daf400f3
10 changed files with 272 additions and 2 deletions
+76
View File
@@ -6,6 +6,7 @@ import logging
import re
from collections import Counter
from collections.abc import Mapping, Sequence
from dataclasses import asdict
from datetime import datetime, timedelta, timezone
from typing import Any, Literal
@@ -58,6 +59,7 @@ from govoplan_core.core.postbox import (
PostboxDeliveryResult,
PostboxDeliveryTemplateRef,
PostboxDirectoryEntryRef,
PostboxExternalRecipientTokenRef,
PostboxMessageAvailability,
PostboxMessageAuthoringRequest,
PostboxMessageRef,
@@ -66,6 +68,7 @@ from govoplan_core.core.postbox import (
PostboxOrganizationUnitTargetRef,
PostboxParticipantRef,
PostboxTargetRef,
PostboxWrappedKeyRef,
normalize_postbox_classification,
postbox_classification_allows,
)
@@ -127,6 +130,34 @@ def _mapping(value: Mapping[str, object] | None) -> dict[str, object]:
return dict(value or {})
def _optional_datetime(value: object) -> datetime | None:
if isinstance(value, datetime):
return value
if isinstance(value, str) and value:
try:
return datetime.fromisoformat(value)
except ValueError:
return None
return None
def _external_token_record(
token: PostboxExternalRecipientTokenRef,
) -> dict[str, object]:
return {
"token_id": token.token_id,
"state": token.state,
"expires_at": token.expires_at.isoformat() if token.expires_at else None,
"one_time": token.one_time,
"key_fetched_at": (
token.key_fetched_at.isoformat() if token.key_fetched_at else None
),
"revoked_at": token.revoked_at.isoformat() if token.revoked_at else None,
"assurance_profile": token.assurance_profile,
"metadata": dict(token.metadata),
}
def _authoring_digest(
request: PostboxMessageAuthoringRequest,
*,
@@ -1157,6 +1188,13 @@ class PostboxService:
producer_resource_id=request.producer_resource_id,
encryption_profile=postbox.encryption_profile,
key_epoch=postbox.key_epoch,
ciphertext_ref=request.ciphertext_ref,
signed_manifest_ref=request.signed_manifest_ref,
wrapped_keys=[asdict(item) for item in request.wrapped_keys],
external_recipient_tokens=[
_external_token_record(item)
for item in request.external_recipient_tokens
],
delivered_at=now,
expires_at=request.expires_at,
metadata_=_mapping(request.metadata),
@@ -1820,6 +1858,12 @@ class PostboxService:
producer_resource_id=source_message.producer_resource_id,
encryption_profile=target_postbox.encryption_profile,
key_epoch=target_postbox.key_epoch,
ciphertext_ref=source_message.ciphertext_ref,
signed_manifest_ref=source_message.signed_manifest_ref,
wrapped_keys=list(source_message.wrapped_keys or []),
external_recipient_tokens=list(
source_message.external_recipient_tokens or []
),
delivered_at=delivered_at,
expires_at=source_message.expires_at,
retention_hold_until=source_message.retention_hold_until,
@@ -3734,6 +3778,38 @@ class PostboxService:
key_epoch=message.key_epoch,
ciphertext_ref=message.ciphertext_ref,
signed_manifest_ref=message.signed_manifest_ref,
wrapped_keys=tuple(
PostboxWrappedKeyRef(
recipient_type=str(item.get("recipient_type") or "unknown"),
recipient_id=str(item.get("recipient_id") or "unknown"),
key_epoch=int(item.get("key_epoch") or message.key_epoch),
wrapped_key_ref=str(item.get("wrapped_key_ref") or ""),
algorithm=(
str(item["algorithm"]) if item.get("algorithm") else None
),
metadata=_mapping(item.get("metadata")),
)
for item in message.wrapped_keys or []
if isinstance(item, Mapping) and item.get("wrapped_key_ref")
),
external_recipient_tokens=tuple(
PostboxExternalRecipientTokenRef(
token_id=str(item.get("token_id") or ""),
state=str(item.get("state") or "pending"),
expires_at=_optional_datetime(item.get("expires_at")),
one_time=bool(item.get("one_time", False)),
key_fetched_at=_optional_datetime(item.get("key_fetched_at")),
revoked_at=_optional_datetime(item.get("revoked_at")),
assurance_profile=(
str(item["assurance_profile"])
if item.get("assurance_profile")
else None
),
metadata=_mapping(item.get("metadata")),
)
for item in message.external_recipient_tokens or []
if isinstance(item, Mapping) and item.get("token_id")
),
participants=tuple(
PostboxParticipantRef(
kind=item.kind,