myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

commit 49d01b6deecb3724b83442ca3c41c89861a75fda
parent 4b6d7b86985b21f5d146fbf265554954ea7147c5
Author: triesap <tyson@radroots.org>
Date:   Fri, 21 Aug 2026 09:09:08 +0000

build: align myc rust policy

- adopt Cargo resolver 3 and the shared deny-lint baseline
- define service-host as the exact default feature profile
- minimize direct runtime features and bind the refreshed lock digest
- route native release acceptance through extbuild with Nix deferred

Diffstat:
MAGENTS.md | 22++++++++++++++--------
MCargo.lock | 1-
MCargo.toml | 25++++++++++++++++++++-----
MREADME | 15++++++++-------
Mradroots.lib.source-lock.v1.toml | 2+-
Mscripts/release-acceptance.sh | 2++
Atests/build_policy.rs | 44++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 89 insertions(+), 22 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -163,13 +163,17 @@ ## 9. Canonical verification -Use the repository-owned Nix lanes as the standalone command authority: +Through RCLD-RSHR-170, run the standalone native command authority through +extbuild. Do not install, repair, invoke, or require Nix, and do not claim Nix, +NixOS-module, or Nix-produced OCI qualification: ```text -nix run .#fmt -nix run .#check -nix run .#test -nix run .#release-acceptance +cargo extbuild doctor +cargo extbuild run -- cargo fmt --all --check +cargo extbuild run -- cargo check --workspace --locked +cargo extbuild run -- cargo test --workspace --all-targets --locked +cargo extbuild run -- cargo clippy --workspace --all-targets --locked -- -D warnings +cargo extbuild run -- ./scripts/release-acceptance.sh ``` The release-acceptance contract requires formatting, locked metadata, locked @@ -177,9 +181,11 @@ all-target checking and testing, warnings-denied all-target Clippy, rustdoc with warnings denied, and diff hygiene. Run any gate not yet covered by the current release script explicitly; do not describe the script as sufficient until it enforces the complete contract. Run additional SQLx freshness, source-lock, -Nix, OCI, systemd, package, SBOM, checksum, notice, and fresh-install gates when -their surfaces change. Use narrower checked-in commands only for iteration, -and never claim a command passed unless it ran successfully. +independently produced OCI, systemd, package, SBOM, checksum, notice, and +fresh-install gates when their surfaces change. Checked-in Nix material remains +deferred source data through RCLD-RSHR-170 and is not a verification gate. Use +narrower checked-in commands only for iteration, and never claim a command +passed unless it ran successfully. ## 10. Commits and irreversible actions diff --git a/Cargo.lock b/Cargo.lock @@ -1369,7 +1369,6 @@ dependencies = [ "clap", "futures-executor", "futures-util", - "getrandom 0.2.17", "hex", "keyring", "nostr", diff --git a/Cargo.toml b/Cargo.toml @@ -8,19 +8,34 @@ license = "AGPL-3.0-or-later" description = "Radroots NIP-46 remote signer for delegated Nostr accounts" [workspace] -resolver = "2" +resolver = "3" -[lints.rust] +[workspace.lints.rust] +unsafe_code = "deny" unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } +[workspace.lints.rustdoc] +broken_intra_doc_links = "deny" + +[workspace.lints.clippy] +dbg_macro = "deny" +todo = "deny" +unimplemented = "deny" + +[lints] +workspace = true + +[features] +default = ["service-host"] +service-host = [] + [dependencies] axum = { version = "0.8", default-features = false, features = ["http1", "json", "tokio"] } chacha20poly1305 = "0.10" clap = { version = "4.5", features = ["derive"] } -getrandom = "0.2" futures-executor = "0.3" hex = "0.4" -keyring = { version = "3.6", features = ["apple-native", "windows-native", "sync-secret-service"] } +keyring = { version = "3.6", default-features = false, features = ["apple-native", "windows-native", "sync-secret-service"] } nostr = { version = "0.44.2", features = ["nip04", "nip44", "nip46", "nip49"] } nostr-sdk = { version = "0.44.1" } radroots_identity = { git = "https://github.com/radrootslabs/lib", rev = "09065a610d95e57acdc895a14c07580fa099e7c3", version = "=0.1.0-alpha" } @@ -36,7 +51,7 @@ sqlx = { version = "0.9.0", default-features = false, features = ["derive", "sql rand = "0.9" thiserror = "2.0" tempfile = "3.17" -tokio = { version = "1.48", features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync", "time"] } +tokio = { version = "1.48", default-features = false, features = ["io-util", "macros", "net", "process", "rt-multi-thread", "sync", "time"] } tracing = "0.1" tracing-appender = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/README b/README @@ -36,17 +36,18 @@ out helpers, and releases Myc's multi-thread Tokio worker while waiting. Helper-provided stderr and protocol error text are never copied into operator errors. -Use the repository-owned Nix lanes for validation: +The default Cargo feature profile is `service-host`. Validate the standalone +crate through extbuild: ```text -nix run .#fmt -nix run .#check -nix run .#test -nix run .#release-acceptance +cargo extbuild doctor +cargo extbuild run -- ./scripts/release-acceptance.sh ``` -Use `nix develop` to enter the repository's development shell before running -narrower ad hoc Cargo commands from this repository root. +Through RCLD-RSHR-170, Nix evaluation, builds, packages, NixOS modules, and +Nix-produced OCI artifacts are deferred and unclaimed. Do not install, repair, +invoke, or require Nix for these checkpoints. Run narrower ad hoc Cargo +commands through `cargo extbuild run --` from this repository root. ## Copyright diff --git a/radroots.lib.source-lock.v1.toml b/radroots.lib.source-lock.v1.toml @@ -6,4 +6,4 @@ workspace_catalog_sha256 = "8c27cebf6825f9ed74e122513c661f6dd31837dddb39d0988014 version = "0.1.0-alpha" source_archive_sha256 = "68badd1fb02d9396682d368e62dfe79969d8da48529760789c823fb4ab54aea3" lockfile = "Cargo.lock" -lockfile_sha256 = "d46a79ad905cbc8e67752eb214d125702c617328e109450e442f13740d2d8e96" +lockfile_sha256 = "3a26058ad786e73e88b04a505d56845c5cdc6bf6d3d8216f03d1b1593dba2ea7" diff --git a/scripts/release-acceptance.sh b/scripts/release-acceptance.sh @@ -6,6 +6,8 @@ cd "$repo_root" cargo fmt --all --check cargo metadata --locked --format-version 1 --no-deps >/dev/null +cargo check --locked --all-targets --no-default-features +cargo check --locked --all-targets --no-default-features --features service-host cargo check --locked --all-targets cargo clippy --locked --all-targets -- -D warnings cargo test --locked diff --git a/tests/build_policy.rs b/tests/build_policy.rs @@ -0,0 +1,44 @@ +#![forbid(unsafe_code)] + +use sha2::{Digest, Sha256}; + +const MANIFEST: &str = include_str!("../Cargo.toml"); +const RELEASE_ACCEPTANCE: &str = include_str!("../scripts/release-acceptance.sh"); +const SOURCE_LOCK: &str = include_str!("../radroots.lib.source-lock.v1.toml"); + +#[test] +fn manifest_freezes_the_final_rust_policy() { + assert!(MANIFEST.contains("[workspace]\nresolver = \"3\"")); + assert!(MANIFEST.contains("[workspace.lints.rust]\nunsafe_code = \"deny\"")); + assert!(MANIFEST.contains("[workspace.lints.rustdoc]\nbroken_intra_doc_links = \"deny\"")); + assert!(MANIFEST.contains( + "[workspace.lints.clippy]\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"" + )); + assert!(MANIFEST.contains("[lints]\nworkspace = true")); +} + +#[test] +fn service_host_is_the_exact_default_feature_profile() { + assert!(MANIFEST.contains("[features]\ndefault = [\"service-host\"]\nservice-host = []")); + assert!(!MANIFEST.contains("getrandom = \"0.2\"")); + assert!(MANIFEST.contains( + "tokio = { version = \"1.48\", default-features = false, features = [\"io-util\", \"macros\", \"net\", \"process\", \"rt-multi-thread\", \"sync\", \"time\"] }" + )); +} + +#[test] +fn release_acceptance_checks_both_feature_profiles() { + assert!( + RELEASE_ACCEPTANCE.contains("cargo check --locked --all-targets --no-default-features\n") + ); + assert!(RELEASE_ACCEPTANCE.contains( + "cargo check --locked --all-targets --no-default-features --features service-host\n" + )); + assert!(!RELEASE_ACCEPTANCE.contains("nix ")); +} + +#[test] +fn source_lock_binds_the_current_cargo_lock() { + let digest = hex::encode(Sha256::digest(include_bytes!("../Cargo.lock"))); + assert!(SOURCE_LOCK.contains(&format!("lockfile_sha256 = \"{digest}\""))); +}