Validate all first-party blocks in a composite stack.
For every StackBlockNode with a path field set, this function verifies that:
1. The path is not absolute (only relative paths are permitted). 2. The path resolves to a directory within base_dir after std::fs::canonicalize is applied (prevents symlink-based traversal). 3. The resolved directory exists on the filesystem. 4. The block also has a command set (required for first-party blocks).
Third-party blocks (no path) are skipped entirely.
Arguments
stack — The parsed composite stack to validate. base_dir — The working directory against which relative paths are resolved. Typically the current working directory (std::env::current_dir()).
Returns
Ok(()) if all first-party blocks are valid.
Errors
StackError::FirstPartyAbsolutePath — path is absolute.StackError::FirstPartyPathTraversal — resolved path escapes base_dir.StackError::FirstPartyPathNotFound — the directory does not exist.StackError::FirstPartyMissingCommand — block has path but no command.
Security
Uses canonicalize + starts_with as the security boundary. String-based .. checks are intentionally omitted — paths like ./sub/../sibling that stay within base_dir are accepted by design.
Examples
# use bridge::stack::composite::CompositeStack;
# use bridge::stack::parser::validate_first_party_blocks;
# use std::path::Path;
let yaml = r#"
my-app:
blocks:
api:
path: "./backend"
command: ["npm", "start"]
"#;
let stack = CompositeStack::from_yaml(yaml).unwrap();
validate_first_party_blocks(&stack, Path::new("/home/user/project")).unwrap();