Files
kyleandClaude Opus 5.5 0f1de0d6d4 M5b plan: task 02, the secret store moves to bxcore
The task moves gatewayd's secret store to bxcore::secrets behind the
Cargo feature `secrets` (spec, section 5). The moved module is given
whole; SecretSpec and SecretSource move with it, so gatewayd's config
keeps its [secrets.<name>] table with the per-secret type from bxcore.
load and read_checked take the role's name first, so the three
sentences that named gatewayd literally now name the role; gatewayd
passes "gatewayd" and its bytes are unchanged (its tests/main.rs pins
them and is not touched). A given loopd test parses the three
manifests (loopd's, the workspace entry, bxcore's features) and checks
the cfg line in bxcore's lib.rs; the task also checks `cargo tree -p
loopd -e features` and builds loopd on its own.

Checked: the reference, replayed from the task text applied
mechanically to the start tree (master plus task 01), is byte for byte
the reference; every before block found exactly once there. Step 2's
failures recorded from that tree: ten test targets with E0432 on
`bxcore::secrets`, two of four no_secrets tests. make gate on titan's
toolchain: gate: ok, 963 tests (956 + 3 + 4), clippy clean, /tmp
unchanged across the run. 23 one-line mutations of the reference, all
caught; removing the zeroize wrapper is not observable and not counted. Given
files pass fmt and the line limit; no chat-template tags.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 02:56:26 -07:00

96 lines
3.6 KiB
Rust

//! `loopd` holds no credentials, so no build of it enables `bxcore`'s feature `secrets` (M5b spec,
//! section 5), and its binary does not contain the code that reads them. Three manifests decide
//! that: `loopd`'s own, the workspace's entry for `bxcore`, and `bxcore`'s feature table. They are
//! parsed, so every spelling TOML allows is read. `make gate` builds the workspace with the feature
//! on (for `gatewayd`), so it cannot see a module that is not behind the feature; the last test
//! checks that line of `bxcore`'s `lib.rs`. Do not edit.
use std::path::{Path, PathBuf};
fn manifest(path: &Path) -> toml::Table {
let text = std::fs::read_to_string(path)
.unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display()));
text.parse::<toml::Table>()
.unwrap_or_else(|e| panic!("cannot parse {}: {e}", path.display()))
}
fn crates() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("..")
}
/// Every string in `value`, at any depth, that turns the feature on: `secrets`, `bxcore/secrets`
/// or `bxcore?/secrets`.
fn enabling(value: &toml::Value, found: &mut Vec<String>) {
match value {
toml::Value::String(s) if s == "secrets" || s.ends_with("/secrets") => {
found.push(s.clone())
}
toml::Value::Array(items) => items.iter().for_each(|v| enabling(v, found)),
toml::Value::Table(table) => table.values().for_each(|v| enabling(v, found)),
_ => {}
}
}
#[test]
fn loopd_never_names_the_feature() {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
let table = manifest(&path);
assert!(table.contains_key("dependencies"), "{}", path.display());
let mut found = Vec::new();
enabling(&toml::Value::Table(table), &mut found);
assert!(found.is_empty(), "{} enables {found:?}", path.display());
}
#[test]
fn the_workspace_entry_for_bxcore_enables_nothing() {
let path = crates().join("../Cargo.toml");
let table = manifest(&path);
let entry = table
.get("workspace")
.and_then(|w| w.get("dependencies"))
.and_then(|d| d.get("bxcore"))
.unwrap_or_else(|| panic!("{}: no [workspace.dependencies] bxcore", path.display()));
assert_eq!(entry.get("features"), None, "{entry:?}");
}
#[test]
fn only_the_feature_itself_turns_the_store_on() {
let path = crates().join("bxcore/Cargo.toml");
let table = manifest(&path);
let features = table
.get("features")
.and_then(toml::Value::as_table)
.unwrap_or_else(|| panic!("{}: no [features]", path.display()));
assert!(features.contains_key("secrets"), "{features:?}");
for (name, list) in features {
if name == "secrets" {
continue;
}
let mut found = Vec::new();
enabling(list, &mut found);
assert!(found.is_empty(), "feature {name} turns on {found:?}");
}
let zeroize = table
.get("dependencies")
.and_then(|d| d.get("zeroize"))
.unwrap_or_else(|| panic!("{}: no zeroize", path.display()));
assert_eq!(
zeroize.get("optional").and_then(toml::Value::as_bool),
Some(true),
"zeroize is built only with the feature"
);
}
#[test]
fn the_module_is_compiled_only_with_the_feature() {
let path = crates().join("bxcore/src/lib.rs");
let text = std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("cannot read {}: {e}", path.display()));
assert!(
text.contains("#[cfg(feature = \"secrets\")]\npub mod secrets;\n"),
"{}: `pub mod secrets;` must follow `#[cfg(feature = \"secrets\")]`",
path.display()
);
assert_eq!(text.matches("mod secrets").count(), 1, "{}", path.display());
}