anodizer_core/config/preflight.rs
1//! Pre-publish preflight configuration.
2//!
3//! The `preflight:` block tunes the live publisher-state / credential probes
4//! that run before any publisher mutates an external registry. The probes
5//! themselves are always read-only; this block only changes how their
6//! outcomes gate the release.
7
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11/// Top-level `preflight:` block.
12#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
13#[serde(default, deny_unknown_fields)]
14pub struct PreflightConfig {
15 /// Promote INDETERMINATE preflight outcomes to hard blockers. An
16 /// indeterminate outcome is one where a probe could not reach a verdict —
17 /// a 5xx, a 429 / rate-limit, a transport failure, or a response that
18 /// hides the permission the publish path needs. By default those degrade
19 /// to warnings so a transient upstream blip cannot abort a release whose
20 /// credentials are actually valid; `strict: true` makes them abort
21 /// instead (fail-closed). Definitive failures (credentials rejected,
22 /// target missing) keep their required→blocker / optional→warning
23 /// severity regardless of this setting. Equivalent to passing the
24 /// global `--strict` on every run.
25 pub strict: bool,
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31
32 #[test]
33 fn empty_yaml_yields_defaults() {
34 let c: PreflightConfig = serde_yaml_ng::from_str("{}").unwrap();
35 assert_eq!(c, PreflightConfig::default());
36 assert!(!c.strict, "strict is opt-in");
37 }
38
39 #[test]
40 fn strict_true_parses() {
41 let c: PreflightConfig = serde_yaml_ng::from_str("strict: true").unwrap();
42 assert!(c.strict);
43 }
44
45 #[test]
46 fn unknown_field_rejected() {
47 let res: Result<PreflightConfig, _> = serde_yaml_ng::from_str("strict: true\nbogus: 1\n");
48 assert!(res.is_err(), "deny_unknown_fields must reject typos");
49 }
50}