Extend Postbox access classification contract
This commit is contained in:
@@ -5,6 +5,8 @@ from dataclasses import dataclass, field
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Literal, Protocol, runtime_checkable
|
from typing import Literal, Protocol, runtime_checkable
|
||||||
|
|
||||||
|
from govoplan_core.core.events import EventClassification
|
||||||
|
|
||||||
|
|
||||||
POSTBOX_MODULE_ID = "postbox"
|
POSTBOX_MODULE_ID = "postbox"
|
||||||
CAPABILITY_POSTBOX_DIRECTORY = "postbox.directory"
|
CAPABILITY_POSTBOX_DIRECTORY = "postbox.directory"
|
||||||
@@ -14,9 +16,62 @@ CAPABILITY_POSTBOX_DELIVERY = "postbox.delivery"
|
|||||||
CAPABILITY_POSTBOX_EVIDENCE = "postbox.evidence"
|
CAPABILITY_POSTBOX_EVIDENCE = "postbox.evidence"
|
||||||
CAPABILITY_POSTBOX_ROUTING = "postbox.routing"
|
CAPABILITY_POSTBOX_ROUTING = "postbox.routing"
|
||||||
|
|
||||||
PostboxAction = Literal["discover", "read", "send", "acknowledge", "administer"]
|
PostboxAction = Literal[
|
||||||
|
"discover",
|
||||||
|
"read",
|
||||||
|
"send",
|
||||||
|
"reply",
|
||||||
|
"acknowledge",
|
||||||
|
"administer",
|
||||||
|
]
|
||||||
PostboxMessageListState = Literal["all", "unread", "read", "acknowledged"]
|
PostboxMessageListState = Literal["all", "unread", "read", "acknowledged"]
|
||||||
PostboxMessageAvailability = Literal["available", "withdrawn", "expired"]
|
PostboxMessageAvailability = Literal["available", "withdrawn", "expired"]
|
||||||
|
PostboxBindingStatus = Literal[
|
||||||
|
"active",
|
||||||
|
"missing",
|
||||||
|
"not_effective",
|
||||||
|
"unit_missing",
|
||||||
|
"unit_inactive",
|
||||||
|
"unit_tenant_mismatch",
|
||||||
|
"function_missing",
|
||||||
|
"function_inactive",
|
||||||
|
"function_tenant_mismatch",
|
||||||
|
"function_reassigned",
|
||||||
|
"directory_unavailable",
|
||||||
|
]
|
||||||
|
|
||||||
|
POSTBOX_CLASSIFICATIONS: tuple[EventClassification, ...] = (
|
||||||
|
"public",
|
||||||
|
"internal",
|
||||||
|
"confidential",
|
||||||
|
"restricted",
|
||||||
|
)
|
||||||
|
_POSTBOX_CLASSIFICATION_RANK = {
|
||||||
|
value: rank for rank, value in enumerate(POSTBOX_CLASSIFICATIONS)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_postbox_classification(
|
||||||
|
value: str,
|
||||||
|
) -> EventClassification | None:
|
||||||
|
candidate = value.strip().casefold()
|
||||||
|
if candidate not in _POSTBOX_CLASSIFICATION_RANK:
|
||||||
|
return None
|
||||||
|
return candidate # type: ignore[return-value]
|
||||||
|
|
||||||
|
|
||||||
|
def postbox_classification_allows(
|
||||||
|
ceiling: str,
|
||||||
|
content: str,
|
||||||
|
) -> bool:
|
||||||
|
normalized_ceiling = normalize_postbox_classification(ceiling)
|
||||||
|
normalized_content = normalize_postbox_classification(content)
|
||||||
|
if normalized_ceiling is None or normalized_content is None:
|
||||||
|
return False
|
||||||
|
return (
|
||||||
|
_POSTBOX_CLASSIFICATION_RANK[normalized_content]
|
||||||
|
<= _POSTBOX_CLASSIFICATION_RANK[normalized_ceiling]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, slots=True)
|
@dataclass(frozen=True, slots=True)
|
||||||
@@ -26,6 +81,9 @@ class PostboxActorRef:
|
|||||||
selected_assignment_id: str | None = None
|
selected_assignment_id: str | None = None
|
||||||
acting_for_account_id: str | None = None
|
acting_for_account_id: str | None = None
|
||||||
authorized_actions: frozenset[PostboxAction] = frozenset()
|
authorized_actions: frozenset[PostboxAction] = frozenset()
|
||||||
|
authorized_classifications: frozenset[EventClassification] = frozenset(
|
||||||
|
{"public", "internal"}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, slots=True)
|
@dataclass(frozen=True, slots=True)
|
||||||
@@ -91,6 +149,9 @@ class PostboxAccessDecisionRef:
|
|||||||
selected_assignment_id: str | None = None
|
selected_assignment_id: str | None = None
|
||||||
holder_count: int = 0
|
holder_count: int = 0
|
||||||
vacant: bool = True
|
vacant: bool = True
|
||||||
|
classification: str = "internal"
|
||||||
|
classification_allowed: bool = True
|
||||||
|
binding_status: PostboxBindingStatus = "active"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, slots=True)
|
@dataclass(frozen=True, slots=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user