Move high-level docs into docs/, matching doubleo7's convention
SPEC.md and ARCHITECTURE.md were sitting at the repo root alongside Cargo.toml/Makefile.toml/packages.d — moved both into docs/ (doubleo7 already does this for its own supplementary docs, so this matches an existing convention in the fleet rather than inventing a new one). Updated every doc-comment cross-reference across src/*.rs and Makefile.toml (23 references) to the new docs/SPEC.md / docs/ ARCHITECTURE.md paths. The two files' own cross-references to each other didn't need changing — they're still same-directory relative references. Also updated the project reference memory pointing at ARCHITECTURE.md's location, so it doesn't go stale pointing at a path that no longer exists. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
f55188e36f
commit
3e87282b21
13 changed files with 23 additions and 23 deletions
|
|
@ -37,7 +37,7 @@ args = ["test"]
|
||||||
# orchestration too (hence its own low number) — its one pure decision
|
# orchestration too (hence its own low number) — its one pure decision
|
||||||
# function (decide_tier_action) is unit tested and should stay visible in
|
# function (decide_tier_action) is unit tested and should stay visible in
|
||||||
# this report; excluding the whole file would hide that signal along with
|
# this report; excluding the whole file would hide that signal along with
|
||||||
# the untested parts. See ARCHITECTURE.md > "separate pure decision logic
|
# the untested parts. See docs/ARCHITECTURE.md > "separate pure decision logic
|
||||||
# from I/O."
|
# from I/O."
|
||||||
[tasks.coverage-report]
|
[tasks.coverage-report]
|
||||||
command = "cargo"
|
command = "cargo"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ pub struct BuildResult {
|
||||||
/// artifact, then runs `makepkg` in `build_dir`.
|
/// artifact, then runs `makepkg` in `build_dir`.
|
||||||
///
|
///
|
||||||
/// Deliberately one fixed "prebuilt binary" shape, not a templating engine
|
/// Deliberately one fixed "prebuilt binary" shape, not a templating engine
|
||||||
/// — see SPEC.md > Scaling > Template reuse. Covers the two shapes the two
|
/// — see docs/SPEC.md > Scaling > Template reuse. Covers the two shapes the two
|
||||||
/// currently-tracked packages actually need: a bare-binary download
|
/// currently-tracked packages actually need: a bare-binary download
|
||||||
/// (scaleway-cli) and a tarball containing a same-named directory (uv).
|
/// (scaleway-cli) and a tarball containing a same-named directory (uv).
|
||||||
/// Extend when a third real shape shows up rather than guessing at
|
/// Extend when a third real shape shows up rather than guessing at
|
||||||
|
|
@ -71,7 +71,7 @@ pub fn build(req: &BuildRequest, build_dir: &Path) -> Result<BuildResult> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the PKGBUILD text for `req`, validating every upstream-controlled
|
/// Builds the PKGBUILD text for `req`, validating every upstream-controlled
|
||||||
/// string first (see SPEC.md > Architecture > Builder: "strict validation
|
/// string first (see docs/SPEC.md > Architecture > Builder: "strict validation
|
||||||
/// on any upstream-controlled string ... never unescaped interpolation").
|
/// on any upstream-controlled string ... never unescaped interpolation").
|
||||||
/// Pure and side-effect-free so it's testable without invoking `makepkg`.
|
/// Pure and side-effect-free so it's testable without invoking `makepkg`.
|
||||||
fn generate_pkgbuild(req: &BuildRequest) -> Result<String> {
|
fn generate_pkgbuild(req: &BuildRequest) -> Result<String> {
|
||||||
|
|
@ -155,7 +155,7 @@ fn archive_stem(asset_name: &str) -> Option<&str> {
|
||||||
/// `asset_name` (via `install_source`) and `binary_name` end up embedded
|
/// `asset_name` (via `install_source`) and `binary_name` end up embedded
|
||||||
/// so `${srcdir}`/`${pkgdir}` can expand. A single check covering both
|
/// so `${srcdir}`/`${pkgdir}` can expand. A single check covering both
|
||||||
/// contexts is safer than trying to remember which fields land in which
|
/// contexts is safer than trying to remember which fields land in which
|
||||||
/// quoting style. See SPEC.md > Architecture > Builder ("never unescaped
|
/// quoting style. See docs/SPEC.md > Architecture > Builder ("never unescaped
|
||||||
/// interpolation").
|
/// interpolation").
|
||||||
fn validate_shell_safe(field: &str, value: &str) -> Result<()> {
|
fn validate_shell_safe(field: &str, value: &str) -> Result<()> {
|
||||||
if value.contains(['\'', '\n', '$', '`', '\\']) {
|
if value.contains(['\'', '\n', '$', '`', '\\']) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ struct PackageFile {
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
pub repo: String,
|
pub repo: String,
|
||||||
/// Exact GitHub release asset name (still not a glob — see
|
/// Exact GitHub release asset name (still not a glob — see
|
||||||
/// SPEC.md > Architecture > Fetcher), optionally containing a
|
/// docs/SPEC.md > Architecture > Fetcher), optionally containing a
|
||||||
/// `{version}` placeholder for projects whose asset names embed the
|
/// `{version}` placeholder for projects whose asset names embed the
|
||||||
/// version (e.g. `scaleway-cli_{version}_linux_amd64`). Substituted via
|
/// version (e.g. `scaleway-cli_{version}_linux_amd64`). Substituted via
|
||||||
/// `checker::version_from_tag` before matching.
|
/// `checker::version_from_tag` before matching.
|
||||||
|
|
@ -29,7 +29,7 @@ pub struct Package {
|
||||||
/// the repo name). Defaults to the package name when omitted.
|
/// the repo name). Defaults to the package name when omitted.
|
||||||
pub binary_name: Option<String>,
|
pub binary_name: Option<String>,
|
||||||
/// Post-build correctness check (not a security control — see
|
/// Post-build correctness check (not a security control — see
|
||||||
/// SPEC.md > Verification trust tiers). Runs `command` against the
|
/// docs/SPEC.md > Verification trust tiers). Runs `command` against the
|
||||||
/// freshly built binary and confirms `version_regex`'s capture group
|
/// freshly built binary and confirms `version_regex`'s capture group
|
||||||
/// matches the version pkgwatch believes it just built.
|
/// matches the version pkgwatch believes it just built.
|
||||||
pub sanity_check: Option<SanityCheck>,
|
pub sanity_check: Option<SanityCheck>,
|
||||||
|
|
@ -53,7 +53,7 @@ pub struct SanityCheck {
|
||||||
#[serde(tag = "method", rename_all = "kebab-case")]
|
#[serde(tag = "method", rename_all = "kebab-case")]
|
||||||
pub enum Verification {
|
pub enum Verification {
|
||||||
/// Tier 4: proves transport integrity only, not authorship. See
|
/// Tier 4: proves transport integrity only, not authorship. See
|
||||||
/// SPEC.md > Verification trust tiers. `checksum_asset_pattern` may
|
/// docs/SPEC.md > Verification trust tiers. `checksum_asset_pattern` may
|
||||||
/// also contain a `{version}` placeholder, same as `asset_pattern`.
|
/// also contain a `{version}` placeholder, same as `asset_pattern`.
|
||||||
SameOriginSha256 { checksum_asset_pattern: String },
|
SameOriginSha256 { checksum_asset_pattern: String },
|
||||||
/// Tier 2: GitHub build-provenance attestation, verified via `gh
|
/// Tier 2: GitHub build-provenance attestation, verified via `gh
|
||||||
|
|
@ -71,7 +71,7 @@ impl Verification {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads every `*.toml` file in `dir` (the `packages.d/` layout from
|
/// Loads every `*.toml` file in `dir` (the `packages.d/` layout from
|
||||||
/// SPEC.md > Scaling to many packages), keyed by package name.
|
/// docs/SPEC.md > Scaling to many packages), keyed by package name.
|
||||||
pub fn load_packages_dir(dir: &Path) -> Result<Vec<(String, Package)>> {
|
pub fn load_packages_dir(dir: &Path) -> Result<Vec<(String, Package)>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for entry in std::fs::read_dir(dir).with_context(|| format!("reading {}", dir.display()))? {
|
for entry in std::fs::read_dir(dir).with_context(|| format!("reading {}", dir.display()))? {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! Two functions, shared by two real callers (`verifier`, `builder`) —
|
//! Two functions, shared by two real callers (`verifier`, `builder`) —
|
||||||
//! not a general-purpose utils dump. See ARCHITECTURE.md > "organize by
|
//! not a general-purpose utils dump. See docs/ARCHITECTURE.md > "organize by
|
||||||
//! pipeline stage, not by layer" for why that distinction matters.
|
//! pipeline stage, not by layer" for why that distinction matters.
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Entry point: parses `argv` and dispatches to `pipeline`. Nothing here
|
//! Entry point: parses `argv` and dispatches to `pipeline`. Nothing here
|
||||||
//! makes a network/subprocess call or contains a decision worth a test —
|
//! makes a network/subprocess call or contains a decision worth a test —
|
||||||
//! see ARCHITECTURE.md > "main is a dispatcher, not the program."
|
//! see docs/ARCHITECTURE.md > "main is a dispatcher, not the program."
|
||||||
|
|
||||||
mod builder;
|
mod builder;
|
||||||
mod checker;
|
mod checker;
|
||||||
|
|
@ -20,8 +20,8 @@ use anyhow::{Result, bail};
|
||||||
|
|
||||||
/// check -> fetch -> verify -> build -> sanity-check -> publish, for
|
/// check -> fetch -> verify -> build -> sanity-check -> publish, for
|
||||||
/// whatever is in packages.d/. Tier 1-3 passes auto-publish; tier 4-6
|
/// whatever is in packages.d/. Tier 1-3 passes auto-publish; tier 4-6
|
||||||
/// passes queue for `pkgwatch review`. See SPEC.md > Architecture for what
|
/// passes queue for `pkgwatch review`. See docs/SPEC.md > Architecture for what
|
||||||
/// each stage does, and ARCHITECTURE.md for how the code implementing it
|
/// each stage does, and docs/ARCHITECTURE.md for how the code implementing it
|
||||||
/// is organized.
|
/// is organized.
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Orchestrates one run of check -> fetch -> verify -> build ->
|
//! Orchestrates one run of check -> fetch -> verify -> build ->
|
||||||
//! sanity-check -> publish across every configured package, plus the
|
//! sanity-check -> publish across every configured package, plus the
|
||||||
//! `review` subcommand for tier 4-6 approvals. The only module that calls
|
//! `review` subcommand for tier 4-6 approvals. The only module that calls
|
||||||
//! more than one other pipeline-stage module — see ARCHITECTURE.md > "main
|
//! more than one other pipeline-stage module — see docs/ARCHITECTURE.md > "main
|
||||||
//! is a dispatcher, not the program" for why this lives here and not in
|
//! is a dispatcher, not the program" for why this lives here and not in
|
||||||
//! `main.rs`.
|
//! `main.rs`.
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ pub fn run_check() -> Result<()> {
|
||||||
|
|
||||||
/// What to do about a package after verification, derived purely from the
|
/// What to do about a package after verification, derived purely from the
|
||||||
/// verification outcome and whether this exact version is already queued
|
/// verification outcome and whether this exact version is already queued
|
||||||
/// for review — no I/O. See ARCHITECTURE.md > "separate pure decision
|
/// for review — no I/O. See docs/ARCHITECTURE.md > "separate pure decision
|
||||||
/// logic from I/O."
|
/// logic from I/O."
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum TierAction {
|
enum TierAction {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
/// Pacman's system-wide config — hardcoded like the rest of this tool's
|
/// Pacman's system-wide config — hardcoded like the rest of this tool's
|
||||||
/// Arch/Manjaro-specific assumptions (see SPEC.md > Scope).
|
/// Arch/Manjaro-specific assumptions (see docs/SPEC.md > Scope).
|
||||||
const PACMAN_CONF: &str = "/etc/pacman.conf";
|
const PACMAN_CONF: &str = "/etc/pacman.conf";
|
||||||
|
|
||||||
/// Copies the built package into `repo_dir` and runs `repo-add` against
|
/// Copies the built package into `repo_dir` and runs `repo-add` against
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Post-build correctness check: runs the freshly built binary and
|
//! Post-build correctness check: runs the freshly built binary and
|
||||||
//! confirms it reports the version pkgwatch believes it just built. Not a
|
//! confirms it reports the version pkgwatch believes it just built. Not a
|
||||||
//! security control — see SPEC.md > Verification trust tiers.
|
//! security control — see docs/SPEC.md > Verification trust tiers.
|
||||||
|
|
||||||
use crate::config::SanityCheck;
|
use crate::config::SanityCheck;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
|
@ -14,7 +14,7 @@ use std::process::Command;
|
||||||
/// whatever's already on the system. Confirms `check.version_regex`'s
|
/// whatever's already on the system. Confirms `check.version_regex`'s
|
||||||
/// capture group matches `expected_version`.
|
/// capture group matches `expected_version`.
|
||||||
///
|
///
|
||||||
/// Correctness check only, not a security control — see SPEC.md >
|
/// Correctness check only, not a security control — see docs/SPEC.md >
|
||||||
/// Verification trust tiers. Catches checker bugs and mangled/wrong-asset
|
/// Verification trust tiers. Catches checker bugs and mangled/wrong-asset
|
||||||
/// downloads, not malicious releases.
|
/// downloads, not malicious releases.
|
||||||
pub fn run(check: &SanityCheck, pkg_bin_dir: &Path, expected_version: &str) -> Result<()> {
|
pub fn run(check: &SanityCheck, pkg_bin_dir: &Path, expected_version: &str) -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use std::path::Path;
|
||||||
/// Last-known-published version per package, so re-runs don't re-flag a
|
/// Last-known-published version per package, so re-runs don't re-flag a
|
||||||
/// version already handled. Deliberately just one file per package for
|
/// version already handled. Deliberately just one file per package for
|
||||||
/// now — this is where a real review-queue persistence layer plugs in
|
/// now — this is where a real review-queue persistence layer plugs in
|
||||||
/// later (see SPEC.md > Architecture > Reviewer queue).
|
/// later (see docs/SPEC.md > Architecture > Reviewer queue).
|
||||||
pub fn load_last_version(state_dir: &Path, name: &str) -> Option<String> {
|
pub fn load_last_version(state_dir: &Path, name: &str) -> Option<String> {
|
||||||
std::fs::read_to_string(state_dir.join(format!("{name}.version")))
|
std::fs::read_to_string(state_dir.join(format!("{name}.version")))
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -22,7 +22,7 @@ pub fn save_last_version(state_dir: &Path, name: &str, version: &str) -> Result<
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tag currently awaiting human review for a tier 4-6 package (see
|
/// Tag currently awaiting human review for a tier 4-6 package (see
|
||||||
/// SPEC.md > Architecture > Reviewer queue), if any. Separate from
|
/// docs/SPEC.md > Architecture > Reviewer queue), if any. Separate from
|
||||||
/// `load_last_version`/`save_last_version`: approving a review doesn't
|
/// `load_last_version`/`save_last_version`: approving a review doesn't
|
||||||
/// mean future versions auto-publish, so the two must be tracked
|
/// mean future versions auto-publish, so the two must be tracked
|
||||||
/// independently.
|
/// independently.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Test-only fixture helpers shared across modules' `#[cfg(test)]` code
|
//! Test-only fixture helpers shared across modules' `#[cfg(test)]` code
|
||||||
//! (`publisher`, `sanity`) — not production code, and not built outside
|
//! (`publisher`, `sanity`) — not production code, and not built outside
|
||||||
//! `cargo test`. See ARCHITECTURE.md > "organize by pipeline stage, not
|
//! `cargo test`. See docs/ARCHITECTURE.md > "organize by pipeline stage, not
|
||||||
//! by layer": this exists to remove one specific piece of duplication
|
//! by layer": this exists to remove one specific piece of duplication
|
||||||
//! (two near-identical copies of "write an executable shell script"), not
|
//! (two near-identical copies of "write an executable shell script"), not
|
||||||
//! as a general test-utils dump.
|
//! as a general test-utils dump.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Runs the trust-tier-specific check declared for a package against a
|
//! Runs the trust-tier-specific check declared for a package against a
|
||||||
//! downloaded artifact, and reports a pass/fail plus the tier it implies.
|
//! downloaded artifact, and reports a pass/fail plus the tier it implies.
|
||||||
//! The only module that knows what each `Verification::method` actually
|
//! The only module that knows what each `Verification::method` actually
|
||||||
//! proves — see SPEC.md > Verification trust tiers.
|
//! proves — see docs/SPEC.md > Verification trust tiers.
|
||||||
|
|
||||||
use crate::checker::version_from_tag;
|
use crate::checker::version_from_tag;
|
||||||
use crate::config::Verification;
|
use crate::config::Verification;
|
||||||
|
|
@ -19,7 +19,7 @@ pub struct VerificationResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the verification method declared for a package against a
|
/// Runs the verification method declared for a package against a
|
||||||
/// downloaded artifact. See SPEC.md > Verification trust tiers for what
|
/// downloaded artifact. See docs/SPEC.md > Verification trust tiers for what
|
||||||
/// each tier does and does not prove.
|
/// each tier does and does not prove.
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
client: &reqwest::blocking::Client,
|
client: &reqwest::blocking::Client,
|
||||||
|
|
@ -59,7 +59,7 @@ pub fn verify(
|
||||||
passed,
|
passed,
|
||||||
justification: if passed {
|
justification: if passed {
|
||||||
"same-origin sha256 matched — proves transport integrity only, \
|
"same-origin sha256 matched — proves transport integrity only, \
|
||||||
not authorship (see tier 4 in SPEC.md)"
|
not authorship (see tier 4 in docs/SPEC.md)"
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
format!("sha256 mismatch: expected {expected}, got {actual}")
|
format!("sha256 mismatch: expected {expected}, got {actual}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue