Files
clawmates/tools/bundler/src/main.rs
T
Omar SobhandClaude Fable 5 add4f79fed Rebrand: TeamClaw -> Clawmates (clawmates.work)
Full-depth rename per the approved plan; the 'claw' product vocabulary
(claws, /claws routes, clawId, Claw Chat) stays — it is now the brand.

- Display brand: Clawmates (manifest, titles, hero, login/rail logo
  'clawmates'); default host app.clawmates.work; registry
  ghcr.io/clawmates
- Crates tc-* -> cm-* (16 crates + all imports); binaries
  clawmates-server/broker/bundler; images clawmates/*; env prefix
  CLAWMATES_* (+ CM_TEST_DATABASE_URL / CM_LIVE_LLM); config
  clawmates.toml; helm chart deploy/helm/clawmates with clawmates-*
  resources; db names clawmates*; sockets /run/clawmates; cookie
  cm_session; kind cluster clawmates-test; seccomp node profile
  clawmates-agent-profile.json
- All 9 Playwright brand assertions updated in lockstep; historical
  spec document left untouched as the only remaining 'TeamClaw'
- Local env migrated: dev pg clawmates-dev-pg/clawmates_dev, shared
  test server clawmates-test-pg, kind cluster recreated with image +
  profile, compose images rebuilt under clawmates/*

Verified end to end: 161 Rust + 68 frontend tests, 29 Playwright
journeys, 4 live kind tests, helm/install/LOC/placeholder gates, and
the clean-room install rehearsal serving the clawmates login page from
a signed bundle of the rebuilt images.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-10 12:31:25 -05:00

69 lines
2.5 KiB
Rust

//! clawmates-bundler: assemble and verify air-gapped install bundles.
//!
//! Usage:
//! clawmates-bundler keygen <private.key> <public.key>
//! clawmates-bundler assemble <out-dir> <version> <private.key> \
//! <src=dest> [<src=dest> ...]
//! clawmates-bundler verify <bundle-dir> <public.key>
use std::path::{Path, PathBuf};
use std::process::ExitCode;
fn main() -> ExitCode {
match run() {
Ok(message) => {
println!("{message}");
ExitCode::SUCCESS
}
Err(message) => {
eprintln!("clawmates-bundler: {message}");
ExitCode::FAILURE
}
}
}
fn run() -> Result<String, String> {
let args: Vec<String> = std::env::args().skip(1).collect();
match args.first().map(String::as_str) {
Some("keygen") if args.len() == 3 => {
clawmates_bundler::generate_keypair(Path::new(&args[1]), Path::new(&args[2]))
.map_err(|e| e.to_string())?;
Ok(format!("wrote {} and {}", args[1], args[2]))
}
Some("assemble") if args.len() >= 5 => {
let artifacts: Vec<(PathBuf, String)> = args[4..]
.iter()
.map(|pair| {
pair.split_once('=')
.map(|(src, dst)| (PathBuf::from(src), dst.to_owned()))
.ok_or_else(|| format!("expected src=dest, got {pair}"))
})
.collect::<Result<_, _>>()?;
clawmates_bundler::assemble(
Path::new(&args[1]),
&args[2],
&artifacts,
Path::new(&args[3]),
)
.map_err(|e| e.to_string())?;
Ok(format!(
"assembled {} artifacts into {}",
artifacts.len(),
args[1]
))
}
Some("pubkey") if args.len() == 3 => {
clawmates_bundler::derive_public_key(Path::new(&args[1]), Path::new(&args[2]))
.map_err(|e| e.to_string())?;
Ok(format!("wrote {}", args[2]))
}
Some("verify") if args.len() == 3 => {
let verified =
clawmates_bundler::verify(Path::new(&args[1]), Path::new(&args[2]))
.map_err(|e| e.to_string())?;
Ok(format!("bundle OK: {verified} artifacts verified offline"))
}
_ => Err("usage: keygen <priv> <pub> | pubkey <priv> <pub> | assemble <out> <version> <priv> <src=dest>... | verify <bundle> <pub>".into()),
}
}