max / makenotwork
743 files changed,
+50603 insertions,
-28013 deletions
| @@ -106,8 +106,12 @@ | |||
| 106 | 106 | | Kind | When | What it proves | | |
| 107 | 107 | |------|------|----------------| | |
| 108 | 108 | | `code_smoke` | build | Boots the fresh binary on a throwaway DB it migrates from scratch and seeds, then probes `/health`. Runs first: green here isolates a later red as an environment problem, not a code one. | | |
| 109 | + | | `fmt` | build | `cargo fmt --check` over every `[[test_target]]`. No compilation, so it fails fast. | | |
| 109 | 110 | | `cargo_test` | build | Every configured `[[test_target]]` crate's suite, in order (see below). | | |
| 110 | 111 | | `hardening_test` | build | What `cargo_test` structurally cannot reach (see below). | | |
| 112 | + | | `clippy` | build | `cargo clippy --all-targets -- -D warnings` over every `[[test_target]]`. | | |
| 113 | + | | `cargo_audit` | build | `cargo audit` in each `[[test_target]]` carrying a `.cargo/audit.toml`. | | |
| 114 | + | | `cargo_deny` | build | `cargo deny check` in each `[[test_target]]` carrying a `deny.toml`. | | |
| 111 | 115 | | `migration_dry_run` | build | Migrations apply cleanly to a restored production dump. | | |
| 112 | 116 | | `boot_smoke` | build | The staged artifact boots in minimal no-DB mode on the build host. | | |
| 113 | 117 | | `node_health` | post-deploy | Each deployed node's unit is active (and serves 2xx if `health_url` is set). Recorded at the end of a promote as the evidence the next promote checks. | | |
| @@ -154,6 +158,24 @@ | |||
| 154 | 158 | tip. If *no* target exists, the gate fails rather than reporting a pass over | |
| 155 | 159 | zero suites. | |
| 156 | 160 | ||
| 161 | + | ### The lint and supply-chain gates | |
| 162 | + | ||
| 163 | + | `clippy` and `fmt` run over the same `[[test_target]]` list as `cargo_test`, | |
| 164 | + | with the same semantics: per-target log banners, stop at the first red target | |
| 165 | + | with the crate named, one deadline across the whole gate. | |
| 166 | + | ||
| 167 | + | `cargo_audit` and `cargo_deny` are **config-gated**: a target only qualifies | |
| 168 | + | once it carries a `.cargo/audit.toml` or `deny.toml`. Both tools are only | |
| 169 | + | meaningful against a triaged posture, and four crates in this repo fail | |
| 170 | + | `cargo audit` purely for lack of a file recording which transitive advisories | |
| 171 | + | have been reviewed and accepted. Running them everywhere would make the gate | |
| 172 | + | permanently and uninformatively red, which teaches everyone to ignore it. | |
| 173 | + | Dropping the config file into a crate is what opts it in. | |
| 174 | + | ||
| 175 | + | Before these existed, `-D warnings` was enforced in exactly one place | |
| 176 | + | (`server/deploy/run-ci.sh`, which dies with the astra pipeline) and | |
| 177 | + | `cargo fmt --check` nowhere at all. | |
| 178 | + | ||
| 157 | 179 | ### Why `hardening_test` exists | |
| 158 | 180 | ||
| 159 | 181 | `cargo_test` builds with `--features fast-tests`, which relaxes |
| @@ -46,10 +46,23 @@ | |||
| 46 | 46 | # with no features, single-threaded, against production constants. It pays for | |
| 47 | 47 | # a second compile of the server's test binary; that is the cost of the | |
| 48 | 48 | # coverage. | |
| 49 | + | # | |
| 50 | + | # The lint + supply-chain gates. `-D warnings` used to be enforced in exactly | |
| 51 | + | # one place (server/deploy/run-ci.sh, which dies with the astra pipeline) and | |
| 52 | + | # `cargo fmt --check` nowhere at all. fmt runs first: it needs no compilation, | |
| 53 | + | # so a formatting red comes back in seconds instead of after a full build. | |
| 54 | + | # cargo_audit and cargo_deny only run in crates carrying a triaged | |
| 55 | + | # .cargo/audit.toml / deny.toml -- four crates in this repo fail cargo audit | |
| 56 | + | # purely for lack of a reviewed advisory posture, and a permanently red gate | |
| 57 | + | # teaches everyone to ignore it. | |
| 49 | 58 | gates = [ | |
| 59 | + | { kind = "fmt" }, | |
| 50 | 60 | { kind = "code_smoke" }, | |
| 51 | 61 | { kind = "cargo_test" }, | |
| 52 | 62 | { kind = "hardening_test" }, | |
| 63 | + | { kind = "clippy" }, | |
| 64 | + | { kind = "cargo_audit" }, | |
| 65 | + | { kind = "cargo_deny" }, | |
| 53 | 66 | { kind = "migration_dry_run" }, | |
| 54 | 67 | { kind = "boot_smoke" }, | |
| 55 | 68 | ] |
| @@ -80,7 +80,8 @@ | |||
| 80 | 80 | .map(|existing| existing != contents) | |
| 81 | 81 | .unwrap_or(true); | |
| 82 | 82 | if needs_write { | |
| 83 | - | fs::write(path, contents).unwrap_or_else(|e| panic!("failed to write {}: {e}", path.display())); | |
| 83 | + | fs::write(path, contents) | |
| 84 | + | .unwrap_or_else(|e| panic!("failed to write {}: {e}", path.display())); | |
| 84 | 85 | } | |
| 85 | 86 | } | |
| 86 | 87 | ||
| @@ -108,7 +109,11 @@ | |||
| 108 | 109 | // lockfile) so the frontend build needs no manual `npm install` gate before | |
| 109 | 110 | // a deploy. Skipped once node_modules exists; needs network on this run. | |
| 110 | 111 | if !Path::new("frontend/node_modules").is_dir() { | |
| 111 | - | match Command::new("npm").args(["ci"]).current_dir("frontend").status() { | |
| 112 | + | match Command::new("npm") | |
| 113 | + | .args(["ci"]) | |
| 114 | + | .current_dir("frontend") | |
| 115 | + | .status() | |
| 116 | + | { | |
| 112 | 117 | Ok(s) if s.success() => {} | |
| 113 | 118 | Ok(s) => { | |
| 114 | 119 | println!( |
| @@ -1,17 +1,14 @@ | |||
| 1 | 1 | # cargo-deny configuration — supply-chain gate for the MNW server. | |
| 2 | 2 | # | |
| 3 | - | # Wired into `deploy/run-ci.sh` (step 5b) as `cargo deny check advisories bans | |
| 4 | - | # sources`. This complements `cargo audit`: `bans` surfaces duplicate-version | |
| 5 | - | # clusters (the x509/crypto and rustls dual stacks the audits flag), and | |
| 6 | - | # `sources` fails the build if any dependency is pulled from a registry or git | |
| 7 | - | # remote we did not sanction. | |
| 3 | + | # Run by Sando's `cargo_deny` gate as `cargo deny check` (all four checks). | |
| 4 | + | # This complements `cargo audit`: `bans` surfaces duplicate-version clusters | |
| 5 | + | # (the x509/crypto and rustls dual stacks the audits flag), and `sources` fails | |
| 6 | + | # the build if any dependency is pulled from a registry or git remote we did not | |
| 7 | + | # sanction. | |
| 8 | 8 | # | |
| 9 | - | # The `licenses` check is intentionally NOT part of the gate command yet: three | |
| 10 | - | # first-party path crates (docengine, s3-storage) ship without a | |
| 11 | - | # `license` field, which `cargo deny check licenses` rejects. Giving those | |
| 12 | - | # crates an explicit license (MIT for reusable infra, per the licensing | |
| 13 | - | # strategy) is a separate cleanup; the allow-list below is kept current so the | |
| 14 | - | # check can be switched on once that lands. | |
| 9 | + | # `licenses` is now part of the gate. The cleanup it was waiting on has landed: | |
| 10 | + | # docengine and s3-storage carry `license = "MIT"`, per the licensing strategy | |
| 11 | + | # (reusable infra is MIT, products are PolyForm-Noncommercial). | |
| 15 | 12 | ||
| 16 | 13 | [advisories] | |
| 17 | 14 | version = 2 | |
| @@ -20,11 +17,6 @@ | |||
| 20 | 17 | # posture. Directly-fixable advisories are fixed in Cargo.toml, never parked here. | |
| 21 | 18 | ignore = [ | |
| 22 | 19 | "RUSTSEC-2023-0071", # rsa Marvin timing side-channel — only via signature *verification* crates; we never decrypt with rsa. | |
| 23 | - | "RUSTSEC-2026-0098", # rustls-webpki 0.101 — transitive via AWS S3 SDK rustls 0.21; only validates trusted S3/STS endpoints. | |
| 24 | - | "RUSTSEC-2026-0099", # rustls-webpki 0.101 — same AWS SDK TLS stack; clears when the SDK moves to rustls 0.23. | |
| 25 | - | "RUSTSEC-2026-0104", # rustls-webpki 0.101 CRL parse panic — same AWS SDK TLS stack, trusted endpoints only. | |
| 26 | - | "RUSTSEC-2026-0183", # git2 Remote::list UB — never called on untrusted input (repos are server-owned). | |
| 27 | - | "RUSTSEC-2026-0184", # git2 BlameHunk Signature UB — same; awaiting a git2 release. | |
| 28 | 20 | "RUSTSEC-2025-0141", # bincode unmaintained — transitive tooling, no code change available. | |
| 29 | 21 | "RUSTSEC-2020-0095", # difference unmaintained — via a dev/test dep. | |
| 30 | 22 | "RUSTSEC-2024-0436", # paste unmaintained — via proc-macro deps. | |
| @@ -69,6 +61,9 @@ | |||
| 69 | 61 | "CDLA-Permissive-2.0", | |
| 70 | 62 | "BlueOak-1.0.0", | |
| 71 | 63 | "bzip2-1.0.6", | |
| 64 | + | # cranelift, via yara-x. Apache-2.0 with the LLVM linking exception: | |
| 65 | + | # more permissive than bare Apache-2.0, no copyleft obligation. | |
| 66 | + | "Apache-2.0 WITH LLVM-exception", | |
| 72 | 67 | ] | |
| 73 | 68 | confidence-threshold = 0.9 | |
| 74 | 69 | # First-party product crates carry the product license; allow it for exactly |