/** * Canonical deployment-failure record — the single structured shape every * producer (the deploy-core classifier, the webapp worker's platform-side * shim) and every consumer (webapp UI, CLI renderers, notifications, AI * surfaces) share. Design: the 2026-08-10 deployment-failure taxonomy design, § 3. * * Pitfall guards encoded (mirroring docker/dockerCliSchemas.ts): * - Pitfall 1/6: every exported schema pairs a `z.infer` companion type * - Pitfall 3: `.strict()` on the envelope and its owned sub-objects; the * nested analysis alone is non-strict (layered strictness — see below) * - Pitfall 7: the `remediation` default uses the factory form * - Pitfall 9: optional strings carry `.min(1)` * * Masking is the producer's job (mask-then-truncate at classification time, * same discipline as `maskFailureAnalysis`); this module only validates and * size-bounds. `docsUrl` is DERIVED from `code` via `deploymentFailureDocsUrl` * and never stored. */ import { z } from "zod"; import { type FailureAnalysis } from "../aws/CloudFormationFailureAnalyser.js"; /** Where in the deploy pipeline the failure occurred. */ export declare const DEPLOYMENT_FAILURE_PHASES: readonly ["preflight", "credentials", "synth", "bootstrap", "image_build", "image_push", "cloudformation", "ecs_stabilise", "platform", "unknown"]; export declare const DeploymentFailurePhaseSchema: z.ZodEnum<{ unknown: "unknown"; platform: "platform"; bootstrap: "bootstrap"; preflight: "preflight"; credentials: "credentials"; synth: "synth"; image_build: "image_build"; image_push: "image_push"; cloudformation: "cloudformation"; ecs_stabilise: "ecs_stabilise"; }>; export type DeploymentFailurePhase = z.infer; /** Whose side the failure sits on — drives the presentation verbs. */ export declare const DEPLOYMENT_FAULT_ATTRIBUTIONS: readonly ["customer_code", "customer_aws", "platform", "indeterminate"]; export declare const DeploymentFaultAttributionSchema: z.ZodEnum<{ platform: "platform"; customer_code: "customer_code"; customer_aws: "customer_aws"; indeterminate: "indeterminate"; }>; export type DeploymentFaultAttribution = z.infer; /** Which system produced the provider-layer reason. */ export declare const DEPLOYMENT_FAILURE_PROVIDER_SOURCES: readonly ["cloudformation", "ecs", "ecr", "iam", "docker", "cdk", "npm", "other"]; export declare const DeploymentFailureProviderSourceSchema: z.ZodEnum<{ docker: "docker"; ecr: "ecr"; other: "other"; npm: "npm"; cloudformation: "cloudformation"; ecs: "ecs"; iam: "iam"; cdk: "cdk"; }>; export type DeploymentFailureProviderSource = z.infer; /** * Dotted lowercase taxonomy key, e.g. "cfn.resource_create_failed". * Single-segment codes are legal: `unclassified` is a first-class bare code * (phase-scoped variants use `unclassified.`). */ export declare const DEPLOYMENT_FAILURE_CODE_PATTERN: RegExp; export declare const DEPLOYMENT_FAILURE_SCHEMA_VERSION = 1; /** * Size caps for the record and its wire siblings. The webapp's DB/wire * `errorMessage` caps live here too so all sites import one coupled-values * module — the DB and wire caps are deliberately DIFFERENT values (10k DB * bound vs 2k wire excerpt); do not "unify" them. */ export declare const DEPLOYMENT_FAILURE_LIMITS: { /** `code` — dotted taxonomy key. */ readonly code: 128; /** `title` — stable per code; safe for one-line list rendering. */ readonly title: 120; /** `detail` — per-occurrence human sentence. */ readonly detail: 1000; /** `provider.code` — e.g. a CFN HandlerErrorCode, ECS stopCode, exit code. */ readonly providerCode: 128; /** `provider.message` — verbatim (pre-masked) provider reason. */ readonly providerMessage: 2000; /** `resource.*` — logical id / resource type / stack name. */ readonly resourceField: 256; /** One remediation bullet. */ readonly remediationStep: 1024; /** Remediation bullet count. */ readonly remediationSteps: 10; /** `excerpt` — capture-time first-error log window, pre-masked. */ readonly excerpt: 2000; /** `logRef` — pointer to the full log, never the log itself. */ readonly logRef: 512; /** `classifierVersion` — enables re-classification of stored rows. */ readonly classifierVersion: 32; /** Nested analysis: any single free-text string (summary, reason, statusReason). */ readonly analysisString: 2000; /** Nested analysis: affected-resources cap — a stuck stack can list hundreds. */ readonly analysisAffectedResources: 50; /** Nested analysis: dependency-chain cap. */ readonly analysisDependencyChain: 50; /** Nested analysis: remediation-bullet cap. */ readonly analysisRemediation: 20; /** Nested analysis: drift-suspects cap. */ readonly analysisDriftSuspects: 50; /** Wire cap for the derived legacy `errorMessage` composition ("title: detail"). */ readonly errorMessageWire: 2000; /** DB cap for the legacy `Deployment.errorMessage` column (mirrors its bound). */ readonly errorMessageDb: 10000; }; /** * Wire mirror of `FailureAnalysis` (@fjall/util/aws) — shape-only validation; * size-bounding happens at construction (`toDeploymentFailureAnalysis`) and at * the persistence boundary, never by rejection (an oversized display-only * string must not void the whole record). */ export declare const DeploymentFailureAnalysisSchema: z.ZodObject<{ rootCause: z.ZodObject<{ resource: z.ZodObject<{ logicalId: z.ZodString; resourceType: z.ZodString; status: z.ZodString; statusReason: z.ZodOptional; physicalId: z.ZodOptional; timestamp: z.ZodOptional; group: z.ZodOptional; constructPath: z.ZodOptional; }, z.core.$strip>; reason: z.ZodString; category: z.ZodEnum<{ unknown: "unknown"; network: "network"; permissions: "permissions"; validation: "validation"; dependency: "dependency"; limit: "limit"; }>; isDirectCause: z.ZodBoolean; }, z.core.$strip>; affectedResources: z.ZodArray; physicalId: z.ZodOptional; timestamp: z.ZodOptional; group: z.ZodOptional; constructPath: z.ZodOptional; }, z.core.$strip>>; dependencyChain: z.ZodArray; summary: z.ZodString; remediation: z.ZodArray; errorPattern: z.ZodOptional; driftSuspects: z.ZodOptional; failedStatus: z.ZodString; statusReason: z.ZodString; }, z.core.$strip>>>; }, z.core.$strip>; export type DeploymentFailureAnalysis = z.infer; /** The Stripe decline_code layer — what AWS/docker/npm actually said. */ export declare const DeploymentFailureProviderSchema: z.ZodObject<{ source: z.ZodEnum<{ docker: "docker"; ecr: "ecr"; other: "other"; npm: "npm"; cloudformation: "cloudformation"; ecs: "ecs"; iam: "iam"; cdk: "cdk"; }>; code: z.ZodOptional; message: z.ZodString; }, z.core.$strict>; export type DeploymentFailureProvider = z.infer; /** The failure's locus, when a specific resource/stack is known. */ export declare const DeploymentFailureResourceSchema: z.ZodObject<{ logicalId: z.ZodOptional; resourceType: z.ZodOptional; stackName: z.ZodOptional; }, z.core.$strict>; export type DeploymentFailureResource = z.infer; export declare const DeploymentFailureSchema: z.ZodObject<{ schemaVersion: z.ZodLiteral<1>; code: z.ZodString; phase: z.ZodEnum<{ unknown: "unknown"; platform: "platform"; bootstrap: "bootstrap"; preflight: "preflight"; credentials: "credentials"; synth: "synth"; image_build: "image_build"; image_push: "image_push"; cloudformation: "cloudformation"; ecs_stabilise: "ecs_stabilise"; }>; fault: z.ZodEnum<{ platform: "platform"; customer_code: "customer_code"; customer_aws: "customer_aws"; indeterminate: "indeterminate"; }>; title: z.ZodString; detail: z.ZodString; provider: z.ZodOptional; code: z.ZodOptional; message: z.ZodString; }, z.core.$strict>>; resource: z.ZodOptional; resourceType: z.ZodOptional; stackName: z.ZodOptional; }, z.core.$strict>>; remediation: z.ZodDefault>; excerpt: z.ZodOptional; logRef: z.ZodOptional; analysis: z.ZodOptional; physicalId: z.ZodOptional; timestamp: z.ZodOptional; group: z.ZodOptional; constructPath: z.ZodOptional; }, z.core.$strip>; reason: z.ZodString; category: z.ZodEnum<{ unknown: "unknown"; network: "network"; permissions: "permissions"; validation: "validation"; dependency: "dependency"; limit: "limit"; }>; isDirectCause: z.ZodBoolean; }, z.core.$strip>; affectedResources: z.ZodArray; physicalId: z.ZodOptional; timestamp: z.ZodOptional; group: z.ZodOptional; constructPath: z.ZodOptional; }, z.core.$strip>>; dependencyChain: z.ZodArray; summary: z.ZodString; remediation: z.ZodArray; errorPattern: z.ZodOptional; driftSuspects: z.ZodOptional; failedStatus: z.ZodString; statusReason: z.ZodString; }, z.core.$strip>>>; }, z.core.$strip>>; classifierVersion: z.ZodString; }, z.core.$strict>; export type DeploymentFailure = z.infer; /** * Validate a wire/JSONB value into a `DeploymentFailure`, returning null for * absent/malformed input — consumers render the legacy `errorMessage` fallback * rather than crashing on a record a newer/older engine produced. */ export declare function parseDeploymentFailure(raw: unknown): DeploymentFailure | null; export declare const DEPLOYMENT_FAILURE_DOCS_BASE_URL = "https://docs.fjall.io/errors"; /** `docsUrl` is derived from `code`, never stored (Vercel/Stripe pattern). */ export declare function deploymentFailureDocsUrl(code: string): string; /** * Fault-attribution copy shared by every renderer (CLI Ink, non-interactive, * webapp Tier 2) so the product speaks with one voice about whose side a * failure sits on. Exhaustive over the fault enum — a new attribution fails to * compile here. Webapp mirror: FAULT_COPY at * webapp/app/components/deployment/deployment-status-header.tsx (byte-identical * strings until the engine-dependency bump replaces the mirror). */ export declare const DEPLOYMENT_FAULT_COPY: Record; /** * Display labels for the provider-source enum, shared by every renderer. * Exhaustive — a new source fails to compile here. Webapp mirror: * PROVIDER_LABELS at * webapp/app/components/deployment/deployment-status-header.tsx. */ export declare const DEPLOYMENT_PROVIDER_LABELS: Record; /** * Compose the derived legacy `errorMessage` from a failure record * ("title: detail", wire-bounded) — writers persist this alongside `failure` * so grep/SQL consumers and pre-taxonomy readers keep working. Webapp mirror: * deriveErrorMessageFromFailure at * webapp/app/lib/deployment/deployment-failure.ts (same name so the * engine-dependency bump swaps the import without a rename). */ export declare function deriveErrorMessageFromFailure(failure: DeploymentFailure): string; /** * Convert the in-memory `FailureAnalysis` (Date timestamps) into the JSON-safe * wire form nested inside a `DeploymentFailure`, size-bounding arrays and * free-text so the record stays within its persistence budget. Pure — does not * mask (the engine producer already masked via `maskFailureAnalysis`). */ export declare function toDeploymentFailureAnalysis(analysis: FailureAnalysis): DeploymentFailureAnalysis;