feat(postbox): add governed content protection profiles
This commit is contained in:
+145
-1
@@ -41,11 +41,84 @@ export type PostboxDirectoryItem = {
|
||||
template_revision_id?: string | null;
|
||||
holder_count: number;
|
||||
vacant: boolean;
|
||||
encryption_profile: PostboxProtectionProfileId;
|
||||
key_epoch: number;
|
||||
encryption_vault_id?: string | null;
|
||||
protection_policy: PostboxProtectionPolicy;
|
||||
access?: PostboxAccessDecision | null;
|
||||
resource_revision: number;
|
||||
etag: string;
|
||||
};
|
||||
|
||||
export type PostboxProtectionProfileId =
|
||||
| "plaintext_v1"
|
||||
| "server_envelope_v1"
|
||||
| "external_e2ee_v1";
|
||||
|
||||
export type PostboxProtectionPolicy = {
|
||||
new_incumbent_history: "all_retained" | "since_assignment" | "bounded_days";
|
||||
history_days?: number | null;
|
||||
ordinary_rotation: "rewrap" | "reencrypt";
|
||||
compromise_rotation: "rewrap" | "reencrypt";
|
||||
recovery_authority: "disabled" | "user_consent" | "institutional_key_holders" | "dual_control";
|
||||
recovery_quorum: number;
|
||||
handover_authority: "user_consent" | "institutional_key_holders" | "dual_control";
|
||||
handover_quorum: number;
|
||||
emergency_access: "disabled" | "dual_control";
|
||||
emergency_quorum: number;
|
||||
export_authority: "user_consent" | "institutional_key_holders" | "dual_control";
|
||||
export_quorum: number;
|
||||
destruction_authority: "institutional_key_holders" | "dual_control";
|
||||
destruction_quorum: number;
|
||||
external_recipient_assurance: "disabled" | "email_otp" | "strong_identity";
|
||||
vacancy_escalation_content_access: "metadata_only";
|
||||
};
|
||||
|
||||
export type PostboxProtectionProfile = {
|
||||
id: PostboxProtectionProfileId;
|
||||
label: string;
|
||||
description: string;
|
||||
server_can_decrypt: boolean;
|
||||
requires_encryption_module: boolean;
|
||||
requires_external_client: boolean;
|
||||
available: boolean;
|
||||
standard: boolean;
|
||||
};
|
||||
|
||||
export type PostboxProtectionTransition = {
|
||||
id: string;
|
||||
postbox_id: string;
|
||||
source_profile: string;
|
||||
target_profile: string;
|
||||
source_vault_id?: string | null;
|
||||
target_vault_id?: string | null;
|
||||
history_mode: string;
|
||||
authority_mode: string;
|
||||
required_quorum: number;
|
||||
evidence_refs: string[];
|
||||
reason: string;
|
||||
state: string;
|
||||
message_count: number;
|
||||
completed_count: number;
|
||||
failed_count: number;
|
||||
requested_by?: string | null;
|
||||
activated_at?: string | null;
|
||||
completed_at?: string | null;
|
||||
resource_revision: number;
|
||||
etag: string;
|
||||
configuration_snapshot: Record<string, unknown>;
|
||||
items: Array<{
|
||||
id: string;
|
||||
message_id: string;
|
||||
source_profile: string;
|
||||
target_profile: string;
|
||||
state: string;
|
||||
source_digest?: string | null;
|
||||
target_digest?: string | null;
|
||||
error_code?: string | null;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type PostboxParticipant = {
|
||||
kind: string;
|
||||
reference_type: string;
|
||||
@@ -93,7 +166,7 @@ export type PostboxMessage = {
|
||||
producer_resource_id?: string | null;
|
||||
in_reply_to_message_id?: string | null;
|
||||
replaces_message_id?: string | null;
|
||||
encryption_profile: string;
|
||||
encryption_profile: PostboxProtectionProfileId;
|
||||
key_epoch: number;
|
||||
ciphertext_ref?: string | null;
|
||||
signed_manifest_ref?: string | null;
|
||||
@@ -213,6 +286,8 @@ export type PostboxTemplateRevision = {
|
||||
allow_vacant_delivery: boolean;
|
||||
portal_visible: boolean;
|
||||
encryption_profile: string;
|
||||
encryption_vault_id?: string | null;
|
||||
protection_policy: PostboxProtectionPolicy;
|
||||
history_policy: Record<string, unknown>;
|
||||
routing_policy: PostboxRoutingPolicy;
|
||||
retention_policy: Record<string, unknown>;
|
||||
@@ -248,6 +323,9 @@ export type PostboxTemplateRevisionPayload = Pick<
|
||||
| "classification"
|
||||
| "allow_vacant_delivery"
|
||||
| "portal_visible"
|
||||
| "encryption_profile"
|
||||
| "encryption_vault_id"
|
||||
| "protection_policy"
|
||||
| "routing_policy"
|
||||
>;
|
||||
|
||||
@@ -290,12 +368,18 @@ export type PostboxExactCreatePayload = {
|
||||
address_key?: string | null;
|
||||
classification: string;
|
||||
portal_visible: boolean;
|
||||
encryption_profile: PostboxProtectionProfileId;
|
||||
encryption_vault_id?: string | null;
|
||||
protection_policy: PostboxProtectionPolicy;
|
||||
};
|
||||
|
||||
export type PostboxMessageAuthoringPayload = {
|
||||
idempotency_key: string;
|
||||
subject: string;
|
||||
body_text?: string | null;
|
||||
ciphertext_ref?: string | null;
|
||||
signed_manifest_ref?: string | null;
|
||||
wrapped_keys?: PostboxMessage["wrapped_keys"];
|
||||
classification: string;
|
||||
participants: PostboxParticipant[];
|
||||
attachments: PostboxAttachment[];
|
||||
@@ -469,6 +553,66 @@ export async function listAdminPostboxes(settings: ApiSettings): Promise<Postbox
|
||||
return response.postboxes;
|
||||
}
|
||||
|
||||
export async function listPostboxProtectionProfiles(
|
||||
settings: ApiSettings
|
||||
): Promise<{ standard_profile: PostboxProtectionProfileId; profiles: PostboxProtectionProfile[] }> {
|
||||
return apiFetch(settings, "/api/v1/postbox/admin/protection-profiles");
|
||||
}
|
||||
|
||||
export async function listPostboxProtectionTransitions(
|
||||
settings: ApiSettings,
|
||||
postboxId: string
|
||||
): Promise<PostboxProtectionTransition[]> {
|
||||
const response = await apiFetch<{ transitions: PostboxProtectionTransition[] }>(
|
||||
settings,
|
||||
`/api/v1/postbox/admin/postboxes/${encodeURIComponent(postboxId)}/protection-transitions`
|
||||
);
|
||||
return response.transitions;
|
||||
}
|
||||
|
||||
export function createPostboxProtectionTransition(
|
||||
settings: ApiSettings,
|
||||
postbox: PostboxDirectoryItem,
|
||||
payload: {
|
||||
idempotency_key: string;
|
||||
target_profile: PostboxProtectionProfileId;
|
||||
target_vault_id?: string | null;
|
||||
history_mode: "future_only" | "migrate_history";
|
||||
authority_mode: "user_consent" | "institutional_key_holders" | "dual_control";
|
||||
required_quorum: number;
|
||||
user_consent_refs: string[];
|
||||
institutional_authorization_refs: string[];
|
||||
reason: string;
|
||||
acknowledge_irreversibility: boolean;
|
||||
}
|
||||
): Promise<PostboxProtectionTransition> {
|
||||
return apiPostJson(
|
||||
settings,
|
||||
`/api/v1/postbox/admin/postboxes/${encodeURIComponent(postbox.id)}/protection-transitions`,
|
||||
{ ...payload, base_revision: postbox.resource_revision },
|
||||
{ headers: { "If-Match": postbox.etag } }
|
||||
);
|
||||
}
|
||||
|
||||
export function updatePostboxProtectionPolicy(
|
||||
settings: ApiSettings,
|
||||
postbox: PostboxDirectoryItem,
|
||||
protectionPolicy: PostboxProtectionPolicy
|
||||
): Promise<PostboxDirectoryItem> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/postbox/admin/postboxes/${encodeURIComponent(postbox.id)}/protection-policy`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "If-Match": postbox.etag },
|
||||
body: JSON.stringify({
|
||||
base_revision: postbox.resource_revision,
|
||||
protection_policy: protectionPolicy
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function listPostboxOrganizationTargets(
|
||||
settings: ApiSettings
|
||||
): Promise<PostboxOrganizationTargets> {
|
||||
|
||||
Reference in New Issue
Block a user