module
Noir::CliValidation
Defined in:
cli_validation.crConstant Summary
-
VALID_OUTPUT_FORMATS =
["plain", "yaml", "json", "jsonl", "toml", "markdown-table", "sarif", "html", "curl", "httpie", "powershell", "oas2", "oas3", "postman", "only-url", "only-param", "only-header", "only-cookie", "only-tag", "mermaid"] of ::String
Class Method Summary
- .exit_with_error(message : String) : NoReturn
- .validate!(options : Hash(String, YAML::Any))
-
.validate_ai_provider_pair!(options : Hash(String, YAML::Any))
--ai-providerand--ai-modelneed each other to take effect. - .validate_base_paths!(options : Hash(String, YAML::Any))
- .validate_concurrency!(options : Hash(String, YAML::Any))
-
.validate_config_file!(options : Hash(String, YAML::Any))
--config-file PATHneeds to exist, be a file (not a directory), and parse as a YAML mapping. - .validate_output_format!(options : Hash(String, YAML::Any))
- .validate_output_path!(options : Hash(String, YAML::Any))
-
.validate_passive_scan_paths!(options : Hash(String, YAML::Any))
--passive-scan-path PATHaccepts multiple entries (repeatable), and each must exist + be a directory —NoirPassiveScan.load_ruleswalksPATH/**/*.{yml,yaml}and Dir.glob silently returns zero matches for non-existent paths. - .validate_tagger_names!(options : Hash(String, YAML::Any))
-
.validate_tech_names!(options : Hash(String, YAML::Any))
-t/--techs,--only-techs,--exclude-techsshould reject unknown tech names eagerly. -
.warn_about_unused_delivery_flags(options : Hash(String, YAML::Any))
--probe-matchand--probe-skiponly run inside the Deliver pipeline (the code that ships endpoints to --probe / --probe-via / --export-es / --export-webhook).
Class Method Detail
--ai-provider and --ai-model need each other to take effect.
Either flag set on its own silently skips the AI analyzer:
--ai-provider openai(no model) —ai_provider_active?is false, AI never runs, user just gets a plain scan--ai-model gpt-4(no provider) — same outcome The ACP family is the one exception:acp:claude/acp:codexcarry their own default model, so no--ai-modelis required.
--config-file PATH needs to exist, be a file (not a directory),
and parse as a YAML mapping. The previous shape let File.read /
YAML.parse raise straight through to the user, producing a
Crystal stack trace for what should be a one-line "wrong path"
message.
--passive-scan-path PATH accepts multiple entries (repeatable),
and each must exist + be a directory — NoirPassiveScan.load_rules
walks PATH/**/*.{yml,yaml} and Dir.glob silently returns zero
matches for non-existent paths. The result is a passive scan that
ran with 0 rules and surfaced 0 findings, with no indication that
the path was bogus. Surface the typo at CLI parse time instead.
-t/--techs, --only-techs, --exclude-techs should reject
unknown tech names eagerly. Pre-fix, a typo like --only-techs falsk (instead of flask) silently dropped through
NoirTechs.similar_to_tech returning "" and the scan produced
zero endpoints without explanation — indistinguishable from
"no flask code found here". Surfacing the typo at CLI parse
time saves the surprise.
--probe-match and --probe-skip only run inside the Deliver
pipeline (the code that ships endpoints to --probe / --probe-via /
--export-es / --export-webhook). With no delivery target
configured they silently no-op — a real surprise for users who
set the flags expecting stdout output to be filtered. Warn at
CLI parse time so the gap is obvious.