import { type Result } from "@fjall/generator"; import type { AwsSdkClientLike } from "./zoneClassifier.js"; /** * A DNS record ACM is waiting on. The name is fully qualified as ACM * publishes it (trailing dot), so it pastes into any DNS provider that takes * absolute names. ACM derives the record from the account and the name, so a * wildcard and its base name, or two certificates covering one name, share a * record: `domainNames` lists every name it validates. */ export interface CertificateValidationRecord { readonly name: string; readonly type: string; readonly value: string; readonly domainNames: readonly string[]; } /** How a certificate stands with respect to validation. */ export type CertificateValidationVerdict = "issued" | "pending" | "unusable"; export interface ObservedCertificate { readonly arn: string; readonly domainName: string; /** ACM's certificate status, verbatim. */ readonly status: string; /** A status ACM adds after this release reads as `unusable`. */ readonly verdict: CertificateValidationVerdict; /** ACM's failure reason (for example `CAA_ERROR`), when it gives one. */ readonly failureReason?: string; } export interface CertificateValidationSnapshot { readonly stackStatus: string; readonly certificates: readonly ObservedCertificate[]; /** Records still needed by pending certificates, one per distinct record. */ readonly outstanding: readonly CertificateValidationRecord[]; /** * Names on pending certificates whose record ACM has not published yet * (the first seconds after the certificate is requested). */ readonly awaitingRecordFor: readonly string[]; } export type CertificateValidationReadErrorKind = "access-denied" | "unavailable" | "aborted"; /** * A failed certificate-validation read. Messages are pre-masked at * construction: every dynamic fragment is an SDK error message routed * through `maskSensitiveOutput`, and the rest are stack names and IAM action * names. */ export declare class CertificateValidationReadError extends Error { readonly kind: CertificateValidationReadErrorKind; constructor(kind: CertificateValidationReadErrorKind, message: string); } export interface CertificateValidationReadParams { /** CloudFormation client in the domain stack's region. */ readonly cloudFormation: AwsSdkClientLike; /** ACM client in the same region: the stack's certificates live there. */ readonly acm: AwsSdkClientLike; readonly stackName: string; readonly abortSignal?: AbortSignal; } /** * Read the ACM validation state of every certificate a domain stack owns or * is creating. * * `success(undefined)` is positive absence: CloudFormation reports the stack * does not exist. A certificate is found two ways, because each misses one * case. ListStackResources names the certificates the stack records, but * while a certificate is being replaced it can still show the old ARN. So * while an operation is in progress, the stack events back to that * operation's start are also read; they carry the new ARN from the moment * CloudFormation asks ACM for it. A certificate whose newest event is a * delete (a rollback, a replaced certificate's cleanup) is left out. */ export declare function readCertificateValidation(params: CertificateValidationReadParams): Promise>; /** * A validation record's identity. ACM can spell one record differently on * different certificates or reads (case, trailing dot), so every site that * decides whether two records are the same one keys on this. */ export declare function certificateValidationRecordKey(record: Pick): string; /** * One line per record, for a failure message or a verify report: * `CNAME -> (validates )`. */ export declare function formatCertificateValidationRecord(record: CertificateValidationRecord): string; /** Why a certificate will not validate, for a deploy warning or a verify report. */ export declare function describeUnusableCertificate(certificate: ObservedCertificate): string;