feat(campaigns): add governed collaboration thread
Module Package Release / publish-packages (push) Successful in 13s

This commit is contained in:
2026-08-22 00:09:34 +02:00
parent 5a21067e44
commit c2f083e5f6
25 changed files with 2315 additions and 24 deletions
+102
View File
@@ -38,6 +38,49 @@ export type CampaignShare = {
export type CampaignShareTarget = {id: string;name: string;secondary?: string | null;};
export type CampaignShareTargets = {users: CampaignShareTarget[];groups: CampaignShareTarget[];};
export type CampaignCollaborationReferenceKind =
| "campaign_version"
| "recipient_import_batch"
| "attachment_rule"
| "delivery_job"
| "report";
export type CampaignCollaborationReference = {
kind: CampaignCollaborationReferenceKind;
id: string;
label?: string | null;
};
export type CampaignCollaborationEntry = {
id: string;
campaign_id: string;
actor_user_id?: string | null;
actor_label: string;
visibility: "collaborators" | "moderators";
content?: string | null;
content_sha256: string;
mention_user_ids: string[];
reference?: CampaignCollaborationReference | null;
tombstone?: "withdrawn" | "redacted" | null;
tombstone_reason?: string | null;
withdrawn_at?: string | null;
redacted_at?: string | null;
created_at: string;
};
export type CampaignCollaborationListResponse = {
items: CampaignCollaborationEntry[];
next_cursor?: string | null;
has_more: boolean;
};
export type CampaignCollaborationCreate = {
content: string;
visibility?: CampaignCollaborationEntry["visibility"];
reference?: Pick<CampaignCollaborationReference, "kind" | "id"> | null;
mention_user_ids?: string[];
};
export type CampaignArchiveEncryptionPolicy = {
available: boolean;
allowed_password_encryption_methods: Array<"aes" | "zip_standard">;
@@ -1763,6 +1806,65 @@ export async function getCampaignShareTargets(settings: ApiSettings, campaignId:
return apiFetch<CampaignShareTargets>(settings, `/api/v1/campaigns/${campaignId}/share-targets`);
}
export async function listCampaignCollaboration(
settings: ApiSettings,
campaignId: string,
options: {cursor?: string | null;limit?: number;} = {}
): Promise<CampaignCollaborationListResponse> {
const params = new URLSearchParams({ limit: String(options.limit ?? 25) });
if (options.cursor) params.set("cursor", options.cursor);
return apiFetch<CampaignCollaborationListResponse>(
settings,
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration?${params.toString()}`
);
}
export async function createCampaignCollaborationEntry(
settings: ApiSettings,
campaignId: string,
payload: CampaignCollaborationCreate
): Promise<CampaignCollaborationEntry> {
return apiFetch<CampaignCollaborationEntry>(
settings,
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration`,
{ method: "POST", body: JSON.stringify(payload) }
);
}
export async function withdrawCampaignCollaborationEntry(
settings: ApiSettings,
campaignId: string,
entryId: string
): Promise<CampaignCollaborationEntry> {
return apiFetch<CampaignCollaborationEntry>(
settings,
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/${encodeURIComponent(entryId)}/withdraw`,
{ method: "POST", body: JSON.stringify({}) }
);
}
export async function redactCampaignCollaborationEntry(
settings: ApiSettings,
campaignId: string,
entryId: string
): Promise<CampaignCollaborationEntry> {
return apiFetch<CampaignCollaborationEntry>(
settings,
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/${encodeURIComponent(entryId)}/redact`,
{ method: "POST", body: JSON.stringify({}) }
);
}
export function campaignCollaborationMentionProvider(
settings: ApiSettings,
campaignId: string
): ReferenceOptionProvider {
return apiReferenceOptionProvider(
settings,
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/mention-options`
);
}
export function campaignShareTargetProvider(
settings: ApiSettings,
campaignId: string,