feat(postbox): add governed content protection profiles
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Literal
|
||||
|
||||
|
||||
POSTBOX_PLAINTEXT_PROFILE = "plaintext_v1"
|
||||
POSTBOX_MANAGED_ENVELOPE_PROFILE = "server_envelope_v1"
|
||||
POSTBOX_EXTERNAL_E2EE_PROFILE = "external_e2ee_v1"
|
||||
POSTBOX_LEGACY_EXTERNAL_ENVELOPE_PROFILE = "external_envelope_v1"
|
||||
POSTBOX_STANDARD_PROFILE = POSTBOX_MANAGED_ENVELOPE_PROFILE
|
||||
|
||||
PostboxProtectionProfile = Literal[
|
||||
"plaintext_v1",
|
||||
"server_envelope_v1",
|
||||
"external_e2ee_v1",
|
||||
]
|
||||
|
||||
SUPPORTED_POSTBOX_PROTECTION_PROFILES = frozenset(
|
||||
{
|
||||
POSTBOX_PLAINTEXT_PROFILE,
|
||||
POSTBOX_MANAGED_ENVELOPE_PROFILE,
|
||||
POSTBOX_EXTERNAL_E2EE_PROFILE,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def normalize_postbox_protection_policy(
|
||||
policy: dict[str, object] | None = None,
|
||||
) -> dict[str, object]:
|
||||
return {
|
||||
"new_incumbent_history": "since_assignment",
|
||||
"history_days": None,
|
||||
"ordinary_rotation": "rewrap",
|
||||
"compromise_rotation": "reencrypt",
|
||||
"recovery_authority": "institutional_key_holders",
|
||||
"recovery_quorum": 2,
|
||||
"handover_authority": "dual_control",
|
||||
"handover_quorum": 2,
|
||||
"emergency_access": "dual_control",
|
||||
"emergency_quorum": 2,
|
||||
"export_authority": "dual_control",
|
||||
"export_quorum": 2,
|
||||
"destruction_authority": "dual_control",
|
||||
"destruction_quorum": 2,
|
||||
"external_recipient_assurance": "strong_identity",
|
||||
"vacancy_escalation_content_access": "metadata_only",
|
||||
**(policy or {}),
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PostboxProtectionProfileDefinition:
|
||||
id: PostboxProtectionProfile
|
||||
label: str
|
||||
description: str
|
||||
server_can_decrypt: bool
|
||||
requires_encryption_module: bool
|
||||
requires_external_client: bool
|
||||
standard: bool = False
|
||||
|
||||
|
||||
POSTBOX_PROTECTION_PROFILE_DEFINITIONS = (
|
||||
PostboxProtectionProfileDefinition(
|
||||
id=POSTBOX_MANAGED_ENVELOPE_PROFILE,
|
||||
label="Institution-managed envelope",
|
||||
description=(
|
||||
"The Encryption provider protects content and authorized institutional "
|
||||
"key holders can govern recovery. This is the standard profile."
|
||||
),
|
||||
server_can_decrypt=True,
|
||||
requires_encryption_module=True,
|
||||
requires_external_client=False,
|
||||
standard=True,
|
||||
),
|
||||
PostboxProtectionProfileDefinition(
|
||||
id=POSTBOX_EXTERNAL_E2EE_PROFILE,
|
||||
label="External end-to-end envelope",
|
||||
description=(
|
||||
"A reviewed client or producer supplies ciphertext, a signed manifest, "
|
||||
"and recipient-wrapped keys. GovOPlaN stores and routes them but cannot "
|
||||
"decrypt the content."
|
||||
),
|
||||
server_can_decrypt=False,
|
||||
requires_encryption_module=False,
|
||||
requires_external_client=True,
|
||||
),
|
||||
PostboxProtectionProfileDefinition(
|
||||
id=POSTBOX_PLAINTEXT_PROFILE,
|
||||
label="No application-layer encryption",
|
||||
description=(
|
||||
"Postbox stores readable message content. Transport and storage controls "
|
||||
"may still apply, but this profile is not encrypted by Postbox."
|
||||
),
|
||||
server_can_decrypt=True,
|
||||
requires_encryption_module=False,
|
||||
requires_external_client=False,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def is_e2ee_profile(profile: str) -> bool:
|
||||
return profile in {
|
||||
POSTBOX_EXTERNAL_E2EE_PROFILE,
|
||||
POSTBOX_LEGACY_EXTERNAL_ENVELOPE_PROFILE,
|
||||
}
|
||||
Reference in New Issue
Block a user