import { type BackupClient } from "@aws-sdk/client-backup"; import { type KMSClient } from "@aws-sdk/client-kms"; import { type Result } from "@fjall/generator"; import { BACKUP_VAULT_NAME, type BackupVaultVerdict } from "@fjall/util"; import type { CloudFormationService } from "../../services/infrastructure/CloudFormationService.js"; export { BACKUP_VAULT_NAME }; export interface BackupGlobalSettings { enableCrossAccountBackup?: boolean; enableDelegatedAdministrator?: boolean; enableMpa?: boolean; } /** * Update AWS Backup global settings for the organisation. * Idempotent — safe to call repeatedly with the same settings. */ export declare function updateBackupGlobalSettings(client: BackupClient, settings?: BackupGlobalSettings, abortSignal?: AbortSignal): Promise>; /** * Whether an account's synthesised stack declares the DR backup vault — and * so whether `probeBackupVaultOwnership` needs to run for it. Mirror of the * DisasterRecovery construct gate in @fjall/components-infrastructure * patterns/aws/account.ts: the vault is synthesised only when * `disasterRecoveryRegion` is set AND the account is production or compliance. * * Probing accounts that synthesise no vault (platform/staging/development) is * dead work that fails on a `backup:DescribeBackupVault` permission those * accounts never grant. Keep this predicate in lockstep with account.ts:122-125. */ export declare function accountHasDisasterRecovery(environment: string | null | undefined, disasterRecoveryRegion: string | undefined): boolean; export interface BackupVaultOwnershipProbe { backup: BackupClient; /** Reads the manager of an unowned vault's key — the import gate. */ kms: KMSClient; /** The target account's CloudFormation seam (type-only: no runtime cycle). */ cfn: Pick; /** The account stack that owns the vault when it is owned at all. */ stackName: string; abortSignal?: AbortSignal; } /** * Probe who owns the fixed-name DR vault in the target account/region, before * synth: the verdict travels to the construct as `-c fjallBackupVault=` * (`BackupVaultVerdictSchema` in @fjall/util is the wire contract) and picks * the template — create, managed stack key, or re-owned against the live key. * * One DescribeBackupVault, one paginated ListStackResources on the account * stack, and for an unowned vault one DescribeKey. Owned ⇔ a current * `AWS::Backup::BackupVault` row (`currentStackResource`) whose physical id * is the vault name; `keyInStack` ⇔ a current `AWS::KMS::Key` row whose * physical id is the live key's id. A never-deployed stack has no live * resources, so `stack_not_found` reads as unowned. The listing fulfils with * the pages it read before an abort, and a partial listing reads an owned * vault as unowned, so the probe re-checks the signal after it. A vault owned * by ANOTHER stack is not distinguished — the import change set fails loudly * with CloudFormation's own "already belongs to another stack". * * Refuses, before any verdict, a vault whose key is not customer-managed — * AWS-owned (no key ARN), or AWS-managed (`KeyManager` AWS, read for an * unowned vault: the import is where a key Fjall cannot alias must be * stopped, and a vault already in the stack was vetted when it was created * or imported). The re-owned template aliases the key and the DR plans copy * cross-account; neither works on such a key, and the message names the cure. * * Every read failure fails the probe (the caller fails the account): a * mis-read verdict either re-CREATEs a colliding vault or declares a re-owned * vault against the wrong key, and `EncryptionKeyArn` is create-only, so the * second mistake replaces the vault. Failure messages are pre-masked at * construction. */ export declare function probeBackupVaultOwnership(probe: BackupVaultOwnershipProbe): Promise>; /** * A backup vault that survives stack teardown (vault + KMS key are * RemovalPolicy.RETAIN). Populated from a single DescribeBackupVault call — * deliberately NOT paginating recovery points, which on a populated vault would * be tens of API calls inside a destroy gate. Per-point expiry detail belongs * in the dedicated `fjall backup status` view (G4). */ export interface SurvivingBackupVault { vaultName: string; region: string; locked: boolean; lockDate?: Date; lockPermanent: boolean; recoveryPointCount: number; encryptionKeyArn?: string; } /** * Probe the fixed-name DR vault for what survives a destroy. Returns * success(null) when no vault exists (ResourceNotFoundException); every other * error propagates as failure for the caller to treat as best-effort. */ export declare function describeSurvivingBackupVault(client: BackupClient, region: string, abortSignal?: AbortSignal): Promise>; /** * Honest, non-suppressible warning for a backup vault a destroy cannot remove. * The vault and its KMS key are RemovalPolicy.RETAIN — CloudFormation marks them * DELETE_SKIPPED and reports the destroy clean; this makes the orphan visible. */ export declare function formatSurvivingVaultWarning(vault: SurvivingBackupVault): string;