commit 9aa7d727eff8cc342fe698f53903e1339772ebf0
parent 267e76547d08db145df6133dc2e8ffbf25b48e50
Author: triesap <tyson@radroots.org>
Date: Sat, 1 Aug 2026 11:57:54 +0000
secrets: migrate workspace consumers
- activate the final SDK secrets dependency edge
- confine predecessor imports to private storage
- enforce the SDK source migration boundary
- record ordered storage and removal gates
Diffstat:
8 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/.cargo/config.toml b/.cargo/config.toml
@@ -21,6 +21,7 @@ radroots_protocol = { path = "../lib/crates/protocol" }
radroots_protocol_contract_v1 = { path = "../lib/crates/protocol_contract_v1" }
radroots_protected_store = { path = "../lib/crates/protected_store" }
radroots_secret_vault = { path = "../lib/crates/secret_vault" }
+radroots_secrets = { path = "../lib/crates/secrets" }
radroots_signing = { path = "../lib/crates/signing" }
radroots_transport = { path = "../lib/crates/transport" }
radroots_transport_nostr = { path = "../lib/crates/transport_nostr" }
diff --git a/Cargo.lock b/Cargo.lock
@@ -2362,6 +2362,7 @@ dependencies = [
"radroots_replica_sync",
"radroots_runtime_paths",
"radroots_secret_vault",
+ "radroots_secrets",
"radroots_signing",
"radroots_sql_core",
"radroots_trade",
@@ -2418,6 +2419,14 @@ name = "radroots_secret_vault"
version = "0.1.0-alpha"
[[package]]
+name = "radroots_secrets"
+version = "0.1.0-alpha"
+dependencies = [
+ "chacha20poly1305",
+ "zeroize",
+]
+
+[[package]]
name = "radroots_signing"
version = "0.1.0-alpha"
dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
@@ -67,6 +67,7 @@ radroots_protocol_contract_v1 = { version = "=0.1.0-alpha", default-features = f
radroots_protected_store = { version = "=0.1.0-alpha", default-features = false }
radroots_runtime_contract_v1 = { path = "crates/runtime_contract_v1", version = "=0.1.0-alpha", default-features = false }
radroots_secret_vault = { version = "=0.1.0-alpha", default-features = false }
+radroots_secrets = { package = "radroots_secrets", version = "=0.1.0-alpha", default-features = false }
radroots_signing = { package = "radroots_signing", version = "=0.1.0-alpha", default-features = false }
radroots_transport = { package = "radroots_transport", version = "=0.1.0-alpha", default-features = false }
radroots_transport_nostr = { package = "radroots_transport_nostr", version = "=0.1.0-alpha", default-features = false }
diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml
@@ -114,7 +114,12 @@ runtime = [
"radroots_transport_nostr/storage",
"radroots_transport_nostr/runtime-tokio",
]
-local-signer = ["runtime", "signing", "radroots_nostr/signing"]
+local-signer = [
+ "runtime",
+ "signing",
+ "dep:radroots_secrets",
+ "radroots_nostr/signing",
+]
transport-nostr-runtime = [
"runtime",
"dep:radroots_nostr",
@@ -157,6 +162,7 @@ radroots_transport_nostr = { workspace = true, optional = true, default-features
radroots_transport_reticulum = { workspace = true, optional = true, default-features = false }
radroots_runtime_paths = { workspace = true, optional = true, default-features = false }
radroots_secret_vault = { workspace = true, optional = true, default-features = false }
+radroots_secrets = { workspace = true, optional = true, default-features = false }
radroots_signing = { workspace = true, default-features = false }
radroots_trade = { workspace = true, default-features = false }
radroots_identity = { workspace = true, default-features = false }
diff --git a/crates/sdk/src/private_store.rs b/crates/sdk/src/private_store.rs
@@ -1,5 +1,9 @@
#![cfg(feature = "runtime")]
+// RCRV1-DEV-008: this module is the sole SDK quarantine for predecessor secret
+// storage until Step 179 transfers the private store into radroots_storage_sqlite.
+// New SDK secret integrations must use radroots_secrets.
+
use crate::RadrootsSdkError;
use radroots_event::envelope::kind::KIND_FARM;
use radroots_event::id::{AddressableCoordinate, AddressableCoordinateParts};
diff --git a/crates/sdk/tests/secrets_migration_boundary.rs b/crates/sdk/tests/secrets_migration_boundary.rs
@@ -0,0 +1,62 @@
+use std::fs;
+use std::path::Path;
+
+const ROOT_MANIFEST: &str = include_str!("../../../Cargo.toml");
+const PACKAGE_MANIFEST: &str = include_str!("../Cargo.toml");
+const CARGO_CONFIG: &str = include_str!("../../../.cargo/config.toml");
+const PRIVATE_STORE: &str = include_str!("../src/private_store.rs");
+const DEVIATIONS: &str = include_str!("../../../docs/implementation/deviations.toml");
+
+#[test]
+fn final_secret_dependency_is_activated_at_the_sdk_boundary() {
+ assert!(ROOT_MANIFEST.contains(
+ "radroots_secrets = { package = \"radroots_secrets\", version = \"=0.1.0-alpha\", default-features = false }"
+ ));
+ assert!(PACKAGE_MANIFEST.contains(
+ "radroots_secrets = { workspace = true, optional = true, default-features = false }"
+ ));
+ assert!(PACKAGE_MANIFEST.contains("\"dep:radroots_secrets\""));
+ assert!(CARGO_CONFIG.contains("radroots_secrets = { path = \"../lib/crates/secrets\" }"));
+}
+
+#[test]
+fn predecessor_secret_imports_are_confined_to_the_private_store_quarantine() {
+ let source_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
+ let mut legacy_sources = Vec::new();
+ collect_rust_sources(&source_root, &mut legacy_sources);
+ legacy_sources.retain(|path| {
+ let source = fs::read_to_string(path).expect("read SDK source");
+ source.contains("radroots_protected_store") || source.contains("radroots_secret_vault")
+ });
+
+ assert_eq!(legacy_sources, vec![source_root.join("private_store.rs")]);
+ assert!(PRIVATE_STORE.contains("RCRV1-DEV-008"));
+ assert!(PRIVATE_STORE.contains("Step 179 transfers the private store"));
+}
+
+#[test]
+fn quarantine_has_exact_future_removal_gates() {
+ for required in [
+ "id = \"RCRV1-DEV-008\"",
+ "affected_steps = [\"153\", \"155\", \"171\", \"179\", \"226\", \"288\", \"293\", \"313\"]",
+ "Step 179 transfers canonical private storage",
+ "Step 313 removes every remaining compatibility package and legacy name",
+ ] {
+ assert!(
+ DEVIATIONS.contains(required),
+ "secret consumer quarantine is missing `{required}`"
+ );
+ }
+}
+
+fn collect_rust_sources(root: &Path, sources: &mut Vec<std::path::PathBuf>) {
+ for entry in fs::read_dir(root).expect("read SDK source directory") {
+ let path = entry.expect("SDK source entry").path();
+ if path.is_dir() {
+ collect_rust_sources(&path, sources);
+ } else if path.extension().is_some_and(|extension| extension == "rs") {
+ sources.push(path);
+ }
+ }
+ sources.sort();
+}
diff --git a/docs/implementation/DEVIATIONS.md b/docs/implementation/DEVIATIONS.md
@@ -14,6 +14,7 @@ silently change `radroots.crates.release.v1`.
| `RCRV1-DEV-005` | 013, 019-026, 226, 247, 249-268, 305 | Pin every Rust crate and internal Radroots dependency in `radrootslabs/sdk` to exactly `0.1.0-alpha` until further explicit authority. |
| `RCRV1-DEV-006` | 073, 261-268 | Retire public event/trade codegen edges now and authenticate the predecessor TypeScript snapshots until their scheduled protocol/codec replacement. |
| `RCRV1-DEV-007` | 122, 170, 235, 305 | Remove the predecessor monolithic transport SPI now; quarantine publish-frozen runtime, SDK, CLI, and daemon consumer shims until their explicit removal gates. |
+| `RCRV1-DEV-008` | 153, 155, 171, 179, 226, 288, 293, 313 | Activate final secrets dependency edges now; quarantine legacy vault/store consumers until their ordered storage, SDK, downstream, and final-removal gates. |
## Record template
diff --git a/docs/implementation/deviations.toml b/docs/implementation/deviations.toml
@@ -2,6 +2,31 @@ schema_version = 1
architecture_id = "radroots.crates.release.v1"
[[deviation]]
+id = "RCRV1-DEV-008"
+date = "2026-08-01"
+status = "active"
+approval = "All code-review recommendations and the full multi-RCLD implementation sequence were explicitly approved by the user."
+affected_steps = ["153", "155", "171", "179", "226", "288", "293", "313"]
+spec_anchors = [
+ "docs/specs/radroots_crates_release_v1.md#12-radroots_secrets",
+ "docs/specs/radroots_crates_release_v1.md#20-current-to-target-migration-map",
+]
+source_evidence = [
+ "Step 179, not Step 153, owns transfer of the current SDK private database and its encrypted records into canonical SQLite storage.",
+ "The SDK can activate the final radroots_secrets dependency now while its private_store module remains the sole predecessor secret-store quarantine.",
+ "Mixed publish-frozen runtime, Myc, and other external hosts still require predecessor vault/store behavior until their ordered migration steps.",
+]
+replacement_action = "Activate the final optional radroots_secrets edge in Step 153; confine predecessor vault/store imports to private_store.rs; Step 179 transfers canonical private storage, Steps 226/288/293 migrate the remaining SDK and downstream consumers, and Step 313 removes every remaining compatibility package and legacy name."
+verification = [
+ "SDK source-boundary tests confine predecessor imports to private_store.rs and require the final optional radroots_secrets dependency edge.",
+ "The local-signer feature activates radroots_secrets without changing the current runtime storage implementation before Step 179.",
+ "Step 155 release-policy validation keeps every quarantine package non-publishable until its exact removal gate.",
+]
+unresolved_risk = "Publish-frozen compatibility code remains reachable inside the SDK private-store path until Steps 179, 226, 288, 293, and 313; no package-realistic publication may proceed while it remains."
+normative_architecture_change = false
+adr_required = false
+
+[[deviation]]
id = "RCRV1-DEV-001"
date = "2026-07-27"
status = "active"