commit 2a8e39f82b9f67561d0d917304440ab79a2ea194
parent 05408359e5135a8b7672a4fb7d67f78df9959107
Author: triesap <tyson@radroots.org>
Date: Thu, 4 Jun 2026 15:14:34 -0700
config: harden rhi runtime config
- move RHI TOML to canonical logging, relays, nostr, subscriber, and receipt groups
- reject old config roots and non-RHI bearer token env references
- route startup logging through explicit config instead of ambient LOG/RUST env
- serialize the RHI test app so global hook tests complete deterministically
- verify nix run .#fmt, nix run .#check, nix run .#test, focused subscriber tests, and git diff --check
Diffstat:
10 files changed, 465 insertions(+), 248 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -2566,9 +2566,9 @@ dependencies = [
[[package]]
name = "p3-air"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a16a8d78c6a37d0eb66b008a18a9e8caa38c3a6a9ca9036416d509faf3dbc86"
+checksum = "d3a5de20a2301bf2530de1ceb13768ec3a80f729fbf8b72f813e30bc54c5bce2"
dependencies = [
"p3-field",
"p3-matrix",
@@ -2577,9 +2577,9 @@ dependencies = [
[[package]]
name = "p3-baby-bear"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d80b9c0a27092644dc22fd8fd6768dab62d325c6f7d121cf896e6bb3789779cf"
+checksum = "d69e6e9af4eaaaa60f7bb9f0e0f73ebcbaefe7e00974d97ad0fa542d6a4f0890"
dependencies = [
"cfg-if",
"num-bigint 0.4.6",
@@ -2594,9 +2594,9 @@ dependencies = [
[[package]]
name = "p3-bn254-fr"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "577200e3fa7e49e2b21e940a6dc7399dc63acb8581da088558cdf7c455adafc0"
+checksum = "2077757c7cb514202ccb5368f521f23f5709c720599e6545c683c66e0a52d2d8"
dependencies = [
"ff",
"num-bigint 0.4.6",
@@ -2609,9 +2609,9 @@ dependencies = [
[[package]]
name = "p3-challenger"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75358edd6e2562752c01f5064a66d88144a3e75ace0407166dbdf8a727597f52"
+checksum = "b6a908924d43e4cfb93fb41c8346cac211b70314385a9037e9241f5b7f3eaf77"
dependencies = [
"p3-field",
"p3-maybe-rayon",
@@ -2623,9 +2623,9 @@ dependencies = [
[[package]]
name = "p3-commit"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0991de9c2f2f8c6a6667eaebe2a5495a2132f9709ffa93357dc18865d154f16"
+checksum = "50acacc7219fce6c01db938f82c1b21b5e7133990b7fff861f91534aeb569419"
dependencies = [
"itertools 0.12.1",
"p3-challenger",
@@ -2637,9 +2637,9 @@ dependencies = [
[[package]]
name = "p3-dft"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "761f1e1b014f2b1b69bd0309124e233d64aa3590e6a41ee786000dd849506d51"
+checksum = "be6408b10a2c27eb13a7d5580c546c2179a8dc7dbc10a990657311891f9b41c0"
dependencies = [
"p3-field",
"p3-matrix",
@@ -2650,9 +2650,9 @@ dependencies = [
[[package]]
name = "p3-field"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2df7cebaa4079b24e0dd7e3aad59eebcbb99a67c1271f79ad884a7c032f5f183"
+checksum = "3dc75969ca3ac847f43e632ab979d59ff7a68f9eac8dbf8edcbba47fc2e1d3aa"
dependencies = [
"itertools 0.12.1",
"num-bigint 0.4.6",
@@ -2664,9 +2664,9 @@ dependencies = [
[[package]]
name = "p3-fri"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49ef10c7f829294e16a6248200e9571908177c0b5f35bdd70748ac3239a02d29"
+checksum = "5cbc4965ee488f3247867b7ec4bb005b8afa72cb0d461a4dcb1387ecab6426d5"
dependencies = [
"itertools 0.12.1",
"p3-challenger",
@@ -2683,9 +2683,9 @@ dependencies = [
[[package]]
name = "p3-interpolation"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413812d3ada8aa10ece23fc68d47d0c23eed1decbc3844a56f9647c7199796d7"
+checksum = "08ad7e9f08c336d7ea39d12e11951188473542565323bac2a6535e536b58487d"
dependencies = [
"p3-field",
"p3-matrix",
@@ -2694,9 +2694,9 @@ dependencies = [
[[package]]
name = "p3-keccak-air"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87a087526deb74bf12cc4efc1e50d5c387120624b15ea1de1f3efb440efbcd4d"
+checksum = "1f5bf177d56740078b5a5a842fa2393427796283dc8174b4a1a325c2d0b042de"
dependencies = [
"p3-air",
"p3-field",
@@ -2708,9 +2708,9 @@ dependencies = [
[[package]]
name = "p3-koala-bear"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cea0ba3389b034b6088d566aea8b57aa29dd2e180966e0c8056f61331c92b4e"
+checksum = "3a9683cd0ef68100df7c62490533047bcf19c04c4a0fa1efc9d7c1e03e31f6b3"
dependencies = [
"cfg-if",
"num-bigint 0.4.6",
@@ -2725,9 +2725,9 @@ dependencies = [
[[package]]
name = "p3-matrix"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fae5cc6ce726cc265cc687c1214e3f1ac1f5c6e973442286ba00d1e75da1c3cb"
+checksum = "75c3f150ceb90e09539413bf481e618d05ee19210b4e467d2902eb82d2e15281"
dependencies = [
"itertools 0.12.1",
"p3-field",
@@ -2740,18 +2740,18 @@ dependencies = [
[[package]]
name = "p3-maybe-rayon"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55ac1d2f102cf8c71dba1b449575c99697781fcc028831e83d2245787bd7a650"
+checksum = "e0641952b42da45e1dfa2d4a2a3163e330f944ad9740942f35026c0a71a605f1"
dependencies = [
"rayon",
]
[[package]]
name = "p3-mds"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f072643e385d65fb9eb089ee6824b320417f78671a0db748566e057e28b250e"
+checksum = "aa4a5f250e174dcfca5cbeac6ad75713924e7e7320e0a335e3c50b8b1f4fe8ec"
dependencies = [
"itertools 0.12.1",
"p3-dft",
@@ -2764,9 +2764,9 @@ dependencies = [
[[package]]
name = "p3-merkle-tree"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "946fcfa239847824c9216db8ac731611c7e82171ef51869bc89d985ad46000d0"
+checksum = "d5703d9229d52a8c09970e4d722c3a8b4d37e688c306c3a1c03b872efcd204e6"
dependencies = [
"itertools 0.12.1",
"p3-commit",
@@ -2781,9 +2781,9 @@ dependencies = [
[[package]]
name = "p3-poseidon2"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00cc4b6e8a439f79541b0910a016da9e6e12a05a24309bbb713e1db0db396952"
+checksum = "522986377b2164c5f94f2dae88e0e0a3d169cc6239202ef4aeb4322d60feffd0"
dependencies = [
"gcd",
"p3-field",
@@ -2795,9 +2795,9 @@ dependencies = [
[[package]]
name = "p3-symmetric"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eebff7fea7deb08a57ccf731a0ed39df25cc66a0e0c2d92c4472c4dee02ee21"
+checksum = "9047ce85c086a9b3f118e10078f10636f7bfeed5da871a04da0b61400af8793a"
dependencies = [
"itertools 0.12.1",
"p3-field",
@@ -2806,9 +2806,9 @@ dependencies = [
[[package]]
name = "p3-uni-stark"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e352e1c9765674f618dbd56e33f673a688d1f85332929fcbefa0fc5e5f4373b5"
+checksum = "fc3dfdeba14d8db621c4e52dd63973384ff35f353fd750154ff88397f4ea5adf"
dependencies = [
"itertools 0.12.1",
"p3-air",
@@ -2825,9 +2825,9 @@ dependencies = [
[[package]]
name = "p3-util"
-version = "0.3.3-succinct"
+version = "0.4.3-succinct"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8164df89bbc92e29938f916cc5f1ccbfe6a36fb5040f21ba93c1f21985b9868"
+checksum = "cff962f8eaa5f36e0447cee7c241f6b4b475fadf3ee61f154327a26bb4e009ba"
dependencies = [
"serde",
]
@@ -3641,6 +3641,7 @@ dependencies = [
"radroots_events",
"radroots_events_codec",
"radroots_identity",
+ "radroots_log",
"radroots_nostr",
"radroots_runtime",
"radroots_runtime_paths",
@@ -4129,18 +4130,18 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "slop-air"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0f533af798f4f9095bbb2a04a91f2026acfc5c5d7578581193bcec71e6a8db"
+checksum = "15597dcaa23dbf30bdbf9709938f34182736792300bb4623fe3459ebe33e775a"
dependencies = [
"p3-air",
]
[[package]]
name = "slop-algebra"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a473c3a06b466dd0708829415a8a9fab451740da066e07862c8c098904aaad6"
+checksum = "6d7e25239ac2fe1cbc2ed5114844209d70361c8d55ef812cb935c90d6f771b5b"
dependencies = [
"itertools 0.14.0",
"p3-field",
@@ -4149,9 +4150,9 @@ dependencies = [
[[package]]
name = "slop-alloc"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69234b7c30707f1ca518d469a014bbc10d38b97e17fef5dbfd158a8269255595"
+checksum = "aadbdfa7badeb1c7576621d1eeb04f305ed6c93c1accd5da5012ad1ddaea2aa1"
dependencies = [
"serde",
"slop-algebra",
@@ -4160,9 +4161,9 @@ dependencies = [
[[package]]
name = "slop-baby-bear"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0c830173902ff1d5fcb2fa8f40ef34c7d68685059a99a6b9ef91be4bb252abd"
+checksum = "9da8ad7e63b774a2f20704bfc963ebeb4f891e23754a3cb6df47a4a465a85492"
dependencies = [
"lazy_static",
"p3-baby-bear",
@@ -4175,9 +4176,9 @@ dependencies = [
[[package]]
name = "slop-basefold"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2dfc41465ee2a8f65afc09da3570997f3c0bf58ae57d559dd7bb05ad5b3f2a0"
+checksum = "012eb95fec1133adbf989e6e819943ce3cc2f12b817d063c13885a4b338581ae"
dependencies = [
"derive-where",
"itertools 0.14.0",
@@ -4198,9 +4199,9 @@ dependencies = [
[[package]]
name = "slop-basefold-prover"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fe45ae8840223fb6a1bc9cf1d97c91d0017246b168280242d75c6aa4dfb785"
+checksum = "c16dfb91c773ba557a735efe3ffbd29bff54b314440d0623ad9756ffc2dfe3fd"
dependencies = [
"derive-where",
"itertools 0.14.0",
@@ -4225,9 +4226,9 @@ dependencies = [
[[package]]
name = "slop-bn254"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7fbae5dd16a3d1e87c9e99cfd557338171710be01458bd5b12dded3878d3fd8"
+checksum = "1243ca619a3f4c07f536a060d1fd2c6f779d5b0e4cfeee3acee4d1f76ae35cb4"
dependencies = [
"ff",
"p3-bn254-fr",
@@ -4240,9 +4241,9 @@ dependencies = [
[[package]]
name = "slop-challenger"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4e80df718cef7d3100658dc8b46fafcc994b814421ec9a7d0763a6ee1e5070c"
+checksum = "594a3251b7fbbabf7e0ba1e5c2f563c2797fc2d51982c0208ce70b2f52b8fbe4"
dependencies = [
"futures",
"p3-challenger",
@@ -4253,9 +4254,9 @@ dependencies = [
[[package]]
name = "slop-commit"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4e3b8f111af56f28eb847662fb87fa8caaee53930a13e8ecea9724163259664"
+checksum = "ee8fd26ee268213b9c36d208a322f6d43ca46347d82cf07a5b83a6b95701890b"
dependencies = [
"p3-commit",
"serde",
@@ -4264,9 +4265,9 @@ dependencies = [
[[package]]
name = "slop-dft"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29b3439e560ad36f22860c1754e2d6b8715a26dd94fd0acd46a8b07be61add7f"
+checksum = "f79c2c28e4155679cc2b2ff17a1e258cbffea580182158a8e4d71dc7cd5dc9fe"
dependencies = [
"p3-dft",
"serde",
@@ -4278,18 +4279,18 @@ dependencies = [
[[package]]
name = "slop-fri"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "361123ccbbd5faa10edb44c6d76b46053e2f539538a159cd952dd4d5b4606c4b"
+checksum = "3645dbec4f2ddfc598d0250e880d422ecae2e70fbb2d7f434f0d5c21df011c1e"
dependencies = [
"p3-fri",
]
[[package]]
name = "slop-futures"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdae12f26b251c25144bae668d44da582ce12deb86d22ff6ebc10a84b2fc2abf"
+checksum = "058c54147a291a867e4253356adf491a29e9d999f45b26103bfc02452d8daa8e"
dependencies = [
"crossbeam",
"futures",
@@ -4302,9 +4303,9 @@ dependencies = [
[[package]]
name = "slop-jagged"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07d9667c28a67f83e42e40c74711f23c072e731e06e9c9997d2e4924d544ce6"
+checksum = "60222309dec4d4bffae090b160847267a23bc5b9ecd4412ba4494b486d21c776"
dependencies = [
"derive-where",
"futures",
@@ -4336,18 +4337,18 @@ dependencies = [
[[package]]
name = "slop-keccak-air"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13601bdd494e77e2d431ba4f555788caf1dc5e5812df49061fedbc957e1e19e3"
+checksum = "c7d7511944cafbc44ce208dc768b591fa6fc55a87d3f7238f8888e2536db607c"
dependencies = [
"p3-keccak-air",
]
[[package]]
name = "slop-koala-bear"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6586b1c0e66c503e4026a8cb007349fa99c2466957c5b09d18fe658d1391ed8"
+checksum = "1ccc675284794435dd053d5e7415089bbd08fccf92cd91e044ea3213821dfb5c"
dependencies = [
"lazy_static",
"p3-koala-bear",
@@ -4360,27 +4361,27 @@ dependencies = [
[[package]]
name = "slop-matrix"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e44c7beb600f1e47c43c2745711cf412872999b1ce6a44b8fb5683cd0b1a64a2"
+checksum = "af3d316b50bf50f8e75d388c829a499ec2f2db77c87c4183d3884d75b99df244"
dependencies = [
"p3-matrix",
]
[[package]]
name = "slop-maybe-rayon"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7a2e15a4db7cbc703c203c1ea00d5a889bf3ff9646e8cfd7076ef584ebca441"
+checksum = "cabdac3bd6efd75739924e4162340caa59b32b24e02d3f84ab8f56d3f3386ee2"
dependencies = [
"p3-maybe-rayon",
]
[[package]]
name = "slop-merkle-tree"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c3d8df667dc00a44093c22564cfc0140b0ca16e41e6b0be7368822832d71d45"
+checksum = "c3b49522dc0a3b87966ba354d8cfcb762baadf9d2641f565aebca39e3032fe2a"
dependencies = [
"derive-where",
"itertools 0.14.0",
@@ -4404,9 +4405,9 @@ dependencies = [
[[package]]
name = "slop-multilinear"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f33c77ba8c2c516592bc23669b47c38babdd3aed64389e368cc1f2f499f8b75e"
+checksum = "e04d8ec813376aaa38b94c3e12a07dd6dd76d3e7240708f51a8daef48b6c2f8a"
dependencies = [
"derive-where",
"futures",
@@ -4425,27 +4426,27 @@ dependencies = [
[[package]]
name = "slop-poseidon2"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c956b11fff1b8a071fa4ba982dc35e458cff1620dc7b33d9cf22d8df30895f79"
+checksum = "7f77602b918f667f970d017293189f9e60ba056d1933c9f717634877838297bc"
dependencies = [
"p3-poseidon2",
]
[[package]]
name = "slop-primitives"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de169e0ca381847f9efa0db5a54533371c10558d7aaed4cb3b2a9bae24a0fe83"
+checksum = "592ded42eb74fd87d2ce13592906cf86f201128dd18e2aa5a35d298bc3534dcb"
dependencies = [
"slop-algebra",
]
[[package]]
name = "slop-stacked"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9103802fef961c064a96457b60da838b2d4aa336b00a89fe3af948d684b8226"
+checksum = "fd59d332620d6da35a7b4f8837906ec7365761bc0bfda344bb232f8c0b395db7"
dependencies = [
"derive-where",
"futures",
@@ -4466,9 +4467,9 @@ dependencies = [
[[package]]
name = "slop-sumcheck"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4b3d5051be430c5b47e95f8258221cb40d276fa3461d0239ca3cd96d95f4ccc"
+checksum = "4d1176c38a586911076061f419101bdc6491b7b9e2039553f2d3a8237158cfb3"
dependencies = [
"futures",
"itertools 0.14.0",
@@ -4484,18 +4485,18 @@ dependencies = [
[[package]]
name = "slop-symmetric"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955145ad6e3a1d083a428f9274071cfbb44c3b29013aae9d6c4c29fb7328cfc0"
+checksum = "108bf1769132b782218e3606b8e2f310741fb89d1745234b59ff17d9e7ab8700"
dependencies = [
"p3-symmetric",
]
[[package]]
name = "slop-tensor"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84835a3d915fb0402eb7b821ba1637399e7f3d330ba8f9b6faca0317d6df7277"
+checksum = "2bb040f7f2dc9be449a25184d2aee0321a748058d81d646a4a96ffcf32e53963"
dependencies = [
"arrayvec",
"derive-where",
@@ -4513,18 +4514,18 @@ dependencies = [
[[package]]
name = "slop-uni-stark"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd531cc607df2b64e68ea80cc1c05584205b06e70dc5b89563f6b74ab1723f74"
+checksum = "5d8a279d09e78b0ea5c5e97daa1b6440d47db8118bf3f5014667661c169c4590"
dependencies = [
"p3-uni-stark",
]
[[package]]
name = "slop-utils"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ce2c30637af6348960554f9aea4cebce7eb172f173f2187892fcac5cceb3729"
+checksum = "1e9910567ffcfdd03aec3e5d220853f01bdbdfe1c1752f7e34cd0a4e20b226bd"
dependencies = [
"p3-util",
"tracing-forest",
@@ -4533,9 +4534,9 @@ dependencies = [
[[package]]
name = "slop-whir"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bf15dc092785295fe2fd22f1057941a3d5f4d0f6f9ffdce43bb1c9fee8e5578"
+checksum = "99519ca11d444567b54d786f71687f63612a75c58404abde353185f53f38dd5e"
dependencies = [
"derive-where",
"futures",
@@ -4602,9 +4603,9 @@ dependencies = [
[[package]]
name = "sp1-build"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "082381d1779d12762a5fb4efa150c2ebdede79a3500eb0a93bf875f7cd64efa0"
+checksum = "1bb06355982a703c0839b6ca1dc69a50d56a3c85e55d0badc8c3b18ebe8c9fa6"
dependencies = [
"anyhow",
"cargo_metadata",
@@ -4616,9 +4617,9 @@ dependencies = [
[[package]]
name = "sp1-core-executor"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61464c74d36b4ab16d44011be6ec1896ee463d9369238ec9edcc1c6ce61f11fd"
+checksum = "58d3af539d746d5312346d33899d297232351ca5aed1668f16d5a5a0ee0a3ab3"
dependencies = [
"bincode",
"bytemuck",
@@ -4657,9 +4658,9 @@ dependencies = [
[[package]]
name = "sp1-core-executor-runner"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52434a8037fd9f19a259f6a432df02fba3ccd2e23ce6a61a50477aba59e04c6e"
+checksum = "19b3b61a7c5c891a8c18ac31deccca3914d59132f8656d6d7db09c453ee5ed6f"
dependencies = [
"base64 0.22.1",
"bincode",
@@ -4679,9 +4680,9 @@ dependencies = [
[[package]]
name = "sp1-core-executor-runner-binary"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d79d7911837cf8ef8fcd1fb791f9133914e7067f8bff3e7d6ec6f0ff46cf929b"
+checksum = "6b0c810b99e4fca0b0d0e791a2a7d6b080aad6ffb6cf950e633409eb2723cba3"
dependencies = [
"bincode",
"crash-handler",
@@ -4694,9 +4695,9 @@ dependencies = [
[[package]]
name = "sp1-core-machine"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bab240796901b64aa65402d14351b37f8e955438e6ee1861e3c9219bba02691"
+checksum = "29b3851384225aae5588b1fca3c9c8f67001187d53abff21709a7cf8f6098f08"
dependencies = [
"bincode",
"cfg-if",
@@ -4743,9 +4744,9 @@ dependencies = [
[[package]]
name = "sp1-cuda"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b00f787fa4b5cbd29e9baddee1e590c5e689333f2b01e5f704293b7f6f17570c"
+checksum = "468c0e82c980535eacdc57d2969f087e56002cd764809596e2f8e513c74abff9"
dependencies = [
"bincode",
"bytes",
@@ -4765,9 +4766,9 @@ dependencies = [
[[package]]
name = "sp1-curves"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac661914a8708368643c805fbc6aeadba004a0619c2f5f1fbfc1866fd37b5c10"
+checksum = "0bd90718c62dc06a42b9a47308ca914bb6d3f04f9265c77cb76bc135929cd59d"
dependencies = [
"cfg-if",
"dashu",
@@ -4786,9 +4787,9 @@ dependencies = [
[[package]]
name = "sp1-derive"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a4f810860abfdc645c4d0589d6efb9302b0d2b3beab8cc60804cb772d5acbe"
+checksum = "ecac7ec9b0d2a12f486486a62b2805257e7ffcced51dd39d25fcefaa133adaf6"
dependencies = [
"proc-macro2",
"quote",
@@ -4797,9 +4798,9 @@ dependencies = [
[[package]]
name = "sp1-hypercube"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02c2575307ebcd93b4320a06fb48a818669551a64a0fecf3b5666628e15f90e2"
+checksum = "8449d118a6fe1532899da955c30247c413c90e8c78b06a452f3a40ff6432299e"
dependencies = [
"arrayref",
"deepsize2",
@@ -4846,9 +4847,9 @@ dependencies = [
[[package]]
name = "sp1-jit"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf63168fc46696206b9a8e664283ea630bda7911eb255e1d96391787858c581"
+checksum = "9355cbdc9d7183d8ab244b695ae7630afb559c6b2bd466bc89a2f3e334b2047a"
dependencies = [
"dynasmrt",
"hashbrown 0.14.5",
@@ -4863,9 +4864,9 @@ dependencies = [
[[package]]
name = "sp1-primitives"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4df14efe799ebd675cf530c853153a4787327a2385067716dfad4ede79ff31ad"
+checksum = "f20c3dd3131b1285420ca25a37f507915ab609887d6dda73973396a0faa719c1"
dependencies = [
"bincode",
"blake3",
@@ -4887,9 +4888,9 @@ dependencies = [
[[package]]
name = "sp1-prover"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf089b2fc3cacd5040e6eaeec7d96dc97bfd428421492a0be939f72d48a49851"
+checksum = "72c3cb0201a41e9da5372b2b437af07ee3ccd6dca99a69ece4213af40d9436b7"
dependencies = [
"anyhow",
"bincode",
@@ -4951,9 +4952,9 @@ dependencies = [
[[package]]
name = "sp1-prover-types"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e29236cc1217ab04fdc548dbc83c817ecbf78c348879f5dbe65649680cd2ce89"
+checksum = "8b289303f43e7ae1d07b528f34e78ca088c61dea13a3458f63a6570da11e32e5"
dependencies = [
"anyhow",
"async-scoped",
@@ -4975,9 +4976,9 @@ dependencies = [
[[package]]
name = "sp1-recursion-circuit"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c809d2ff42f22ebeafac078f7fae717e50f9658bcd1a5e847c0c7d7d7bf94019"
+checksum = "19d9ce031605bc111474c11e7841536f3469311253791ef326ee16427e10178e"
dependencies = [
"bincode",
"itertools 0.14.0",
@@ -5015,9 +5016,9 @@ dependencies = [
[[package]]
name = "sp1-recursion-compiler"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9162e3ad6f369307142a81d627c4883316f7d65b1e5a0ece3dd45780e29ea2"
+checksum = "993b5dcde57622009857883637177946254f3cf00290cc4b998b54a76ffab7c0"
dependencies = [
"backtrace",
"cfg-if",
@@ -5036,9 +5037,9 @@ dependencies = [
[[package]]
name = "sp1-recursion-executor"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec793f4c6c032d141476c97fb83dd86abfe3c68f8aace603d57a3d20859a10c5"
+checksum = "983d18b6e0e641c8173b250c234fe355c3a9ba5b7485d3af5a54ddb7ab51e814"
dependencies = [
"backtrace",
"cfg-if",
@@ -5060,9 +5061,9 @@ dependencies = [
[[package]]
name = "sp1-recursion-gnark-ffi"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac3939b80a23bc369c2ffc1fdb136de3fd83323fe53b03b17fbb11ea383f330"
+checksum = "43cb9411bdf57706fa6b342c60534c47c6a066aeb5129e89d8d39f6fb37d12e5"
dependencies = [
"anyhow",
"bincode",
@@ -5084,9 +5085,9 @@ dependencies = [
[[package]]
name = "sp1-recursion-machine"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e60fd9a5f5b9bc39e3ddb39c5ac49da32b6aa7ab63c4fef7b6bb2565c2e98b9e"
+checksum = "01ab820757fa3783a0230efd48a509fb64b8e7fbaf1d257211dae0c66df79002"
dependencies = [
"itertools 0.14.0",
"rand 0.8.5",
@@ -5106,9 +5107,9 @@ dependencies = [
[[package]]
name = "sp1-sdk"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c15071380f43c33b3dbe5650cd5acf54a8e0af4b80a833075a56309256a383"
+checksum = "321a52e7b41aef0eb04e880bc2625f9d150553a04be7607756ac5d494850d037"
dependencies = [
"anyhow",
"async-trait",
@@ -5144,9 +5145,9 @@ dependencies = [
[[package]]
name = "sp1-verifier"
-version = "6.2.1"
+version = "6.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91895b72db38423e477635cf22d65a3dc9dc333a872fc2fe0cd6e8daf9661891"
+checksum = "44e7a8627fcbfd89ec21932ae33e3a5b9adc4ef844c0e295ef36ee43f0fbf442"
dependencies = [
"bincode",
"blake3",
diff --git a/Cargo.toml b/Cargo.toml
@@ -15,6 +15,7 @@ radroots_core = { path = "../lib/crates/core" }
radroots_events = { path = "../lib/crates/events" }
radroots_events_codec = { path = "../lib/crates/events_codec" }
radroots_identity = { path = "../lib/crates/identity" }
+radroots_log = { path = "../lib/crates/log" }
radroots_nostr = { path = "../lib/crates/nostr" }
radroots_runtime = { path = "../lib/crates/runtime" }
radroots_runtime_paths = { path = "../lib/crates/runtime_paths" }
@@ -36,6 +37,7 @@ radroots_core = { workspace = true, features = ["std", "serde", "typeshare"] }
radroots_events = { workspace = true, features = ["serde"] }
radroots_events_codec = { workspace = true, features = ["nostr"] }
radroots_identity = { workspace = true }
+radroots_log = { workspace = true }
radroots_nostr = { workspace = true, features = ["client", "codec", "events", "http"] }
radroots_runtime = { workspace = true, features = ["cli"] }
radroots_runtime_paths = { workspace = true }
diff --git a/config.toml b/config.toml
@@ -1,47 +1,29 @@
[metadata]
name = "rhi"
-# display_name = ""
-# about = ""
-# picture = ""
-# banner = ""
-# banner = ""
-# nip05 = ""
-# lud06 = ""
-# lud16 = ""
-[config]
-# Service-host sample location:
-# /etc/radroots/workers/rhi/config.toml
-# Launch with:
-# RHI_PATHS_PROFILE=service_host
-#
-# Manual operator runs may instead place this file at:
-# ~/.radroots/config/workers/rhi/config.toml
-# Repo-owned local runs should prefer the root .env.local control plane, which derives
-# RHI_PATHS_PROFILE=repo_local and RHI_PATHS_REPO_LOCAL_ROOT automatically
-# when path-like values are omitted, the active profile derives:
-# interactive_user:
-# logs_dir = ~/.radroots/logs/workers/rhi
-# worker identity = ~/.radroots/secrets/workers/rhi/identity.secret.json
-# subscriber state = ~/.radroots/data/workers/rhi/trade-listing/state.json
-# service_host:
-# logs_dir = /var/log/radroots/workers/rhi
-# worker identity = /etc/radroots/secrets/workers/rhi/identity.secret.json
-# subscriber state = /var/lib/radroots/workers/rhi/trade-listing/state.json
-# the canonical live worker identity is always an encrypted local envelope
-# only override logs_dir or config.subscriber.state.path intentionally
-relays = [
+[logging]
+filter = "info"
+stdout = true
+
+[relays]
+urls = [
"ws://127.0.0.1:8080"
]
-nip89_identifier = "rhi"
-nip89_extra_tags = []
-[config.subscriber.backoff]
+[nostr.nip89]
+identifier = "rhi"
+extra_tags = []
+
+[subscriber.backoff]
base_ms = 500
max_ms = 30000
factor = 2
jitter_ms = 0
-[config.subscriber.state]
+[subscriber.state]
replay_window_secs = 86400
replay_overlap_secs = 300
+
+[trade_validation_receipt]
+backend = "disabled"
+proof_mode = "none"
diff --git a/flake.nix b/flake.nix
@@ -142,7 +142,7 @@
};
test = mkApp "test" {
text = ''
- cargo test
+ cargo test -- --test-threads=1
'';
};
}
diff --git a/src/config.rs b/src/config.rs
@@ -1,4 +1,4 @@
-use anyhow::{Context, Result};
+use anyhow::{Context, Result, bail};
use radroots_nostr::prelude::RadrootsNostrMetadata;
use radroots_runtime::{BackoffConfig, RadrootsNostrServiceConfig};
use serde::{Deserialize, Serialize};
@@ -17,27 +17,78 @@ fn default_replay_overlap_secs() -> u64 {
5 * 60
}
+fn default_logging_filter() -> String {
+ "info".to_owned()
+}
+
+fn default_logging_stdout() -> bool {
+ true
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct LoggingConfig {
+ pub output_dir: PathBuf,
+ pub filter: String,
+ pub stdout: bool,
+}
+
+#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default, deny_unknown_fields)]
+struct RawLoggingConfig {
+ pub output_dir: Option<PathBuf>,
+ pub filter: Option<String>,
+ pub stdout: Option<bool>,
+}
+
+impl RawLoggingConfig {
+ fn into_logging_config(self, paths: &RhiRuntimePaths) -> Result<LoggingConfig> {
+ let filter = self.filter.unwrap_or_else(default_logging_filter);
+ let filter = filter.trim();
+ if filter.is_empty() {
+ bail!("logging.filter must not be empty");
+ }
+
+ Ok(LoggingConfig {
+ output_dir: self.output_dir.unwrap_or_else(|| paths.logs_dir.clone()),
+ filter: filter.to_owned(),
+ stdout: self.stdout.unwrap_or_else(default_logging_stdout),
+ })
+ }
+}
+
#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default, deny_unknown_fields)]
+struct RawRelaysConfig {
+ pub urls: Vec<String>,
+}
+
+#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default, deny_unknown_fields)]
+struct RawNostrConfig {
+ pub nip89: RawNip89Config,
+}
+
+#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default, deny_unknown_fields)]
+struct RawNip89Config {
+ pub identifier: Option<String>,
+ pub extra_tags: Vec<Vec<String>>,
+}
+
+#[derive(Debug, Clone)]
struct RawServiceConfig {
- #[serde(default)]
- pub logs_dir: Option<String>,
- #[serde(default)]
- pub relays: Vec<String>,
- #[serde(default)]
- pub nip89_identifier: Option<String>,
- #[serde(default)]
- pub nip89_extra_tags: Vec<Vec<String>>,
+ pub logging: LoggingConfig,
+ pub relays: RawRelaysConfig,
+ pub nostr: RawNostrConfig,
}
impl RawServiceConfig {
- fn into_service_config(self, paths: &RhiRuntimePaths) -> RadrootsNostrServiceConfig {
+ fn into_service_config(self) -> RadrootsNostrServiceConfig {
RadrootsNostrServiceConfig {
- logs_dir: self
- .logs_dir
- .unwrap_or_else(|| paths.logs_dir.display().to_string()),
- relays: self.relays,
- nip89_identifier: self.nip89_identifier,
- nip89_extra_tags: self.nip89_extra_tags,
+ logs_dir: self.logging.output_dir.display().to_string(),
+ relays: self.relays.urls,
+ nip89_identifier: self.nostr.nip89.identifier,
+ nip89_extra_tags: self.nostr.nip89.extra_tags,
}
}
}
@@ -46,6 +97,7 @@ impl RawServiceConfig {
pub struct Configuration {
#[serde(flatten)]
pub service: RadrootsNostrServiceConfig,
+ pub logging: LoggingConfig,
#[serde(default)]
pub subscriber: SubscriberConfig,
#[serde(default)]
@@ -61,6 +113,7 @@ pub struct SubscriberConfig {
}
#[derive(Debug, Deserialize, Clone, Default)]
+#[serde(default, deny_unknown_fields)]
struct RawSubscriberConfig {
#[serde(default)]
pub backoff: BackoffConfig,
@@ -85,6 +138,7 @@ pub struct SubscriberStateConfig {
}
#[derive(Debug, Deserialize, Clone)]
+#[serde(deny_unknown_fields)]
struct RawSubscriberStateConfig {
#[serde(default)]
pub path: Option<PathBuf>,
@@ -128,31 +182,40 @@ impl Default for SubscriberStateConfig {
}
#[derive(Debug, Deserialize, Clone)]
-struct RawConfiguration {
- #[serde(flatten)]
- pub service: RawServiceConfig,
+#[serde(deny_unknown_fields)]
+struct RawSettings {
+ pub metadata: RadrootsNostrMetadata,
+ #[serde(default)]
+ pub logging: RawLoggingConfig,
+ #[serde(default)]
+ pub relays: RawRelaysConfig,
+ #[serde(default)]
+ pub nostr: RawNostrConfig,
#[serde(default)]
pub subscriber: RawSubscriberConfig,
#[serde(default)]
pub trade_validation_receipt: TradeValidationReceiptProverPolicy,
}
-#[derive(Debug, Deserialize, Clone)]
-struct RawSettings {
- pub metadata: RadrootsNostrMetadata,
- pub config: RawConfiguration,
-}
-
impl RawSettings {
- fn into_settings(self, paths: &RhiRuntimePaths) -> Settings {
- Settings {
+ fn into_settings(self, paths: &RhiRuntimePaths) -> Result<Settings> {
+ let logging = self.logging.into_logging_config(paths)?;
+ let service = RawServiceConfig {
+ logging: logging.clone(),
+ relays: self.relays,
+ nostr: self.nostr,
+ }
+ .into_service_config();
+
+ Ok(Settings {
metadata: self.metadata,
config: Configuration {
- service: self.config.service.into_service_config(paths),
- subscriber: self.config.subscriber.into_subscriber_config(paths),
- trade_validation_receipt: self.config.trade_validation_receipt,
+ service,
+ logging,
+ subscriber: self.subscriber.into_subscriber_config(paths),
+ trade_validation_receipt: self.trade_validation_receipt,
},
- }
+ })
}
}
@@ -173,7 +236,7 @@ fn load_settings_from_path_with_resolver(
.with_context(|| format!("read configuration from {}", path.display()))?;
let settings: RawSettings =
toml::from_str(&raw).with_context(|| format!("parse configuration {}", path.display()))?;
- Ok(settings.into_settings(&paths))
+ settings.into_settings(&paths)
}
pub fn load_settings_from_path(path: &Path) -> Result<Settings> {
@@ -328,11 +391,13 @@ mod tests {
[metadata]
name = "rhi-test"
-[config]
-relays = ["wss://relay.example.com"]
-nip89_identifier = "rhi"
+[relays]
+urls = ["wss://relay.example.com"]
-[config.subscriber.state]
+[nostr.nip89]
+identifier = "rhi"
+
+[subscriber.state]
replay_window_secs = 123
replay_overlap_secs = 45
"#,
@@ -352,6 +417,20 @@ replay_overlap_secs = 45
"/home/treesap/.radroots/logs/workers/rhi"
);
assert_eq!(
+ settings.config.logging.output_dir,
+ PathBuf::from("/home/treesap/.radroots/logs/workers/rhi")
+ );
+ assert_eq!(settings.config.logging.filter, "info");
+ assert!(settings.config.logging.stdout);
+ assert_eq!(
+ settings.config.service.relays,
+ vec!["wss://relay.example.com"]
+ );
+ assert_eq!(
+ settings.config.service.nip89_identifier.as_deref(),
+ Some("rhi")
+ );
+ assert_eq!(
settings.config.subscriber.state.path,
PathBuf::from("/home/treesap/.radroots/data/workers/rhi/trade-listing/state.json")
);
@@ -377,10 +456,28 @@ replay_overlap_secs = 45
[metadata]
name = "rhi-test"
-[config]
-relays = ["wss://relay.example.com"]
+[logging]
+output_dir = "logs/rhi"
+filter = "warn"
+stdout = false
-[config.trade_validation_receipt]
+[relays]
+urls = ["wss://relay.example.com"]
+
+[nostr.nip89]
+identifier = "rhi"
+extra_tags = [["t", "radroots"]]
+
+[subscriber.backoff]
+base_ms = 10
+max_ms = 100
+factor = 3
+jitter_ms = 5
+
+[subscriber.state]
+path = "state/trade-listing.json"
+
+[trade_validation_receipt]
backend = "deterministic_none"
proof_mode = "none"
"#,
@@ -395,6 +492,33 @@ proof_mode = "none"
)
.expect("load settings");
+ assert_eq!(settings.config.service.logs_dir, "logs/rhi");
+ assert_eq!(
+ settings.config.logging.output_dir,
+ PathBuf::from("logs/rhi")
+ );
+ assert_eq!(settings.config.logging.filter, "warn");
+ assert!(!settings.config.logging.stdout);
+ assert_eq!(
+ settings.config.service.relays,
+ vec!["wss://relay.example.com"]
+ );
+ assert_eq!(
+ settings.config.service.nip89_identifier.as_deref(),
+ Some("rhi")
+ );
+ assert_eq!(
+ settings.config.service.nip89_extra_tags,
+ vec![vec!["t".to_owned(), "radroots".to_owned()]]
+ );
+ assert_eq!(settings.config.subscriber.backoff.base_ms, 10);
+ assert_eq!(settings.config.subscriber.backoff.max_ms, 100);
+ assert_eq!(settings.config.subscriber.backoff.factor, 3);
+ assert_eq!(settings.config.subscriber.backoff.jitter_ms, 5);
+ assert_eq!(
+ settings.config.subscriber.state.path,
+ PathBuf::from("state/trade-listing.json")
+ );
assert_eq!(
settings.config.trade_validation_receipt.backend,
TradeValidationReceiptProverBackend::DeterministicNone
@@ -406,6 +530,71 @@ proof_mode = "none"
}
#[test]
+ fn old_config_roots_are_rejected() {
+ let temp = tempfile::tempdir().expect("tempdir");
+ for (name, body, needle) in [
+ (
+ "config-root",
+ r#"
+[metadata]
+name = "rhi-test"
+
+[config]
+relays = ["wss://relay.example.com"]
+"#,
+ "unknown field `config`",
+ ),
+ (
+ "config-subscriber-backoff",
+ r#"
+[metadata]
+name = "rhi-test"
+
+[config.subscriber.backoff]
+base_ms = 10
+"#,
+ "unknown field `config`",
+ ),
+ (
+ "config-subscriber-state",
+ r#"
+[metadata]
+name = "rhi-test"
+
+[config.subscriber.state]
+replay_window_secs = 10
+"#,
+ "unknown field `config`",
+ ),
+ (
+ "config-trade-validation-receipt",
+ r#"
+[metadata]
+name = "rhi-test"
+
+[config.trade_validation_receipt]
+backend = "deterministic_none"
+proof_mode = "none"
+"#,
+ "unknown field `config`",
+ ),
+ ] {
+ let config_path = temp.path().join(format!("{name}.toml"));
+ std::fs::write(&config_path, body).expect("write config");
+
+ let error = load_settings_from_path_with_resolver(
+ &config_path,
+ &linux_resolver(),
+ RadrootsPathProfile::InteractiveUser,
+ None,
+ )
+ .expect_err("old config root must fail");
+ let message = format!("{error:#}");
+ assert!(message.contains(needle), "{message}");
+ }
+ }
+
+ #[test]
fn default_subscriber_state_path_is_canonical_for_current_process() {
let path =
default_subscriber_state_path_for_process().expect("resolve current process defaults");
@@ -433,8 +622,8 @@ proof_mode = "none"
assert_eq!(
contract.path_overrides.subordinate_path_override_keys,
vec![
- "config.service.logs_dir".to_owned(),
- "config.subscriber.state.path".to_owned(),
+ "logging.output_dir".to_owned(),
+ "subscriber.state.path".to_owned(),
]
);
assert_eq!(
diff --git a/src/features/trade_listing/subscriber.rs b/src/features/trade_listing/subscriber.rs
@@ -344,15 +344,12 @@ mod tests {
RadrootsNostrRelayPoolNotification, RadrootsNostrRelayUrl, RadrootsNostrSubscriptionId,
RadrootsNostrTag,
};
- use std::sync::{Mutex, MutexGuard};
- use tokio::sync::watch;
+ use tokio::sync::{Mutex, MutexGuard, watch};
- static TEST_LOCK: Mutex<()> = Mutex::new(());
+ static TEST_LOCK: Mutex<()> = Mutex::const_new(());
- fn test_guard() -> MutexGuard<'static, ()> {
- let guard = TEST_LOCK
- .lock()
- .unwrap_or_else(std::sync::PoisonError::into_inner);
+ async fn test_guard() -> MutexGuard<'static, ()> {
+ let guard = TEST_LOCK.lock().await;
*subscriber_test_hooks()
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = SubscriberTestHooks::default();
@@ -394,7 +391,7 @@ mod tests {
#[tokio::test]
async fn subscriber_io_wrappers_cover_fallback_and_hook_paths() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let event = RadrootsNostrEventBuilder::new(RadrootsNostrKind::TextNote, "test")
@@ -456,7 +453,7 @@ mod tests {
#[tokio::test]
async fn subscriber_returns_ok_when_stop_is_pre_requested() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let (_tx, rx) = watch::channel(true);
@@ -469,7 +466,7 @@ mod tests {
#[tokio::test]
async fn subscriber_reuses_runtime_owned_state_across_runs() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let runtime = shared_runtime();
@@ -504,7 +501,7 @@ mod tests {
#[tokio::test]
async fn subscriber_returns_err_when_no_relays_are_configured() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let (_tx, rx) = watch::channel(false);
@@ -517,7 +514,7 @@ mod tests {
#[tokio::test]
async fn subscriber_can_stop_after_start_when_relay_is_present() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -536,7 +533,7 @@ mod tests {
#[tokio::test]
async fn subscriber_covers_notification_closed_path() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -555,7 +552,7 @@ mod tests {
#[tokio::test]
async fn subscriber_covers_non_event_notification_and_stop_ok_path() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -582,7 +579,7 @@ mod tests {
#[tokio::test]
async fn subscriber_covers_event_processing_paths() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -613,7 +610,7 @@ mod tests {
#[tokio::test]
async fn subscriber_covers_handle_event_and_error_paths() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -655,7 +652,7 @@ mod tests {
#[tokio::test]
async fn subscriber_covers_delay_and_error_feedback_warn_path() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let _ = client.add_relay("wss://relay.example.com").await;
@@ -687,7 +684,7 @@ mod tests {
#[tokio::test]
async fn handled_domain_errors_advance_replay_anchor() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let runtime = shared_runtime();
@@ -718,7 +715,7 @@ mod tests {
#[tokio::test]
async fn subscriber_process_event_feedback_error_branches_are_covered() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let event = RadrootsNostrEventBuilder::new(RadrootsNostrKind::Custom(6000), "event")
@@ -745,7 +742,7 @@ mod tests {
#[tokio::test]
async fn subscriber_process_event_feedback_non_error_branches_are_covered() {
- let _guard = test_guard();
+ let _guard = test_guard().await;
let keys = RadrootsNostrKeys::generate();
let client = RadrootsNostrClient::new(keys.clone());
let event_ok = RadrootsNostrEventBuilder::new(RadrootsNostrKind::Custom(6000), "ok")
diff --git a/src/features/trade_validation_receipt.rs b/src/features/trade_validation_receipt.rs
@@ -314,30 +314,37 @@ impl TradeValidationReceiptRemoteHttpAuth {
match self {
Self::NoAuth => Ok(()),
Self::BearerTokenEnv { env_var } => {
- if env_var.trim().is_empty() {
- return Err(TradeValidationReceiptJobError::RemoteHttpInvalidConfig(
- "auth.env_var",
- ));
- }
+ validate_rhi_secret_env_var_name(env_var)?;
Ok(())
}
}
}
}
+fn validate_rhi_secret_env_var_name(env_var: &str) -> Result<&str, TradeValidationReceiptJobError> {
+ let env_var = env_var.trim();
+ if env_var.is_empty() || !env_var.starts_with("RHI_") {
+ return Err(TradeValidationReceiptJobError::RemoteHttpInvalidConfig(
+ "auth.env_var",
+ ));
+ }
+ Ok(env_var)
+}
+
fn remote_http_auth_token(
config: &TradeValidationReceiptRemoteHttpProverConfig,
) -> Result<Option<String>, TradeValidationReceiptJobError> {
match &config.auth {
TradeValidationReceiptRemoteHttpAuth::NoAuth => Ok(None),
TradeValidationReceiptRemoteHttpAuth::BearerTokenEnv { env_var } => {
+ let env_var = validate_rhi_secret_env_var_name(env_var)?;
let value = std::env::var(env_var).map_err(|_| {
- TradeValidationReceiptJobError::RemoteHttpAuthTokenMissing(env_var.clone())
+ TradeValidationReceiptJobError::RemoteHttpAuthTokenMissing(env_var.to_owned())
})?;
let token = value.trim();
if token.is_empty() {
return Err(TradeValidationReceiptJobError::RemoteHttpAuthTokenMissing(
- env_var.clone(),
+ env_var.to_owned(),
));
}
Ok(Some(token.to_owned()))
@@ -1993,7 +2000,7 @@ mod tests {
.as_mut()
.expect("remote config")
.auth = TradeValidationReceiptRemoteHttpAuth::BearerTokenEnv {
- env_var: "RADROOTS_TEST_REMOTE_HTTP_TOKEN".to_string(),
+ env_var: "RHI_TEST_REMOTE_HTTP_TOKEN".to_string(),
};
assert!(matches!(
bearer_over_http.validate(),
@@ -2003,6 +2010,23 @@ mod tests {
));
}
+ #[test]
+ fn remote_http_auth_env_var_must_use_rhi_prefix_before_process_env_read() {
+ let mut policy = remote_http_policy();
+ let remote_http = policy.remote_http.as_mut().expect("remote config");
+ remote_http.endpoint_url = "https://example.test/prove".to_string();
+ remote_http.auth = TradeValidationReceiptRemoteHttpAuth::BearerTokenEnv {
+ env_var: "RADROOTS_TEST_REMOTE_HTTP_TOKEN".to_string(),
+ };
+
+ assert!(matches!(
+ policy.validate(),
+ Err(TradeValidationReceiptJobError::RemoteHttpInvalidConfig(
+ "auth.env_var"
+ ))
+ ));
+ }
+
#[cfg(feature = "sp1_verify")]
#[test]
fn remote_http_policy_accepts_core_mode_when_configured() {
diff --git a/src/lib.rs b/src/lib.rs
@@ -235,6 +235,11 @@ mod tests {
nip89_identifier: Some("rhi".to_string()),
nip89_extra_tags: Vec::new(),
},
+ logging: config::LoggingConfig {
+ output_dir: std::env::temp_dir().join("rhi-test-logs"),
+ filter: "info".to_string(),
+ stdout: true,
+ },
subscriber: config::SubscriberConfig {
backoff: radroots_runtime::BackoffConfig {
base_ms: 1,
diff --git a/src/main.rs b/src/main.rs
@@ -6,6 +6,8 @@ use anyhow::Result;
#[cfg(not(test))]
use clap::Parser;
#[cfg(not(test))]
+use radroots_log::{LogFileLayout, LoggingOptions};
+#[cfg(not(test))]
use rhi::cli::Command;
use rhi::{cli_args, config, paths, run_rhi};
#[cfg(not(test))]
@@ -91,14 +93,23 @@ fn load_args_and_settings() -> Result<(cli_args, config::Settings)> {
.unwrap_or_else(paths::default_config_path_for_process)?;
let settings =
config::load_settings_from_path(&config_path).context("load configuration")?;
- radroots_runtime::init_with_logs_dir(
- std::path::Path::new(settings.config.service.logs_dir.as_str()),
- None,
- )?;
+ init_rhi_logging(&settings)?;
Ok((args, settings))
}
}
+#[cfg(not(test))]
+fn init_rhi_logging(settings: &config::Settings) -> Result<()> {
+ radroots_log::init_logging(LoggingOptions {
+ dir: Some(settings.config.logging.output_dir.clone()),
+ file_name: "rhi.log".to_owned(),
+ stdout: settings.config.logging.stdout,
+ default_level: Some(settings.config.logging.filter.clone()),
+ file_layout: LogFileLayout::PrefixedDate,
+ })
+ .context("initialize logging")
+}
+
fn runtime_startup_report(
args: &cli_args,
settings: &config::Settings,
@@ -122,9 +133,9 @@ fn runtime_startup_report(
&contract.canonical_config_path,
),
canonical_config_path: contract.canonical_config_path.clone(),
- logs_dir: PathBuf::from(settings.config.service.logs_dir.as_str()),
+ logs_dir: settings.config.logging.output_dir.clone(),
logs_dir_source: config_or_profile_path_source(
- &PathBuf::from(settings.config.service.logs_dir.as_str()),
+ &settings.config.logging.output_dir,
&contract.canonical_logs_dir,
),
canonical_logs_dir: contract.canonical_logs_dir.clone(),
@@ -268,6 +279,11 @@ mod tests {
nip89_identifier: Some("rhi".to_string()),
nip89_extra_tags: Vec::new(),
},
+ logging: config::LoggingConfig {
+ output_dir: std::env::temp_dir().join("rhi-test-logs"),
+ filter: "info".to_string(),
+ stdout: true,
+ },
subscriber: config::SubscriberConfig::default(),
trade_validation_receipt:
rhi::features::trade_validation_receipt::TradeValidationReceiptProverPolicy::default(),
@@ -290,8 +306,8 @@ mod tests {
repo_local_root_source: None,
subordinate_path_override_source: "config_artifact".to_string(),
subordinate_path_override_keys: vec![
- "config.service.logs_dir".to_string(),
- "config.subscriber.state.path".to_string(),
+ "logging.output_dir".to_string(),
+ "subscriber.state.path".to_string(),
],
},
default_shared_secret_backend: "encrypted_file".to_string(),
@@ -418,6 +434,7 @@ mod tests {
};
let mut settings = minimal_settings();
settings.config.service.logs_dir = "/tmp/rhi/logs".to_string();
+ settings.config.logging.output_dir = PathBuf::from("/tmp/rhi/logs");
settings.config.subscriber.state.path = PathBuf::from("/tmp/rhi/state.json");
let contract = sample_runtime_contract();
@@ -467,6 +484,7 @@ mod tests {
let contract = sample_runtime_contract();
let mut settings = minimal_settings();
settings.config.service.logs_dir = contract.canonical_logs_dir.display().to_string();
+ settings.config.logging.output_dir = contract.canonical_logs_dir.clone();
settings.config.subscriber.state.path = contract.canonical_subscriber_state_path.clone();
let report =
diff --git a/src/paths.rs b/src/paths.rs
@@ -17,8 +17,7 @@ const RHI_DEFAULT_SHARED_SECRET_BACKEND: &str = "encrypted_file";
const RHI_ALLOWED_PROFILES: [&str; 3] = ["interactive_user", "service_host", "repo_local"];
const RHI_ALLOWED_SHARED_SECRET_BACKENDS: [&str; 1] = ["encrypted_file"];
const SUBORDINATE_PATH_OVERRIDE_SOURCE: &str = "config_artifact";
-const SUBORDINATE_PATH_OVERRIDE_KEYS: [&str; 2] =
- ["config.service.logs_dir", "config.subscriber.state.path"];
+const SUBORDINATE_PATH_OVERRIDE_KEYS: [&str; 2] = ["logging.output_dir", "subscriber.state.path"];
const MIGRATION_IMPORT_HINT: &str = "stop the worker, inspect this legacy path, then perform an explicit import or manual copy into the canonical destination; rhi will not move it on startup";
#[derive(Debug, Clone, PartialEq, Eq)]