Requirements Document
Introduction
CascadeGuard is a CLI tool for container image lifecycle management. This feature introduces config inheritance via .cascadeguard.yaml defaults, new CLI commands for state file and CI pipeline generation, updated validation logic, and documentation updates. The goal is to eliminate per-image repetition of registry/repository fields, promote standalone scripts to first-class CLI subcommands, and fix the 25 validation failures in the cascadeguard-open-secure-images repository.
Glossary
- CLI: The
cascadeguardcommand-line interface implemented inapp.py - ConfigLoader: The module responsible for reading
.cascadeguard.yamland applying repo-level defaults to image entries - Validator: The
cmd_validatefunction that checksimages.yamlentries for required fields - ImageEntry: A single dictionary representing one image in
images.yaml - MergeDefaults: The
merge_defaults()function that applies config defaults to image entries - StateGenerator: The
cmd_images_generatecommand handler that produces state files fromimages.yaml - CIGenerator: The
cmd_ci_generatecommand handler that produces CI pipeline files fromimages.yaml - ConfigFile: The
.cascadeguard.yamlfile at the repository root containing repo-level defaults and CI settings - Parser: The
build_parser()function that defines CLI argument structure
Requirements
Requirement 1: Load Repository Configuration
User Story: As a CascadeGuard user, I want the CLI to load repo-level defaults from .cascadeguard.yaml, so that I do not have to repeat common fields on every image entry.
Acceptance Criteria
- WHEN a
.cascadeguard.yamlfile exists in the repository root, THE ConfigLoader SHALL parse the file and return a configuration dictionary - WHEN a
.cascadeguard.yamlfile does not exist in the repository root, THE ConfigLoader SHALL return an empty dictionary without raising an error - IF the
.cascadeguard.yamlfile contains invalid YAML syntax, THEN THE ConfigLoader SHALL print an error to stderr and return exit code 1 - IF the
.cascadeguard.yamlfile root value is not a dictionary, THEN THE ConfigLoader SHALL print an error to stderr and return exit code 1 - WHEN the
.cascadeguard.yamlfile contains unknown keys, THE ConfigLoader SHALL ignore the unknown keys silently
Requirement 2: Merge Config Defaults into Image Entries
User Story: As a CascadeGuard user, I want repo-level defaults for registry, repository, and local.dir to be applied to each image automatically, so that I can define these values once instead of per-image.
Acceptance Criteria
- WHEN an ImageEntry lacks a
registryfield and the ConfigFiledefaults.registryis set, THE MergeDefaults SHALL set the ImageEntryregistryto the config default value - WHEN an ImageEntry lacks a
repositoryfield and the ConfigFiledefaults.repositoryis set, THE MergeDefaults SHALL set the ImageEntryrepositoryto the config default value - WHEN an ImageEntry lacks a
local.dirfield and the ConfigFiledefaults.local.diris set, THE MergeDefaults SHALL set the ImageEntrylocal.dirto the config default value - WHEN an ImageEntry already has a
registryfield, THE MergeDefaults SHALL retain the ImageEntry value regardless of the ConfigFile default - WHEN an ImageEntry already has a
repositoryfield, THE MergeDefaults SHALL retain the ImageEntry value regardless of the ConfigFile default - WHEN an ImageEntry already has a
local.dirfield, THE MergeDefaults SHALL retain the ImageEntry value regardless of the ConfigFile default - THE MergeDefaults SHALL return a new list without mutating the original image list
- THE MergeDefaults SHALL return a list of the same length as the input image list
- WHEN the ConfigFile has no
defaultssection, THE MergeDefaults SHALL return copies of the original images with no fields added
Requirement 3: Validate Images with Config Inheritance
User Story: As a CascadeGuard user, I want cascadeguard images validate to apply config defaults before checking required fields, so that images relying on repo-level defaults pass validation.
Acceptance Criteria
- WHEN validating images, THE Validator SHALL load the ConfigFile and merge defaults before checking required fields
- WHEN an enabled ImageEntry has
name,registry, anddockerfilefields after merging defaults, THE Validator SHALL consider the ImageEntry valid - WHEN an enabled ImageEntry is missing
registryordockerfileafter merging defaults, THE Validator SHALL report a validation error indicating the missing field - WHEN a disabled ImageEntry (enabled: false) has a
namefield, THE Validator SHALL consider the ImageEntry valid regardless of other missing fields - WHEN any ImageEntry is missing the
namefield, THE Validator SHALL report a validation error regardless of enabled status - WHEN all images pass validation, THE Validator SHALL return exit code 0 and print a success count
- WHEN any image fails validation, THE Validator SHALL return exit code 1 and print all errors to stderr
- WHEN a required field is missing after merge, THE Validator SHALL include a hint that the field can be set in
.cascadeguard.yamldefaults
Requirement 4: Generate State Files via CLI
User Story: As a CascadeGuard user, I want a cascadeguard images generate command, so that I can generate state files without relying on Taskfile wrappers or Docker indirection.
Acceptance Criteria
- WHEN a user runs
cascadeguard images generate, THE StateGenerator SHALL load the ConfigFile, merge defaults, and generate state files for each image - WHEN the
--output-dirflag is provided, THE StateGenerator SHALL write state files to the specified directory - WHEN the
--output-dirflag is not provided, THE StateGenerator SHALL write state files to the current working directory - WHEN state generation succeeds, THE StateGenerator SHALL return exit code 0 and print a summary of generated files
- IF the specified
images.yamlfile does not exist, THEN THE StateGenerator SHALL print an error to stderr and return exit code 1 - WHEN
cascadeguard images generateis run twice with the same inputs, THE StateGenerator SHALL produce identical output files
Requirement 5: Generate CI Pipelines via CLI
User Story: As a CascadeGuard user, I want a cascadeguard ci generate command, so that I can generate CI pipeline files without relying on Taskfile wrappers or Docker indirection.
Acceptance Criteria
- WHEN a user runs
cascadeguard ci generate, THE CIGenerator SHALL load the ConfigFile, merge defaults, and generate CI pipeline files - WHEN the
--platformflag is provided, THE CIGenerator SHALL use the specified platform for pipeline generation - WHEN the
--platformflag is not provided and the ConfigFile hasci.platformset, THE CIGenerator SHALL use the ConfigFile platform value - WHEN neither the
--platformflag nor the ConfigFileci.platformis set, THE CIGenerator SHALL default to “github” - WHEN the
--output-dirflag is provided, THE CIGenerator SHALL write pipeline files to the specified directory - WHEN the
--output-dirflag is not provided, THE CIGenerator SHALL write pipeline files to the current working directory - WHEN the
--dry-runflag is provided, THE CIGenerator SHALL preview the output without writing files - IF the specified
images.yamlfile does not exist, THEN THE CIGenerator SHALL print an error to stderr and return exit code 1 - WHEN
cascadeguard ci generateis run twice with the same inputs, THE CIGenerator SHALL produce identical output files
Requirement 6: CLI Argument Registration
User Story: As a CascadeGuard user, I want the new commands registered in the CLI parser, so that I can discover and use them via --help and standard argument parsing.
Acceptance Criteria
- THE Parser SHALL register
generateas a subcommand under theimagescommand group - THE Parser SHALL register
cias a new top-level command with ageneratesubcommand - WHEN a user runs
cascadeguard images generate --help, THE CLI SHALL display help text describing the command and its flags - WHEN a user runs
cascadeguard ci generate --help, THE CLI SHALL display help text describing the command and its flags - THE Parser SHALL accept
--images-yaml,--output-dir, and--cache-dirflags forimages generate - THE Parser SHALL accept
--images-yaml,--output-dir,--platform, and--dry-runflags forci generate
Requirement 7: Backward Compatibility
User Story: As an existing CascadeGuard user, I want the CLI to behave identically to before when no .cascadeguard.yaml defaults section exists, so that my existing workflows are not broken.
Acceptance Criteria
- WHEN the ConfigFile has no
defaultssection, THE Validator SHALL behave identically to the current validation logic - WHEN the ConfigFile does not exist, THE CLI SHALL proceed with per-image fields only and produce the same results as the current behavior
- THE CLI SHALL preserve all existing commands and their behavior without modification
Requirement 8: Error Handling for State and CI Generation
User Story: As a CascadeGuard user, I want clear error messages when generation fails, so that I can diagnose and fix issues quickly.
Acceptance Criteria
- IF a source repository is unreachable during state generation, THEN THE StateGenerator SHALL print a warning and continue generating state for remaining images
- WHEN state generation encounters a partial failure, THE StateGenerator SHALL preserve existing state files for images that failed
- IF CI generation encounters an error, THEN THE CIGenerator SHALL print the error to stderr and return exit code 1