import type { MessageResponse } from "./index.js"; export declare const VIOLATION_THREAD_LAYOUTS: readonly ["three_containers", "single_container", "compact_incident", "conversation_evidence", "spoiler_evidence"]; export type ViolationThreadLayout = (typeof VIOLATION_THREAD_LAYOUTS)[number]; export declare const VIOLATION_THREAD_REQUIRED_PERMISSIONS: readonly ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY", "CREATE_PRIVATE_THREADS", "SEND_MESSAGES_IN_THREADS", "MANAGE_THREADS", "MANAGE_ROLES", "MANAGE_CHANNELS"]; export declare const VIOLATION_THREAD_ACCESS_PERMISSIONS: readonly ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY", "SEND_MESSAGES_IN_THREADS"]; export declare const VIOLATION_THREAD_RUNTIME_PERMISSIONS: readonly ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY", "CREATE_PRIVATE_THREADS", "SEND_MESSAGES_IN_THREADS", "MANAGE_THREADS"]; export declare const VIOLATION_THREAD_LIMITS: Readonly<{ moderatorRoles: 10; moderatorUsers: 10; unsafeChannelExamples: 20; evidenceCharacters: 2000; evidenceUtf8Bytes: 32768; evidenceLifetimeSeconds: 30; }>; export type ViolationThreadPermissionName = (typeof VIOLATION_THREAD_REQUIRED_PERMISSIONS)[number]; interface ViolationEvidenceReferenceBase { key: string; sourceEventId: string; guildId: string; channelId: string; messageId: string | null; authorUserId: string; } export type ViolationEvidenceReference = (ViolationEvidenceReferenceBase & { source: "discord_auto_moderation"; configurationRevision?: never; }) | (ViolationEvidenceReferenceBase & { source: "enhanced_scanner"; configurationRevision: string; }); export type ViolationAccessRoleInspection = { outcome: "safe"; roleId: string; } | { outcome: "missing" | "everyone" | "managed" | "hierarchy_blocked" | "dangerous_permissions" | "unintended_channel_access"; roleId: string; dangerousPermissionNames: readonly string[]; unintendedChannelIds: readonly string[]; unintendedChannelCount: number; truncated: boolean; }; export type ViolationThreadConfigurationInspection = { outcome: "allowed"; configurationRevision: string; accessRole: ViolationAccessRoleInspection | null; missingPermissions: readonly ViolationThreadPermissionName[]; requiredChanges: readonly string[]; } | { outcome: "guild_mismatch" | "channel_missing" | "role_missing" | "unsafe_access_role" | "denied"; configurationRevision: string | null; accessRole: ViolationAccessRoleInspection | null; missingPermissions: readonly ViolationThreadPermissionName[]; requiredChanges: readonly string[]; safeCode: string; }; export type ViolationThreadConfigurationResult = { outcome: "configured" | "already_configured"; configurationRevision: string; appliedChanges: readonly string[]; } | { outcome: "stale_inspection" | "channel_missing" | "role_missing" | "unsafe_access_role" | "missing_permission" | "failed" | "ambiguous"; safeCode?: string; }; export type ViolationThreadMutationResult = { outcome: "created" | "already_exists"; threadId: string; } | { outcome: "channel_missing" | "thread_missing" | "member_missing" | "missing_permission" | "capacity_exceeded" | "no_longer_required" | "failed" | "ambiguous"; safeCode?: string; }; export type ViolationThreadDeliveryResult = { outcome: "sent" | "already_sent"; messageId: string; } | { outcome: "evidence_unavailable" | "evidence_mismatch" | "thread_missing" | "missing_permission" | "failed" | "ambiguous"; safeCode?: string; }; /** Guild-owner-routed adapter for role-gated private violation threads. */ export interface ViolationThreadService { inspectConfiguration(input: { guildId: string; parentChannelId: string; accessRoleId: string | null; moderatorRoleIds: readonly string[]; moderatorUserIds?: readonly string[]; }): Promise; createAccessRole(input: { guildId: string; name: string; operationKey: string; revalidate(): Promise; }): Promise<{ outcome: "created"; roleId: string; } | { outcome: "missing_permission" | "no_longer_required" | "failed" | "ambiguous"; safeCode?: string; }>; configureParent(input: { guildId: string; parentChannelId: string; accessRoleId: string; moderatorRoleIds: readonly string[]; moderatorUserIds?: readonly string[]; expectedConfigurationRevision: string; operationKey: string; revalidate(): Promise; }): Promise; create(input: { guildId: string; parentChannelId: string; name: string; operationKey: string; revalidate(): Promise; }): Promise; addMember(input: { guildId: string; threadId: string; memberUserId: string; operationKey: string; }): Promise; removeMember(input: { guildId: string; threadId: string; memberUserId: string; operationKey: string; }): Promise; send(input: { guildId: string; threadId: string; response: MessageResponse; presentation?: { layout: ViolationThreadLayout; caseNumber: number; }; operationKey: string; }): Promise; /** Replace staff controls without changing the bot-owned message body or its mentions. */ editControls?(input: { guildId: string; threadId: string; messageId: string; buttons: NonNullable; operationKey: string; revalidate(): Promise; }): Promise<{ outcome: "updated"; } | { outcome: "failed"; safeCode: string; }>; close(input: { guildId: string; threadId: string; /** Delete only the bound private thread after closing it; records remain intact. */ deleteThread?: boolean; /** Required when deleteThread is true. */ parentChannelId?: string; operationKey: string; revalidate(): Promise; }): Promise; reconcile(input: { guildId: string; parentChannelId: string; threadId?: string; /** Destructive recovery must reject existing threads not created by this bot. */ requireBotOwner?: boolean; operationKey: string; }): Promise<{ outcome: "exists"; threadId: string; archived: boolean; locked: boolean; } | { outcome: "absent" | "unknown"; safeCode?: string; }>; } export {};