feat: initialize governed postbox module
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
|
||||
class PostboxAccessDecisionResponse(BaseModel):
|
||||
allowed: bool
|
||||
action: str
|
||||
postbox_id: str
|
||||
reason_code: str
|
||||
explanation: str
|
||||
organization_unit_id: str | None = None
|
||||
function_id: str | None = None
|
||||
assignment_ids: list[str] = Field(default_factory=list)
|
||||
assignment_sources: list[str] = Field(default_factory=list)
|
||||
selected_assignment_id: str | None = None
|
||||
holder_count: int = 0
|
||||
vacant: bool = True
|
||||
|
||||
|
||||
class PostboxDirectoryItem(BaseModel):
|
||||
id: str
|
||||
tenant_id: str
|
||||
address: str
|
||||
address_key: str
|
||||
name: str
|
||||
status: str
|
||||
classification: str
|
||||
organization_unit_id: str | None = None
|
||||
organization_unit_name: str | None = None
|
||||
function_id: str | None = None
|
||||
function_name: str | None = None
|
||||
context_key: str | None = None
|
||||
template_revision_id: str | None = None
|
||||
holder_count: int = 0
|
||||
vacant: bool = True
|
||||
access: PostboxAccessDecisionResponse | None = None
|
||||
|
||||
|
||||
class PostboxDirectoryResponse(BaseModel):
|
||||
postboxes: list[PostboxDirectoryItem]
|
||||
|
||||
|
||||
class PostboxParticipantPayload(BaseModel):
|
||||
kind: str = Field(min_length=1, max_length=30)
|
||||
reference_type: str = Field(min_length=1, max_length=50)
|
||||
reference_id: str | None = Field(default=None, max_length=255)
|
||||
label: str | None = Field(default=None, max_length=500)
|
||||
address: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class PostboxAttachmentPayload(BaseModel):
|
||||
reference_type: str = Field(min_length=1, max_length=50)
|
||||
reference_id: str = Field(min_length=1, max_length=255)
|
||||
name: str | None = Field(default=None, max_length=1000)
|
||||
media_type: str | None = Field(default=None, max_length=255)
|
||||
size_bytes: int | None = Field(default=None, ge=0)
|
||||
digest: str | None = Field(default=None, max_length=255)
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PostboxMessageItem(BaseModel):
|
||||
id: str
|
||||
tenant_id: str
|
||||
postbox_id: str
|
||||
subject: str
|
||||
body_text: str | None = None
|
||||
status: str
|
||||
classification: str
|
||||
sender_label: str | None = None
|
||||
delivered_at: datetime
|
||||
read_at: datetime | None = None
|
||||
acknowledged_at: datetime | None = None
|
||||
expires_at: datetime | None = None
|
||||
withdrawn_at: datetime | None = None
|
||||
producer_module: str | None = None
|
||||
producer_resource_type: str | None = None
|
||||
producer_resource_id: str | None = None
|
||||
encryption_profile: str
|
||||
key_epoch: int
|
||||
ciphertext_ref: str | None = None
|
||||
signed_manifest_ref: str | None = None
|
||||
participants: list[PostboxParticipantPayload] = Field(default_factory=list)
|
||||
attachments: list[PostboxAttachmentPayload] = Field(default_factory=list)
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PostboxMessageListResponse(BaseModel):
|
||||
messages: list[PostboxMessageItem]
|
||||
total: int
|
||||
limit: int
|
||||
offset: int
|
||||
|
||||
|
||||
class PostboxMessageStateRequest(BaseModel):
|
||||
state: Literal["read", "acknowledged"]
|
||||
|
||||
|
||||
class PostboxTargetPayload(BaseModel):
|
||||
postbox_id: str | None = Field(default=None, max_length=36)
|
||||
address_key: str | None = Field(default=None, max_length=500)
|
||||
template_id: str | None = Field(default=None, max_length=36)
|
||||
organization_unit_id: str | None = Field(default=None, max_length=36)
|
||||
function_id: str | None = Field(default=None, max_length=36)
|
||||
context_key: str | None = Field(default=None, max_length=255)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_target(self) -> "PostboxTargetPayload":
|
||||
direct = bool(self.postbox_id or self.address_key)
|
||||
templated = bool(
|
||||
self.template_id
|
||||
and self.organization_unit_id
|
||||
and self.function_id
|
||||
)
|
||||
if direct == templated:
|
||||
raise ValueError(
|
||||
"Specify one direct Postbox target or one complete template target."
|
||||
)
|
||||
return self
|
||||
|
||||
|
||||
class PostboxDeliveryCreateRequest(BaseModel):
|
||||
target: PostboxTargetPayload
|
||||
producer_module: str = Field(min_length=1, max_length=100)
|
||||
producer_resource_type: str = Field(min_length=1, max_length=100)
|
||||
producer_resource_id: str | None = Field(default=None, max_length=255)
|
||||
idempotency_key: str = Field(min_length=1, max_length=255)
|
||||
subject: str = Field(min_length=1, max_length=1000)
|
||||
body_text: str | None = None
|
||||
sender_label: str | None = Field(default=None, max_length=500)
|
||||
classification: str = Field(default="internal", min_length=1, max_length=50)
|
||||
participants: list[PostboxParticipantPayload] = Field(default_factory=list)
|
||||
attachments: list[PostboxAttachmentPayload] = Field(default_factory=list)
|
||||
expires_at: datetime | None = None
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PostboxDeliveryResponse(BaseModel):
|
||||
delivery_id: str
|
||||
postbox_id: str
|
||||
message_id: str
|
||||
address: str
|
||||
status: str
|
||||
vacant: bool
|
||||
holder_count: int
|
||||
duplicate: bool = False
|
||||
evidence: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class PostboxExactCreateRequest(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=500)
|
||||
description: str | None = None
|
||||
organization_unit_id: str = Field(min_length=1, max_length=36)
|
||||
function_id: str = Field(min_length=1, max_length=36)
|
||||
address_key: str | None = Field(default=None, max_length=120)
|
||||
classification: str = Field(default="internal", min_length=1, max_length=50)
|
||||
|
||||
|
||||
class PostboxTemplateRevisionPayload(BaseModel):
|
||||
function_type_id: str | None = Field(default=None, max_length=36)
|
||||
scope_kind: Literal["tenant", "unit", "subtree", "unit_type"] = "tenant"
|
||||
scope_id: str | None = Field(default=None, max_length=255)
|
||||
name_pattern: str = Field(
|
||||
default="{unit_name} / {function_name}",
|
||||
min_length=1,
|
||||
max_length=500,
|
||||
)
|
||||
address_pattern: str = Field(
|
||||
default="{template_slug}.{unit_slug}.{function_slug}",
|
||||
min_length=1,
|
||||
max_length=500,
|
||||
)
|
||||
classification: str = Field(default="internal", min_length=1, max_length=50)
|
||||
allow_vacant_delivery: bool = True
|
||||
|
||||
|
||||
class PostboxTemplateCreateRequest(PostboxTemplateRevisionPayload):
|
||||
slug: str = Field(min_length=1, max_length=120)
|
||||
name: str = Field(min_length=1, max_length=250)
|
||||
description: str | None = None
|
||||
|
||||
|
||||
class PostboxTemplateRevisionItem(PostboxTemplateRevisionPayload):
|
||||
id: str
|
||||
revision: int
|
||||
encryption_profile: str
|
||||
history_policy: dict[str, Any] = Field(default_factory=dict)
|
||||
routing_policy: dict[str, Any] = Field(default_factory=dict)
|
||||
retention_policy: dict[str, Any] = Field(default_factory=dict)
|
||||
published_at: datetime | None = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class PostboxTemplateItem(BaseModel):
|
||||
id: str
|
||||
tenant_id: str
|
||||
slug: str
|
||||
name: str
|
||||
description: str | None = None
|
||||
status: str
|
||||
current_revision: int
|
||||
published_revision_id: str | None = None
|
||||
revisions: list[PostboxTemplateRevisionItem] = Field(default_factory=list)
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class PostboxTemplateListResponse(BaseModel):
|
||||
templates: list[PostboxTemplateItem]
|
||||
|
||||
|
||||
class PostboxTemplatePublishRequest(BaseModel):
|
||||
revision: int | None = Field(default=None, ge=1)
|
||||
|
||||
|
||||
class PostboxMaterializeRequest(BaseModel):
|
||||
organization_unit_id: str = Field(min_length=1, max_length=36)
|
||||
function_id: str = Field(min_length=1, max_length=36)
|
||||
context_key: str | None = Field(default=None, max_length=255)
|
||||
|
||||
|
||||
class PostboxOrganizationFunctionItem(BaseModel):
|
||||
id: str
|
||||
slug: str
|
||||
name: str
|
||||
function_type_id: str | None = None
|
||||
delegable: bool = False
|
||||
act_in_place_allowed: bool = False
|
||||
|
||||
|
||||
class PostboxOrganizationUnitItem(BaseModel):
|
||||
id: str
|
||||
slug: str
|
||||
name: str
|
||||
unit_type_id: str | None = None
|
||||
parent_id: str | None = None
|
||||
functions: list[PostboxOrganizationFunctionItem] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PostboxOrganizationTargetsResponse(BaseModel):
|
||||
units: list[PostboxOrganizationUnitItem]
|
||||
|
||||
|
||||
class PostboxGroupingPayload(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=250)
|
||||
is_default: bool = False
|
||||
postbox_ids: list[str] = Field(default_factory=list, max_length=250)
|
||||
|
||||
|
||||
class PostboxGroupingItem(PostboxGroupingPayload):
|
||||
id: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class PostboxGroupingListResponse(BaseModel):
|
||||
groupings: list[PostboxGroupingItem]
|
||||
Reference in New Issue
Block a user