/** * Content pin for the CloudFormation Registry schema (#1390). * * cfn-lint is pinned to a git tag (`PINNED_VERSIONS.cfnLint`). The registry * schema could not be: it is a single "latest" artifact with no version in the * path, republished constantly — * * $ curl -sI .../CloudformationSchema.zip * Last-Modified: Mon, 03 Aug 2026 01:29:20 GMT * * — so `npm run --prefix lexicons/aws prepack`, which CI runs on every build and * any local codegen or docs task triggers, resolved to whatever CloudFormation * shipped that morning. During the #1312 docs work a docs-only branch twice * picked up a resource-count move with nothing in the commit explaining it. The * count was only the visible symptom; the same regeneration rewrites generated * types and the resource registry. * * Since there is no version to pin, the pin is over content. Specifically over * the **extracted schemas**, not the zip: AWS repackaging the archive changes * its `ETag` and its bytes while the schemas are identical, and a pin that fires * on that would be noise. Sorted `typeName` → `sha256(schema)`, hashed in order, * moves exactly when a schema does. * * Advisory is not enough here, unlike the emulator image pins (#808). An * emulator that drifts fails a test you can see; a spec that drifts silently * rewrites committed artifacts in a branch about something else. So a mismatch * refuses, and accepting is a deliberate act that lands as its own commit. */ /** * The resource types the pinned archive contained. * * Committed beside the digest so accepting a new spec is reviewable as a diff: * the PR that moves the pin shows exactly which types AWS added or removed, * rather than one opaque hash replacing another. The generated artifacts cannot * play that role — `src/generated/` is not committed. */ export declare const PINNED_TYPE_NAMES: ReadonlySet; export interface SpecPin { /** `sha256:…` over the sorted typeName → schema content. */ readonly digest: string; /** How many resource types the pinned archive contained. */ readonly resources: number; /** ISO date the pin was accepted, so a diff reads as a decision. */ readonly accepted: string; } /** * The accepted upstream spec. * * To move it: run generation, read the refusal, confirm the delta is one you * want, and paste the printed pin here in its own commit. */ export declare const AWS_SPEC_PIN: SpecPin; /** Env var that accepts whatever upstream currently serves, printing the new pin. */ export declare const ACCEPT_ENV = "CHANT_ACCEPT_AWS_SPEC"; /** * Digest the extracted schemas. Stable against repackaging; changes when any * schema's bytes change, or when a type is added or removed. */ export declare function specContentDigest(schemas: ReadonlyMap): string; /** What moved between the pinned archive and the one just fetched. */ export interface SpecDrift { digest: string; resources: number; added: string[]; removed: string[]; } /** Compare a freshly fetched archive against a pin. `null` when it matches. */ export declare function specDrift(schemas: ReadonlyMap, pinnedNames: ReadonlySet | undefined, pin?: SpecPin): SpecDrift | null; /** The refusal a mismatch produces, or the acceptance notice under {@link ACCEPT_ENV}. */ export declare function driftMessage(drift: SpecDrift, pin?: SpecPin, options?: { fatal?: boolean; }): string; /** * Refuse a fetched archive whose RESOURCE SET does not match the pin. * * Under {@link ACCEPT_ENV} it warns with the same detail instead, so the * accept-then-paste loop is one command rather than two. * * ## Why byte drift alone is a warning (chant #1473) * * This originally threw on any digest mismatch, which made the aws lexicon * unpublishable. `prepack` runs `generate`, `generate` fetches from upstream, * and CloudFormation republishes individual schemas several times a day: three * distinct digests were observed on 2026-08-03 alone, all with an unchanged * count of 1650, and two fetches two hours apart differed in 4 of 1650 files. * `chant-v0.39.0` published 13 packages and failed on aws for exactly this, * with a pin ~18 hours old. * * A pin that goes stale by itself within hours cannot gate a release: it does * not distinguish "someone regenerated against a spec nobody chose" from * "AWS edited a description this afternoon". * * So the two cases are separated: * * - **The resource set moved** (a type added or removed) — still a refusal. * That always changes the published API, and it is the case #1390 was filed * about. * - **Only bytes moved**, with an identical type set — a warning. Whether it * matters is decided downstream by the surface gate in core's * `validateLexiconArtifacts`, which compares the generated API against the * committed `surface.snapshot.json`. That gate is exact: a byte change that * alters the emitted surface fails the build, and one that does not is * correctly ignored. * * The guarantee is unchanged in substance — nothing ships whose surface was * not reviewed — and it is now enforced against the thing that actually * matters rather than against an archive that is not stable enough to pin. */ export declare function assertPinnedSpec(schemas: ReadonlyMap, options?: { pin?: SpecPin; /** Defaults to {@link PINNED_TYPE_NAMES}; overridden in tests. */ pinnedNames?: ReadonlySet; env?: NodeJS.ProcessEnv; warn?: (message: string) => void; }): void; //# sourceMappingURL=pin.d.ts.map