Skip to main content

Module overlay

Module overlay 

Source
Expand description

Runtime compilation and merging of overlay CloudFormation resource provider schemas on top of the bundled compiled schemas.

Bundled schemas are compiled at build time from raw CloudFormation registry JSON into the compiled representation baked into the binary. This module runs the same transform at engine construction time, so callers can supply additional schemas - for example properties a service has shipped but not yet published to the CloudFormation registry - and have templates using them validate without false findings.

§Merge model

One model, applied uniformly: an overlay may add entries to a collection and restate a single-valued constraint or a logical group, and it never silently drops a constraint the bundled schema already carries. Adding an entry to required or to a dependency list is stating a constraint, so it can legitimately produce a finding on a template that violates it; what an overlay cannot do is make a bundled constraint disappear. Concretely, for every field of a schema or property:

Field kindRule
Keyed collections - properties, definitions, patternPropertiesdeep-merged by key: new keys are added, shared keys recurse
requiredreplaced when the overlay states the keyword (even as [] - that is how a requirement is cleared, and a removal is logged); unioned into the base when the keyword is omitted
Independent-fact collections - the /properties/... lifecycle metadata lists, and each key of dependentRequired/dependentExcludedunioned, order-preserving, deduplicated
Single-valued constraints - type, pattern, const, numeric bounds, lengths, item and property counts, uniqueItems, format, additionalProperties, not.enumreplaced when the overlay supplies them, inherited otherwise
Logical groups - requiredOr, requiredXor, primaryIdentifierreplaced as a whole when supplied. Each is one group (“at least one of”, “exactly one of”, “these properties identify the resource”), so unioning two groups would fabricate a third constraint that neither schema states
Composition - allOf/anyOf/oneOf/if-then-elsereplaced when supplied, because a complete overlay restates the whole composition and appending would duplicate branches. allOf splits into plain and conditional entries during compilation, so an overlay supplying allOf replaces both halves together
Singleton subschemas - items (the schema every array element must satisfy)deep-merged, like one keyed entry: an overlay stating only pattern narrows the element schema without discarding the rest of it
Schema-level metadata - replacementStrategy, documentationUrl, sourceUrlreplaced when supplied. These enrich reporting and constrain nothing
Enumsenum and enumCaseInsensitive are two representations of one field and are never both populated for a property. Supplying either replaces whichever the bundled schema used, keeping the bundled comparison semantics: widening a case-insensitive enum with a plain enum stays case-insensitive, so previously accepted casings keep validating

A $ref is never folded into the property that points at it. An overlay extending a $ref property has its fields merged beside the reference, and PropSchema::resolve combines the whole chain at validation time - each hop’s own constraints applied over its target, nearest hop winning. So a constraint-only overlay (say, just enum) takes effect, a chain of references is followed to its end, and a definition changed by a later overlay still reaches every property referencing it. It also means the merge never depends on the order definitions are visited in. Within a chain the same rules decide each field, so a hop that restates a single-valued constraint overrides the one further along, while collections accumulate across every hop.

An overlay that supplies a $ref for a property updates the reference target (ref_name) but preserves the base property’s existing inline/additive constraints (e.g. pattern, maxLength). This means an overlay can redirect a property to a different definition without discarding constraints the bundled schema already carries.

Overlays for the same type are applied in the order given; a later overlay sees the result of the earlier ones.

§Scope limits

  • An overlay cannot remove an entry from a lifecycle metadata list - those collections only ever grow. required is the one collection with replacement semantics (below), and any requirement a replacement removes is logged.
  • Composition entries (allOf/anyOf/oneOf branches) are full property schemas: branch required, additionalProperties, dependency maps, value constraints, and nested conditionals are all evaluated when the branch is matched or (for a selected then/else branch) enforced.
  • Constructs the compiled model does not represent - a $ref outside #/definitions/, tuple-form items, an unknown property type, malformed keyword values, or invalid regular expressions - are rejected.
  • Validation keywords with no compiled representation (propertyNames, contains, and not other than not.enum) are rejected. multipleOf and dependencies (array-form property dependencies) ARE represented and accepted.
  • Constraint siblings beside a $ref are accepted when they have a compiled representation (e.g. pattern, maxLength, enum). Only genuinely unrepresented keywords are rejected. Annotation-only siblings (description, title) are always accepted. Bundled schemas are compiled with draft-07 $ref evaluation instead (siblings ignored), so the engine never enforces more than CloudFormation’s own contract on them; an overlay author states siblings deliberately and gets them enforced.
  • enum and enumCaseInsensitive are one field in two comparison modes; an overlay cannot switch a property the service treats case-insensitively over to case-sensitive comparison, because doing so would reject casings that validate today.
  • required has authoritative replacement semantics: an overlay that explicitly states required (even as required: []) replaces the prior required list at that schema level, including clearing it. Omitting required from the overlay preserves the base’s list unchanged.
  • Conditional constraints the build pipeline contributes as extension fragments are validated from a separate embedded artifact that overlays do not merge into, so an overlay cannot suppress a finding originating there.
  • Schema-level metadata (documentationUrl, sourceUrl, replacementStrategy) alone is not sufficient - the overlay must carry at least one validatable constraint. Metadata enriches diagnostic context only when combined with properties, required, or other constraints. Annotations such as description are accepted anywhere and compiled to nothing: they have no validation meaning and no reader, so an overlay stating only a description changes nothing.
  • Overlay-derived resource types, GetAtt attributes and types, Ref return types, primary identifiers, and schema metadata are propagated to both rule engines. Region-specific availability and enum snapshots remain bundled.

§Catalog vs. config separation

The SchemaValidator separates its schema store (the validated/merged catalog of all compiled schemas) from its construction config (SchemaValidatorConfig) so embedders can serialize/deserialize the config and rebuild the validator without keeping the merged store around. The overlay catalog exposes overlay-aware metadata (type names, GetAtt/Ref types, primary identifiers) without re-merging.

Enums§

SchemaOverlayError
Why an overlay schema was rejected.

Constants§

MAX_OVERLAY_DEPTH
Maximum JSON nesting accepted in an overlay schema.