From 6dce4e2ac7dc0108d0cca38fbedc7e0ada39ca70 Mon Sep 17 00:00:00 2001 From: KeelrLeek <156356974+KeelrLeek@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:43:16 -0500 Subject: [PATCH] the freenet layer: adapter, persona and profile services, the contracts bundled as commitments --- Cargo.lock | 471 ++++++++++++- Cargo.toml | 2 + crates/freenet-adapter/Cargo.toml | 21 + crates/freenet-adapter/src/lib.rs | 789 ++++++++++++++++++++++ crates/freenet-adapter/tests/live_node.rs | 95 +++ crates/persona-state/Cargo.toml | 18 + crates/persona-state/src/lib.rs | 371 ++++++++++ src-tauri/Cargo.toml | 4 + src-tauri/assets/identity_delegate.wasm | Bin 0 -> 202026 bytes src-tauri/assets/media_contract.wasm | Bin 0 -> 171945 bytes src-tauri/assets/persona_contract.wasm | Bin 0 -> 184115 bytes src-tauri/src/config.rs | 34 + src-tauri/src/freenet.rs | 355 ++++++++++ src-tauri/src/persona.rs | 395 +++++++++++ src-tauri/src/profile.rs | 786 +++++++++++++++++++++ src-tauri/src/state.rs | 6 + 16 files changed, 3337 insertions(+), 10 deletions(-) create mode 100644 crates/freenet-adapter/Cargo.toml create mode 100644 crates/freenet-adapter/src/lib.rs create mode 100644 crates/freenet-adapter/tests/live_node.rs create mode 100644 crates/persona-state/Cargo.toml create mode 100644 crates/persona-state/src/lib.rs create mode 100644 src-tauri/assets/identity_delegate.wasm create mode 100644 src-tauri/assets/media_contract.wasm create mode 100644 src-tauri/assets/persona_contract.wasm create mode 100644 src-tauri/src/freenet.rs create mode 100644 src-tauri/src/persona.rs create mode 100644 src-tauri/src/profile.rs diff --git a/Cargo.lock b/Cargo.lock index 9db6107..c98cde4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,13 +165,17 @@ version = "1.5.0-alpha" dependencies = [ "audio-formats", "base64 0.22.1", + "bincode", + "bs58", "crc32fast", "flate2", + "freenet-adapter", "image", "keyring", "library", "log", "metadata", + "persona-state", "player", "quick-xml 0.37.5", "realfft", @@ -259,6 +263,21 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -301,6 +320,20 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake3" +version = "1.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +dependencies = [ + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.1", + "digest 0.11.3", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -310,6 +343,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block2" version = "0.6.2" @@ -568,6 +610,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.5" @@ -584,6 +632,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "cookie" version = "0.18.1" @@ -693,6 +753,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -746,6 +815,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "cssparser" version = "0.36.0" @@ -785,6 +863,42 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "darling" version = "0.23.0" @@ -873,6 +987,16 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.5.8" @@ -909,8 +1033,19 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -1046,6 +1181,31 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.16.0" @@ -1183,6 +1343,12 @@ dependencies = [ "log", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "field-offset" version = "0.3.6" @@ -1199,6 +1365,16 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "flatbuffers" +version = "24.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1baf0dbf96932ec9a3038d57900329c015b0bfb7b63d904f3bc27e2b02a096" +dependencies = [ + "bitflags 1.3.2", + "rustc_version", +] + [[package]] name = "flate2" version = "1.1.9" @@ -1272,6 +1448,60 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "freenet-adapter" +version = "1.5.0-alpha" +dependencies = [ + "bs58", + "freenet-stdlib", + "log", + "serde", + "thiserror 2.0.18", + "tokio", + "tokio-tungstenite", +] + +[[package]] +name = "freenet-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26e5c6bee9ffa0e2683bc8b41a7bd9f1e57e7fd49ac4f6ae433e5a82e9006df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "freenet-stdlib" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62aeba7634d1ae5c2d02f78db33ee40442511858275be5be2099d24a13b2559" +dependencies = [ + "bincode", + "blake3", + "bs58", + "byteorder", + "bytes", + "chrono", + "flatbuffers", + "freenet-macros", + "futures", + "js-sys", + "semver", + "serde", + "serde-wasm-bindgen", + "serde_json", + "serde_with", + "thiserror 2.0.18", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "funty" version = "2.0.0" @@ -1793,6 +2023,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.10.1" @@ -2021,7 +2260,7 @@ checksum = "76b0d7d4541def58a37bf8efc559683f21edce7c82f0d866c93ac21f7e098f93" dependencies = [ "attohttpc", "log", - "rand", + "rand 0.8.6", "url", "xmltree", ] @@ -2412,6 +2651,15 @@ dependencies = [ "web_atoms", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "md-5" version = "0.10.6" @@ -2419,7 +2667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", ] [[package]] @@ -2572,6 +2820,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-bigint" version = "0.4.8" @@ -3031,6 +3288,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "persona-state" +version = "1.5.0-alpha" +dependencies = [ + "bincode", + "blake3", + "ed25519-dalek", + "serde", +] + [[package]] name = "phf" version = "0.13.1" @@ -3090,6 +3357,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.33" @@ -3348,8 +3625,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -3359,7 +3646,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3371,6 +3668,15 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -3661,7 +3967,7 @@ dependencies = [ "borsh", "bytes", "num-traits", - "rand", + "rand 0.8.6", "rkyv", "serde", "serde_json", @@ -3910,6 +4216,17 @@ dependencies = [ "typeid", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -4058,6 +4375,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4065,8 +4393,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", ] [[package]] @@ -4075,6 +4412,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.9" @@ -4188,6 +4534,16 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4959,6 +5315,15 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + [[package]] name = "time" version = "0.3.53" @@ -5025,6 +5390,7 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", "socket2", "tokio-macros", @@ -5062,6 +5428,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -5247,9 +5625,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "tracing-core" version = "0.1.36" @@ -5257,6 +5647,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -5297,6 +5717,23 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" +dependencies = [ + "bytes", + "data-encoding", + "http 1.4.2", + "httparse", + "log", + "rand 0.9.5", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + [[package]] name = "typeid" version = "1.0.3" @@ -5393,6 +5830,12 @@ dependencies = [ "url", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8-width" version = "0.1.9" @@ -5423,6 +5866,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "value-bag" version = "1.12.0" @@ -5510,6 +5959,8 @@ dependencies = [ "cfg-if", "once_cell", "rustversion", + "serde", + "serde_json", "wasm-bindgen-macro", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 58973e3..21a6698 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ members = [ "crates/metadata", "crates/library", "crates/audio-formats", + "crates/freenet-adapter", + "crates/persona-state", ] [workspace.package] diff --git a/crates/freenet-adapter/Cargo.toml b/crates/freenet-adapter/Cargo.toml new file mode 100644 index 0000000..197a910 --- /dev/null +++ b/crates/freenet-adapter/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "freenet-adapter" +version.workspace = true +edition.workspace = true + +# The narrow, versioned boundary around a LOCAL Freenet node +# (TODO-Feature-Docs/soulseek-social-chat-and-sharing/, supplement design +# §5.3), hardened by the F0–F7+F2b spike records in research/freenet-*/. +# +# Pins: freenet-stdlib =0.8.5 is what node 0.2.132 speaks (bincode wire); +# tokio-tungstenite must match the stdlib's minor or the stream type the +# WebApi takes will not unify. Bump BOTH together, against a tested node. + +[dependencies] +freenet-stdlib = { version = "=0.8.5", features = ["net"] } +tokio-tungstenite = "0.27.0" +tokio.workspace = true +serde.workspace = true +log.workspace = true +thiserror.workspace = true +bs58 = "0.5" diff --git a/crates/freenet-adapter/src/lib.rs b/crates/freenet-adapter/src/lib.rs new file mode 100644 index 0000000..7580e00 --- /dev/null +++ b/crates/freenet-adapter/src/lib.rs @@ -0,0 +1,789 @@ +//! The FreenetAdapter — SoulStream's ONLY door to a local Freenet node. +//! +//! Everything here follows the supplement design (§5.3) and the rules the +//! F0–F7+F2b spikes recorded (research/freenet-*/RUN-RECORD.md): +//! +//! - **Off by default, kill-switchable.** `enable()` is the only thing that +//! spawns work; `disable()` stops the supervisor, drops the connection, +//! and ends every retry. A missing/stopped/incompatible node must never +//! affect Soulseek or playback — nothing in here is on any audio path. +//! - **The privilege boundary is this crate.** A loopback Freenet API is +//! fully privileged and unauthenticated (F0): whatever can reach it owns +//! the node. The webview therefore gets STATUS ONLY through the Tauri +//! layer — never a node handle, never raw state bytes. +//! - **Detection is cheap and three-valued** (absent / occupied-not-api / +//! compatible), with its own short timeouts: a refused loopback connect +//! costs ~2 s on Windows (F0), so the TCP probe gets 600 ms. A TYPED host +//! error counts as compatible — local mode answers `ConnectedPeers` with +//! "not supported" (F0), so refusals prove the protocol. +//! - **One request in flight per connection.** The stdlib's `WebApi` +//! correlates responses FIFO; the session serializes ops and routes +//! unsolicited `UpdateNotification`s to a bounded event bus (lagging +//! subscribers lose oldest events, honestly, rather than growing queues). +//! - **Write rules from the spikes:** a node refuses the FIRST write to a +//! contract it never held ("auto-fetch triggered", F5) — `update` retries +//! over ~18 s and callers should prime with a GET (`get_then_update`); +//! sequence-bearing states must be read-and-bumped by the caller (F5); +//! a restarted node drops out of update propagation (F2) — services +//! reconcile by relaying their own state after reconnect. +//! - **Redacted diagnostics.** Logs carry ids, lengths and outcomes; never +//! state bytes, never key material. + +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, Mutex as StdMutex}; +use std::time::Duration; + +use freenet_stdlib::client_api::{ + ClientRequest, ContractRequest, ContractResponse, HostResponse, NodeQuery, WebApi, +}; +use freenet_stdlib::prelude::*; +use serde::Serialize; +use tokio::sync::{broadcast, mpsc, oneshot, watch}; +use tokio::time::timeout; + +pub const DEFAULT_WS_PORT: u16 = 7509; + +/// TCP probe budget — see the F0 note about Windows' 2 s refusal cost. +const DETECT_TCP_TIMEOUT: Duration = Duration::from_millis(600); +const DETECT_WS_TIMEOUT: Duration = Duration::from_secs(2); +const DETECT_QUERY_TIMEOUT: Duration = Duration::from_secs(5); +const OP_TIMEOUT: Duration = Duration::from_secs(120); +const PUT_TIMEOUT: Duration = Duration::from_secs(180); +/// "auto-fetch triggered" retry schedule (F5): 6 attempts, 3 s apart. +const AUTOFETCH_RETRIES: u32 = 6; +const AUTOFETCH_BACKOFF: Duration = Duration::from_secs(3); +/// Reconnect backoff while enabled but the node is missing/lost. +const SUPERVISOR_BACKOFF: Duration = Duration::from_secs(5); +const CMD_QUEUE: usize = 32; +const EVENT_QUEUE: usize = 64; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +#[serde(tag = "kind", rename_all = "kebab-case")] +pub enum AdapterStatus { + /// The kill switch position. Nothing runs, nothing retries. + Disabled, + Detecting, + /// Nothing listens on the port. NOT an error — Freenet is optional. + NodeAbsent, + /// Something listens but does not speak the client API. + NodeOccupied, + /// Speaks WebSocket but the protocol exchange failed undecipherably. + NodeIncompatible { detail: String }, + Connected, + /// Connection lost while enabled; the supervisor is retrying. + Lost { detail: String }, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "kind", rename_all = "kebab-case")] +pub enum AdapterEvent { + Status(AdapterStatus), + /// A subscribed contract changed. Ids and lengths only — the webview + /// never receives replicated bytes through the event path. + ContractUpdate { instance: String, update_len: usize }, +} + +#[derive(Debug, thiserror::Error)] +pub enum AdapterError { + #[error("freenet layer is disabled")] + Disabled, + #[error("freenet node is not connected ({0:?})")] + NotConnected(AdapterStatus), + #[error("request timed out")] + Timeout, + #[error("adapter is shutting down")] + ShuttingDown, + #[error("node refused: {0}")] + Node(String), + #[error("{0}")] + Other(String), +} + +type Result = std::result::Result; + +/// What `contract_put`/`update` return so callers can address the instance +/// later without recomputing. +#[derive(Debug, Clone, Serialize)] +pub struct ContractIds { + pub instance: String, + pub code_hash: String, +} + +struct Cmd { + req: ClientRequest<'static>, + reply: oneshot::Sender>, + op_timeout: Duration, +} + +struct Inner { + ws_port: StdMutex, + status: StdMutex, + events: broadcast::Sender, + /// Sender into the LIVE session, if any. + session: StdMutex>>, + /// Kill switch: flipping to false ends the supervisor and its session. + enabled: watch::Sender, + /// Distinguishes supervisor generations so a stale task can't clobber + /// the status of a newer enable(). + generation: AtomicU64, +} + +#[derive(Clone)] +pub struct FreenetAdapter { + inner: Arc, +} + +impl Default for FreenetAdapter { + fn default() -> Self { + let (enabled, _) = watch::channel(false); + let (events, _) = broadcast::channel(EVENT_QUEUE); + Self { + inner: Arc::new(Inner { + ws_port: StdMutex::new(DEFAULT_WS_PORT), + status: StdMutex::new(AdapterStatus::Disabled), + events, + session: StdMutex::new(None), + enabled, + generation: AtomicU64::new(0), + }), + } + } +} + +/// Spawn on the caller's tokio runtime when there is one (async commands, +/// tests), else on a runtime the adapter owns. `enable()` is reached from +/// Tauri's event-loop thread — the setup hook, sync commands — where a bare +/// `tokio::spawn` is a non-unwinding panic that takes the whole process down +/// (0xc0000409, seen live 2026-09-02 on the first toggle of the switch). +fn spawn_anywhere(fut: F) +where + F: std::future::Future + Send + 'static, +{ + match tokio::runtime::Handle::try_current() { + Ok(handle) => { + handle.spawn(fut); + } + Err(_) => { + static RT: std::sync::OnceLock = std::sync::OnceLock::new(); + let rt = RT.get_or_init(|| { + tokio::runtime::Builder::new_multi_thread() + .worker_threads(2) + .thread_name("freenet-adapter") + .enable_all() + .build() + .expect("freenet adapter runtime") + }); + rt.spawn(fut); + } + } +} + + +impl FreenetAdapter { + pub fn set_ws_port(&self, port: u16) { + *self.inner.ws_port.lock().unwrap() = port; + } + + pub fn ws_port(&self) -> u16 { + *self.inner.ws_port.lock().unwrap() + } + + pub fn status(&self) -> AdapterStatus { + self.inner.status.lock().unwrap().clone() + } + + pub fn is_enabled(&self) -> bool { + *self.inner.enabled.borrow() + } + + pub fn subscribe(&self) -> broadcast::Receiver { + self.inner.events.subscribe() + } + + fn set_status(&self, generation: u64, s: AdapterStatus) { + if self.inner.generation.load(Ordering::SeqCst) != generation { + return; // a newer enable()/disable() owns the status now + } + *self.inner.status.lock().unwrap() = s.clone(); + let _ = self.inner.events.send(AdapterEvent::Status(s)); + } + + /// Turn the layer on: spawns the supervisor, which detects, connects, + /// and reconnects with backoff until `disable()`. + pub fn enable(&self) { + if self.is_enabled() { + return; + } + let generation = self.inner.generation.fetch_add(1, Ordering::SeqCst) + 1; + self.inner.enabled.send_replace(true); + let this = self.clone(); + spawn_anywhere(async move { + this.supervisor(generation).await; + }); + log::info!("freenet adapter enabled (gen {generation})"); + } + + /// The kill switch. Ends the supervisor, drops the session, stops every + /// retry. Callers see `Disabled` errors immediately. + pub fn disable(&self) { + let generation = self.inner.generation.fetch_add(1, Ordering::SeqCst) + 1; + self.inner.enabled.send_replace(false); + *self.inner.session.lock().unwrap() = None; + *self.inner.status.lock().unwrap() = AdapterStatus::Disabled; + let _ = self.inner.events.send(AdapterEvent::Status(AdapterStatus::Disabled)); + log::info!("freenet adapter disabled (gen {generation})"); + } + + // ------------------------------------------------------------ detect + + /// Three-valued node detection. Usable while disabled (it opens its own + /// short-lived connection and touches no adapter state). + pub async fn detect(&self) -> AdapterStatus { + let port = self.ws_port(); + let addr = format!("127.0.0.1:{port}"); + match timeout(DETECT_TCP_TIMEOUT, tokio::net::TcpStream::connect(&addr)).await { + Err(_) | Ok(Err(_)) => return AdapterStatus::NodeAbsent, + Ok(Ok(stream)) => drop(stream), + } + let mut api = match timeout(DETECT_WS_TIMEOUT, connect_ws(port)).await { + Err(_) => return AdapterStatus::NodeOccupied, + Ok(Err(_)) => return AdapterStatus::NodeOccupied, + Ok(Ok(api)) => api, + }; + if api + .send(ClientRequest::NodeQueries(NodeQuery::ConnectedPeers)) + .await + .is_err() + { + return AdapterStatus::NodeIncompatible { detail: "send failed".into() }; + } + match timeout(DETECT_QUERY_TIMEOUT, api.recv()).await { + Ok(Ok(_)) => AdapterStatus::Connected, + // A decoded, typed refusal IS protocol proof (local mode answers + // ConnectedPeers with "not supported" — F0). + Ok(Err(e)) if e.to_string().contains("not supported") => AdapterStatus::Connected, + Ok(Err(e)) => AdapterStatus::NodeIncompatible { detail: truncate(&e.to_string(), 120) }, + Err(_) => AdapterStatus::NodeIncompatible { detail: "no reply to health query".into() }, + } + } + + // ------------------------------------------------------------ supervisor + + async fn supervisor(&self, generation: u64) { + let mut enabled_rx = self.inner.enabled.subscribe(); + loop { + if self.inner.generation.load(Ordering::SeqCst) != generation || !*enabled_rx.borrow() { + return; + } + self.set_status(generation, AdapterStatus::Detecting); + let detected = self.detect().await; + match detected { + AdapterStatus::Connected => {} + other => { + self.set_status(generation, other); + if wait_or_disabled(&mut enabled_rx, SUPERVISOR_BACKOFF).await { + return; + } + continue; + } + } + let port = self.ws_port(); + let api = match timeout(DETECT_WS_TIMEOUT, connect_ws(port)).await { + Ok(Ok(api)) => api, + _ => { + self.set_status(generation, AdapterStatus::Lost { detail: "connect failed".into() }); + if wait_or_disabled(&mut enabled_rx, SUPERVISOR_BACKOFF).await { + return; + } + continue; + } + }; + let (tx, rx) = mpsc::channel::(CMD_QUEUE); + *self.inner.session.lock().unwrap() = Some(tx); + self.set_status(generation, AdapterStatus::Connected); + log::info!("freenet adapter connected to 127.0.0.1:{port}"); + let reason = self.run_session(api, rx, &mut enabled_rx).await; + *self.inner.session.lock().unwrap() = None; + if self.inner.generation.load(Ordering::SeqCst) != generation || !*enabled_rx.borrow() { + return; + } + self.set_status(generation, AdapterStatus::Lost { detail: truncate(&reason, 120) }); + log::warn!("freenet session ended: {}", truncate(&reason, 120)); + if wait_or_disabled(&mut enabled_rx, SUPERVISOR_BACKOFF).await { + return; + } + } + } + + /// One connection's lifetime. STRICTLY one request in flight (the wire + /// correlates FIFO); notifications stream out between and during ops. + async fn run_session( + &self, + mut api: WebApi, + mut rx: mpsc::Receiver, + enabled_rx: &mut watch::Receiver, + ) -> String { + loop { + tokio::select! { + changed = enabled_rx.changed() => { + if changed.is_err() || !*enabled_rx.borrow() { + return "disabled".into(); + } + } + maybe_cmd = rx.recv() => { + let Some(cmd) = maybe_cmd else { return "handle dropped".into() }; + if api.send(cmd.req).await.is_err() { + let _ = cmd.reply.send(Err(AdapterError::Node("send failed".into()))); + return "send failed".into(); + } + // Await THIS op's response; unsolicited notifications + // arriving in between are forwarded, not misdelivered. + let deadline = tokio::time::Instant::now() + cmd.op_timeout; + loop { + let left = deadline.saturating_duration_since(tokio::time::Instant::now()); + if left.is_zero() { + let _ = cmd.reply.send(Err(AdapterError::Timeout)); + break; + } + match timeout(left, api.recv()).await { + Err(_) => { + let _ = cmd.reply.send(Err(AdapterError::Timeout)); + break; + } + Ok(Err(e)) => { + let _ = cmd.reply.send(Err(AdapterError::Node(e.to_string()))); + break; + } + Ok(Ok(HostResponse::ContractResponse( + ContractResponse::UpdateNotification { key, update }, + ))) => { + self.forward_notification(&key, &update); + continue; + } + Ok(Ok(resp)) => { + let _ = cmd.reply.send(Ok(resp)); + break; + } + } + } + } + streamed = api.recv() => { + // Idle traffic: subscription notifications, or the end + // of the connection. + match streamed { + Ok(HostResponse::ContractResponse( + ContractResponse::UpdateNotification { key, update }, + )) => self.forward_notification(&key, &update), + Ok(_) => { /* stray late response; correlation is FIFO, drop */ } + Err(e) => return e.to_string(), + } + } + } + } + } + + fn forward_notification(&self, key: &ContractKey, update: &UpdateData<'static>) { + let len = match update { + UpdateData::State(s) => s.as_ref().len(), + UpdateData::Delta(d) => d.as_ref().len(), + UpdateData::StateAndDelta { state, delta } => state.as_ref().len() + delta.as_ref().len(), + _ => 0, + }; + // Bounded broadcast: lagging receivers lose oldest events. Honest. + let _ = self.inner.events.send(AdapterEvent::ContractUpdate { + instance: key.id().encode(), + update_len: len, + }); + } + + // ------------------------------------------------------------ ops + + async fn request(&self, req: ClientRequest<'static>, op_timeout: Duration) -> Result { + if !self.is_enabled() { + return Err(AdapterError::Disabled); + } + let tx = { + let guard = self.inner.session.lock().unwrap(); + guard.clone() + }; + let Some(tx) = tx else { + return Err(AdapterError::NotConnected(self.status())); + }; + let (reply_tx, reply_rx) = oneshot::channel(); + tx.send(Cmd { req, reply: reply_tx, op_timeout }) + .await + .map_err(|_| AdapterError::ShuttingDown)?; + reply_rx.await.map_err(|_| AdapterError::ShuttingDown)? + } + + fn container(code: Vec, params: &[u8]) -> (ContractContainer, ContractKey) { + let params = Parameters::from(params.to_vec()).into_owned(); + let c = ContractContainer::Wasm(ContractWasmAPIVersion::V1(WrappedContract::new( + Arc::new(ContractCode::from(code)), + params, + ))); + let k = c.key(); + (c, k) + } + + /// Compute the ids a (code, params) pair addresses — no network. + pub fn contract_ids(code: Vec, params: &[u8]) -> ContractIds { + let (_, key) = Self::container(code, params); + ContractIds { + instance: key.id().encode(), + code_hash: key.encoded_code_hash(), + } + } + + pub async fn contract_put( + &self, + code: Vec, + params: &[u8], + state: Vec, + subscribe: bool, + ) -> Result { + let (container, key) = Self::container(code, params); + let ids = ContractIds { + instance: key.id().encode(), + code_hash: key.encoded_code_hash(), + }; + let resp = self + .request( + ContractRequest::Put { + contract: container, + state: WrappedState::new(state), + related_contracts: RelatedContracts::new(), + subscribe, + blocking_subscribe: false, + } + .into(), + PUT_TIMEOUT, + ) + .await?; + match resp { + HostResponse::ContractResponse(ContractResponse::PutResponse { .. }) => Ok(ids), + other => Err(unexpected("PutResponse", &other)), + } + } + + pub async fn contract_get( + &self, + instance_b58: &str, + subscribe: bool, + ) -> Result> { + let id = parse_instance(instance_b58)?; + let resp = self + .request( + ContractRequest::Get { + key: id, + return_contract_code: false, + subscribe, + blocking_subscribe: false, + } + .into(), + OP_TIMEOUT, + ) + .await + // Depending on version, a never-put contract comes back either + // as a typed NotFound or as an error frame "missing contract: + // " (observed on 0.2.132 local mode). Fold both into one + // shape so services can match on "contract not found" alone. + .map_err(|e| match e { + AdapterError::Node(msg) if msg.contains("missing contract") => { + AdapterError::Node("contract not found".into()) + } + e => e, + })?; + match resp { + HostResponse::ContractResponse(ContractResponse::GetResponse { state, .. }) => { + Ok(state.to_vec()) + } + HostResponse::ContractResponse(ContractResponse::NotFound { .. }) => { + Err(AdapterError::Node("contract not found".into())) + } + other => Err(unexpected("GetResponse", &other)), + } + } + + pub async fn contract_subscribe(&self, instance_b58: &str) -> Result { + let id = parse_instance(instance_b58)?; + let resp = self + .request( + ContractRequest::Subscribe { key: id, summary: None }.into(), + OP_TIMEOUT, + ) + .await?; + match resp { + HostResponse::ContractResponse(ContractResponse::SubscribeResponse { + subscribed, + .. + }) => Ok(subscribed), + other => Err(unexpected("SubscribeResponse", &other)), + } + } + + /// UPDATE with the recorded first-write behavior handled: a node that + /// never held the contract answers "auto-fetch triggered" and asks the + /// client to retry; we do, on the spike's schedule. Returns the + /// post-merge summary bytes. + pub async fn contract_update( + &self, + code: Vec, + params: &[u8], + delta: Vec, + ) -> Result> { + let (_, key) = Self::container(code, params); + let mut last: Option = None; + for attempt in 0..AUTOFETCH_RETRIES { + if attempt > 0 { + tokio::time::sleep(AUTOFETCH_BACKOFF).await; + if !self.is_enabled() { + return Err(AdapterError::Disabled); // kill switch ends retries + } + } + let resp = self + .request( + ContractRequest::Update { + key, + data: UpdateData::Delta(StateDelta::from(delta.clone())), + } + .into(), + OP_TIMEOUT, + ) + .await; + match resp { + Ok(HostResponse::ContractResponse(ContractResponse::UpdateResponse { + summary, + .. + })) => return Ok(summary.as_ref().to_vec()), + Ok(other) => return Err(unexpected("UpdateResponse", &other)), + Err(AdapterError::Node(msg)) if msg.contains("auto-fetch triggered") => { + log::info!( + "freenet: first-write priming on attempt {attempt} (auto-fetch in flight)" + ); + last = Some(AdapterError::Node(msg)); + } + Err(e) => return Err(e), + } + } + Err(last.unwrap_or(AdapterError::Timeout)) + } + + /// The reliable first-write recipe from F5: one GET primes code+state on + /// this node, then the update applies. Use for a contract this node may + /// never have held. + pub async fn get_then_update( + &self, + code: Vec, + params: &[u8], + delta: Vec, + ) -> Result> { + let ids = Self::contract_ids(code.clone(), params); + let _ = self.contract_get(&ids.instance, false).await; // prime; absence is fine + self.contract_update(code, params, delta).await + } + + // ------------------------------------------------------------ delegates + + fn delegate_container(code: Vec, params: &[u8]) -> (DelegateContainer, DelegateKey) { + let params = Parameters::from(params.to_vec()).into_owned(); + let dc = DelegateCode::from(code); + let d = Delegate::from((&dc, ¶ms)); + let c = DelegateContainer::Wasm(DelegateWasmAPIVersion::V1(d)); + let k = c.key().clone(); + (c, k) + } + + /// Compute the delegate key a (code, params) pair addresses — no + /// network. Lets services pin and log their delegate generation. + pub fn delegate_key_b58(code: Vec, params: &[u8]) -> String { + let (_, key) = Self::delegate_container(code, params); + bs58::encode(key.bytes()).into_string() + } + + /// Register (idempotent per node) and return the delegate key (b58). + /// `cipher`/`nonce` are legacy fields the node ignores (core#4140). + pub async fn delegate_register(&self, code: Vec, params: &[u8]) -> Result { + use freenet_stdlib::client_api::DelegateRequest; + let (container, key) = Self::delegate_container(code, params); + let resp = self + .request( + ClientRequest::DelegateOp(DelegateRequest::RegisterDelegate { + delegate: container, + cipher: [0u8; 32], + nonce: [0u8; 24], + }), + OP_TIMEOUT, + ) + .await?; + match resp { + HostResponse::DelegateResponse { .. } => Ok(bs58::encode(key.bytes()).into_string()), + other => Err(unexpected("DelegateResponse", &other)), + } + } + + /// One application message in, the delegate's app-message reply out. + /// NOTE (F1): migration across delegate code generations must be + /// verified by reading state back — `RegisterDelegateWithPredecessors` + /// silently copies nothing in 0.2.132 (GHSA-824h-7x5x-wfmf). + pub async fn delegate_message( + &self, + code: Vec, + params: &[u8], + payload: Vec, + ) -> Result> { + use freenet_stdlib::client_api::DelegateRequest; + let (_, key) = Self::delegate_container(code.clone(), params); + let params_owned = Parameters::from(params.to_vec()).into_owned(); + let resp = self + .request( + ClientRequest::DelegateOp(DelegateRequest::ApplicationMessages { + key, + params: params_owned, + inbound: vec![InboundDelegateMsg::ApplicationMessage( + ApplicationMessage::new(payload), + )], + }), + OP_TIMEOUT, + ) + .await?; + match resp { + HostResponse::DelegateResponse { values, .. } => values + .into_iter() + .find_map(|v| match v { + OutboundDelegateMsg::ApplicationMessage(m) => Some(m.payload), + _ => None, + }) + .ok_or_else(|| AdapterError::Node("no app message in delegate reply".into())), + other => Err(unexpected("DelegateResponse", &other)), + } + } +} + +// ------------------------------------------------------------------ helpers + +async fn connect_ws(port: u16) -> std::result::Result { + let uri = format!("ws://127.0.0.1:{port}/v1/contract/command?encodingProtocol=native"); + let cfg = tokio_tungstenite::tungstenite::protocol::WebSocketConfig::default() + .max_message_size(Some(100 * 1024 * 1024)) + .max_frame_size(Some(16 * 1024 * 1024)); + let (stream, _) = tokio_tungstenite::connect_async_with_config(&uri, Some(cfg), false) + .await + .map_err(|e| e.to_string())?; + Ok(WebApi::start(stream)) +} + +/// Wait out a backoff, returning true if the adapter was disabled meanwhile. +async fn wait_or_disabled(enabled_rx: &mut watch::Receiver, dur: Duration) -> bool { + tokio::select! { + _ = tokio::time::sleep(dur) => !*enabled_rx.borrow(), + changed = enabled_rx.changed() => changed.is_err() || !*enabled_rx.borrow(), + } +} + +fn parse_instance(b58: &str) -> Result { + ContractInstanceId::try_from(b58.to_string()) + .map_err(|e| AdapterError::Other(format!("bad instance id: {e}"))) +} + +fn unexpected(wanted: &str, got: &HostResponse) -> AdapterError { + // Display, not Debug: HostResponse Display is summary-shaped and does + // not dump state bytes. + AdapterError::Node(format!("expected {wanted}, got {}", truncate(&got.to_string(), 120))) +} + +fn truncate(s: &str, n: usize) -> String { + if s.len() <= n { + return s.to_string(); + } + let mut cut = n; + while cut > 0 && !s.is_char_boundary(cut) { + cut -= 1; + } + format!("{}…", &s[..cut]) +} + +// ------------------------------------------------------------------ tests + +#[cfg(test)] +mod tests { + use super::*; + + /// The event-loop path: no tokio context at all. Must not panic, must + /// flip enabled, and disable() must still end it. + #[test] + fn enable_works_outside_any_runtime() { + std::thread::spawn(|| { + assert!(tokio::runtime::Handle::try_current().is_err()); + let a = FreenetAdapter::default(); + a.enable(); + assert!(a.is_enabled()); + std::thread::sleep(std::time::Duration::from_millis(300)); + a.disable(); + assert!(!a.is_enabled()); + assert_eq!(a.status(), AdapterStatus::Disabled); + }) + .join() + .expect("no panic on the runtime-less path"); + } + + #[tokio::test] + async fn disabled_is_the_default_and_ops_refuse() { + let a = FreenetAdapter::default(); + assert_eq!(a.status(), AdapterStatus::Disabled); + assert!(!a.is_enabled()); + let err = a.contract_get("11111111111111111111111111111111", false).await; + assert!(matches!(err, Err(AdapterError::Disabled))); + } + + #[tokio::test] + async fn detect_absent_on_closed_port() { + let a = FreenetAdapter::default(); + a.set_ws_port(1); // nothing listens on port 1 + assert_eq!(a.detect().await, AdapterStatus::NodeAbsent); + } + + #[tokio::test] + async fn detect_occupied_on_non_api_listener() { + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + tokio::spawn(async move { + loop { + let Ok((mut sock, _)) = listener.accept().await else { break }; + use tokio::io::AsyncWriteExt; + // Answer like a confused HTTP server, then hang up. + let _ = sock.write_all(b"HTTP/1.1 404 Not Found\r\n\r\n").await; + } + }); + let a = FreenetAdapter::default(); + a.set_ws_port(port); + assert_eq!(a.detect().await, AdapterStatus::NodeOccupied); + } + + #[tokio::test] + async fn kill_switch_ends_everything() { + let a = FreenetAdapter::default(); + a.set_ws_port(1); + a.enable(); + assert!(a.is_enabled()); + // Give the supervisor a moment to enter its loop, then kill it. + tokio::time::sleep(Duration::from_millis(50)).await; + a.disable(); + assert_eq!(a.status(), AdapterStatus::Disabled); + assert!(!a.is_enabled()); + let err = a.contract_get("11111111111111111111111111111111", false).await; + assert!(matches!(err, Err(AdapterError::Disabled))); + // A stale supervisor tick must not resurrect a status. + tokio::time::sleep(Duration::from_millis(200)).await; + assert_eq!(a.status(), AdapterStatus::Disabled); + } + + #[tokio::test] + async fn contract_ids_are_deterministic_offline() { + let code = vec![0u8, 1, 2, 3]; + let a = FreenetAdapter::contract_ids(code.clone(), b"params"); + let b = FreenetAdapter::contract_ids(code, b"params"); + assert_eq!(a.instance, b.instance); + assert_eq!(a.code_hash, b.code_hash); + } +} diff --git a/crates/freenet-adapter/tests/live_node.rs b/crates/freenet-adapter/tests/live_node.rs new file mode 100644 index 0000000..6237e57 --- /dev/null +++ b/crates/freenet-adapter/tests/live_node.rs @@ -0,0 +1,95 @@ +//! Live integration against a REAL local Freenet node — the house pattern +//! (`#[ignore]`d corpus tests inside the crate, run on demand): +//! +//! 1. start a node: freenet local local --config-dir --data-dir +//! 2. set SOULSTREAM_F0_WASM to a contract wasm (the F0 spike's +//! research/freenet-f0/f0-contract build works verbatim) +//! 3. cargo test -p freenet-adapter --release -- --ignored +//! +//! Exercises the full adapter loop: detect → enable → put → get → +//! subscribe → update (with the first-write priming path) → notification +//! event → kill switch mid-life. + +use freenet_adapter::{AdapterEvent, AdapterStatus, FreenetAdapter}; +use std::time::Duration; + +fn wasm() -> Option> { + let path = std::env::var("SOULSTREAM_F0_WASM").ok()?; + std::fs::read(path).ok() +} + +#[tokio::test] +#[ignore = "needs a local freenet node on 7509 and SOULSTREAM_F0_WASM"] +async fn full_loop_against_live_node() { + let Some(code) = wasm() else { + panic!("set SOULSTREAM_F0_WASM to a contract wasm path"); + }; + let a = FreenetAdapter::default(); + + // Detection first — a wrong environment should fail here, loudly. + let detected = a.detect().await; + assert_eq!(detected, AdapterStatus::Connected, "node not reachable: {detected:?}"); + + a.enable(); + // Wait for the supervisor to connect. + let mut tries = 0; + while a.status() != AdapterStatus::Connected { + tokio::time::sleep(Duration::from_millis(200)).await; + tries += 1; + assert!(tries < 50, "supervisor never connected: {:?}", a.status()); + } + + // A fresh instance per run: params carry a nonce. + let params = format!("adapter-live-{}", std::process::id()).into_bytes(); + let ids = FreenetAdapter::contract_ids(code.clone(), ¶ms); + + // PUT initial state. + let put_ids = a + .contract_put(code.clone(), ¶ms, br#"["alpha"]"#.to_vec(), false) + .await + .expect("put"); + assert_eq!(put_ids.instance, ids.instance); + + // GET it back. + let state = a.contract_get(&ids.instance, false).await.expect("get"); + assert_eq!(state, br#"["alpha"]"#); + + // SUBSCRIBE, then watch for the update notification through the + // adapter's bounded event bus. + let mut events = a.subscribe(); + assert!(a.contract_subscribe(&ids.instance).await.expect("subscribe")); + + // UPDATE via the primed path (exercises get_then_update's shape even + // though this node already holds the contract). + let summary = a + .get_then_update(code.clone(), ¶ms, br#"["beta"]"#.to_vec()) + .await + .expect("update"); + assert!(!summary.is_empty(), "update summary should carry bytes"); + + // The merged state must be the union. + let state = a.contract_get(&ids.instance, false).await.expect("get2"); + assert_eq!(state, br#"["alpha","beta"]"#); + + // The notification should have crossed the event bus (ids only). + let deadline = tokio::time::Instant::now() + Duration::from_secs(10); + let mut saw_update = false; + while tokio::time::Instant::now() < deadline { + match tokio::time::timeout(Duration::from_secs(1), events.recv()).await { + Ok(Ok(AdapterEvent::ContractUpdate { instance, .. })) if instance == ids.instance => { + saw_update = true; + break; + } + Ok(Ok(_)) => continue, + Ok(Err(_)) => break, + Err(_) => continue, + } + } + assert!(saw_update, "no ContractUpdate event reached the bus"); + + // Kill switch mid-life: immediate, and ops refuse afterwards. + a.disable(); + assert_eq!(a.status(), AdapterStatus::Disabled); + let err = a.contract_get(&ids.instance, false).await; + assert!(matches!(err, Err(freenet_adapter::AdapterError::Disabled))); +} diff --git a/crates/persona-state/Cargo.toml b/crates/persona-state/Cargo.toml new file mode 100644 index 0000000..a57de67 --- /dev/null +++ b/crates/persona-state/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "persona-state" +version.workspace = true +edition.workspace = true + +# The persona profile + avatar-asset state model — the byte-exact shapes +# the bundled persona/media contract wasms validate (their sources are the +# F2/F2b spike crates; these definitions must stay bincode-identical to +# them, field by field, or published state stops verifying). + +[dependencies] +serde.workspace = true +bincode = "1" +ed25519-dalek = { version = "2", default-features = false, features = ["alloc"] } +blake3 = "1" + +[dev-dependencies] +ed25519-dalek = { version = "2", features = ["rand_core"] } diff --git a/crates/persona-state/src/lib.rs b/crates/persona-state/src/lib.rs new file mode 100644 index 0000000..6e6e0c5 --- /dev/null +++ b/crates/persona-state/src/lib.rs @@ -0,0 +1,371 @@ +//! Persona profile + avatar-asset state — the shapes the bundled Freenet +//! contracts validate. +//! +//! BYTE-COMPATIBILITY IS THE CONTRACT. `ProfileState` and `MediaAssetV1` +//! must stay bincode-identical (field order, types, sig-body layouts) to +//! the wasm bundled in `src-tauri/assets/` (built from the F2/F2b spike +//! sources, keys pinned by tests there). Change anything here and every +//! published profile stops verifying — that is a migration event. +//! +//! Two signing conventions coexist under `soulstream.profile/v1` (an F2b +//! record): PROFILES sign their RAW sig-body; ASSETS sign blake3(sig-body). +//! `profile_sign_payload` / `asset_sign_payload` return exactly what the +//! identity delegate must be handed for each. + +use ed25519_dalek::{Signature, Verifier, VerifyingKey}; +use serde::{Deserialize, Serialize}; + +pub const SCHEMA_VERSION: u32 = 1; +pub const SIGN_DOMAIN: &str = "soulstream.profile/v1"; + +pub const PROFILE_PARAMS_FAMILY: &[u8] = b"soulstream.persona.v1"; +pub const MEDIA_PARAMS_FAMILY: &[u8] = b"soulstream.media.v1"; + +pub const MAX_PROFILE_BYTES: usize = 4 * 1024; +pub const MAX_NAME_BYTES: usize = 64; +pub const MAX_BIO_BYTES: usize = 280; + +/// v1 avatar rendition: one square PNG. +pub const V1_MEDIA_TYPE: &str = "image/png"; +pub const V1_DIMENSION: u32 = 256; +pub const MAX_MEDIA_BYTES: usize = 96 * 1024; +pub const MAX_MEDIA_STATE_BYTES: usize = 128 * 1024; + +// ------------------------------------------------------------------ profile + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct MediaRefV1 { + pub content_hash: [u8; 32], + pub media_type: String, + pub byte_length: u32, + pub width: u16, + pub height: u16, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ProfileState { + pub schema_version: u32, + pub owner: [u8; 32], + pub sequence: u64, + pub display_name: String, + pub bio: String, + pub avatar: Option, + pub sig: Vec, +} + +#[derive(Serialize)] +struct ProfileSigBody<'a> { + schema_version: u32, + owner: &'a [u8; 32], + sequence: u64, + display_name: &'a str, + bio: &'a str, + avatar: &'a Option, +} + +/// What the delegate signs for a profile: the RAW sig-body (F2 convention). +pub fn profile_sign_payload(p: &ProfileState) -> Vec { + bincode::serialize(&ProfileSigBody { + schema_version: p.schema_version, + owner: &p.owner, + sequence: p.sequence, + display_name: &p.display_name, + bio: &p.bio, + avatar: &p.avatar, + }) + .expect("serializes") +} + +fn signable(domain: &str, payload: &[u8]) -> Vec { + let mut msg = Vec::new(); + msg.extend_from_slice(b"soulstream.sig.v1"); + msg.push(0); + msg.extend_from_slice(domain.as_bytes()); + msg.push(0); + msg.extend_from_slice(blake3::hash(payload).as_bytes()); + msg +} + +pub fn verify_sig(public: &[u8; 32], payload: &[u8], sig: &[u8]) -> bool { + let Ok(vk) = VerifyingKey::from_bytes(public) else { return false }; + let Ok(sig) = Signature::from_slice(sig) else { return false }; + vk.verify(&signable(SIGN_DOMAIN, payload), &sig).is_ok() +} + +pub fn make_profile_params(owner: &[u8; 32]) -> Vec { + let mut p = Vec::with_capacity(PROFILE_PARAMS_FAMILY.len() + 32); + p.extend_from_slice(PROFILE_PARAMS_FAMILY); + p.extend_from_slice(owner); + p +} + +#[derive(Debug, PartialEq, Eq)] +pub enum ProfileInvalid { + Oversized(usize), + Malformed, + WrongSchema(u32), + WrongOwner, + NameTooLong(usize), + BioTooLong(usize), + AvatarUnbounded, + BadSignature, +} + +impl core::fmt::Display for ProfileInvalid { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + ProfileInvalid::Oversized(n) => write!(f, "profile {n} bytes over cap {MAX_PROFILE_BYTES}"), + ProfileInvalid::Malformed => write!(f, "bytes do not parse as a profile"), + ProfileInvalid::WrongSchema(v) => write!(f, "unknown profile schema {v}"), + ProfileInvalid::WrongOwner => write!(f, "profile owner differs from the address owner"), + ProfileInvalid::NameTooLong(n) => write!(f, "display name {n} bytes over cap {MAX_NAME_BYTES}"), + ProfileInvalid::BioTooLong(n) => write!(f, "bio {n} bytes over cap {MAX_BIO_BYTES}"), + ProfileInvalid::AvatarUnbounded => write!(f, "avatar reference outside the v1 bounds"), + ProfileInvalid::BadSignature => write!(f, "owner signature does not verify"), + } + } +} + +fn avatar_bounded(r: &MediaRefV1) -> bool { + r.media_type == V1_MEDIA_TYPE + && r.byte_length as usize <= MAX_MEDIA_BYTES + && r.width as u32 == V1_DIMENSION + && r.height as u32 == V1_DIMENSION +} + +/// Gen-2 validation (avatar-accepting) — the generation the bundled +/// contract enforces. Gen-1 states (avatar=None) validate identically. +pub fn validate_profile(owner: &[u8; 32], bytes: &[u8]) -> Result { + if bytes.len() > MAX_PROFILE_BYTES { + return Err(ProfileInvalid::Oversized(bytes.len())); + } + let p: ProfileState = bincode::deserialize(bytes).map_err(|_| ProfileInvalid::Malformed)?; + if p.schema_version != SCHEMA_VERSION { + return Err(ProfileInvalid::WrongSchema(p.schema_version)); + } + if &p.owner != owner { + return Err(ProfileInvalid::WrongOwner); + } + if p.display_name.len() > MAX_NAME_BYTES { + return Err(ProfileInvalid::NameTooLong(p.display_name.len())); + } + if p.bio.len() > MAX_BIO_BYTES { + return Err(ProfileInvalid::BioTooLong(p.bio.len())); + } + if let Some(r) = &p.avatar { + if !avatar_bounded(r) { + return Err(ProfileInvalid::AvatarUnbounded); + } + } + if !verify_sig(&p.owner, &profile_sign_payload(&p), &p.sig) { + return Err(ProfileInvalid::BadSignature); + } + Ok(p) +} + +// ------------------------------------------------------------------ asset + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct MediaAssetV1 { + pub schema_version: u32, + pub owner: [u8; 32], + pub asset_id: [u8; 16], + pub revision: u32, + pub media_type: String, + pub width: u32, + pub height: u32, + pub sanitized_static_bytes: Vec, + pub sig: Vec, +} + +#[derive(Serialize)] +struct AssetSigBody<'a> { + schema_version: u32, + owner: &'a [u8; 32], + asset_id: &'a [u8; 16], + revision: u32, + media_type: &'a str, + width: u32, + height: u32, + content_hash: &'a [u8; 32], +} + +fn asset_sig_body(a: &MediaAssetV1) -> Vec { + let content_hash = *blake3::hash(&a.sanitized_static_bytes).as_bytes(); + bincode::serialize(&AssetSigBody { + schema_version: a.schema_version, + owner: &a.owner, + asset_id: &a.asset_id, + revision: a.revision, + media_type: &a.media_type, + width: a.width, + height: a.height, + content_hash: &content_hash, + }) + .expect("serializes") +} + +/// What the delegate signs for an asset: blake3(sig-body) — 32 bytes. +pub fn asset_sign_payload(a: &MediaAssetV1) -> Vec { + blake3::hash(&asset_sig_body(a)).as_bytes().to_vec() +} + +pub fn make_media_params(owner: &[u8; 32], content_hash: &[u8; 32]) -> Vec { + let mut p = Vec::with_capacity(MEDIA_PARAMS_FAMILY.len() + 64); + p.extend_from_slice(MEDIA_PARAMS_FAMILY); + p.extend_from_slice(owner); + p.extend_from_slice(content_hash); + p +} + +#[derive(Debug, PartialEq, Eq)] +pub enum AssetInvalid { + Oversized(usize), + HashMismatch, + Malformed, + WrongSchema(u32), + WrongOwner, + WrongType(String), + WrongDimensions(u32, u32), + BytesOverBudget(usize), + BadSignature, +} + +impl core::fmt::Display for AssetInvalid { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + AssetInvalid::Oversized(n) => write!(f, "asset state {n} bytes over gate {MAX_MEDIA_STATE_BYTES}"), + AssetInvalid::HashMismatch => write!(f, "bytes do not hash to the referenced content hash"), + AssetInvalid::Malformed => write!(f, "bytes do not parse as a media asset"), + AssetInvalid::WrongSchema(v) => write!(f, "unknown media schema {v}"), + AssetInvalid::WrongOwner => write!(f, "asset owner differs from the reference owner"), + AssetInvalid::WrongType(t) => write!(f, "media type {t:?} not accepted (v1: image/png)"), + AssetInvalid::WrongDimensions(w, h) => write!(f, "declared {w}x{h} is not the 256x256 rendition"), + AssetInvalid::BytesOverBudget(n) => write!(f, "{n} media bytes over the {MAX_MEDIA_BYTES} budget"), + AssetInvalid::BadSignature => write!(f, "owner signature does not verify"), + } + } +} + +/// Structural verification of a fetched asset against a signed reference — +/// everything that must pass BEFORE any image decoding happens. +pub fn validate_asset( + owner: &[u8; 32], + content_hash: &[u8; 32], + state_bytes: &[u8], +) -> Result { + if state_bytes.len() > MAX_MEDIA_STATE_BYTES { + return Err(AssetInvalid::Oversized(state_bytes.len())); + } + let a: MediaAssetV1 = bincode::deserialize(state_bytes).map_err(|_| AssetInvalid::Malformed)?; + if a.schema_version != SCHEMA_VERSION { + return Err(AssetInvalid::WrongSchema(a.schema_version)); + } + if &a.owner != owner { + return Err(AssetInvalid::WrongOwner); + } + if a.sanitized_static_bytes.len() > MAX_MEDIA_BYTES { + return Err(AssetInvalid::BytesOverBudget(a.sanitized_static_bytes.len())); + } + if blake3::hash(&a.sanitized_static_bytes).as_bytes() != content_hash { + return Err(AssetInvalid::HashMismatch); + } + if a.media_type != V1_MEDIA_TYPE { + return Err(AssetInvalid::WrongType(a.media_type.clone())); + } + if a.width != V1_DIMENSION || a.height != V1_DIMENSION { + return Err(AssetInvalid::WrongDimensions(a.width, a.height)); + } + if !verify_sig(owner, &asset_sign_payload(&a), &a.sig) { + return Err(AssetInvalid::BadSignature); + } + Ok(a) +} + +// ------------------------------------------------------------------ tests + +#[cfg(test)] +mod tests { + use super::*; + use ed25519_dalek::{Signer, SigningKey}; + + fn kp(seed: u8) -> SigningKey { + SigningKey::from_bytes(&[seed; 32]) + } + + fn sign_raw(key: &SigningKey, payload: &[u8]) -> Vec { + key.sign(&signable(SIGN_DOMAIN, payload)).to_bytes().to_vec() + } + + #[test] + fn profile_roundtrip_both_generations() { + let k = kp(1); + let owner = k.verifying_key().to_bytes(); + let mut p = ProfileState { + schema_version: SCHEMA_VERSION, + owner, + sequence: 1, + display_name: "Kyle".into(), + bio: String::new(), + avatar: None, + sig: vec![], + }; + p.sig = sign_raw(&k, &profile_sign_payload(&p)); + let b = bincode::serialize(&p).unwrap(); + assert!(validate_profile(&owner, &b).is_ok()); + // With a bounded avatar ref. + let mut p2 = p.clone(); + p2.sequence = 2; + p2.avatar = Some(MediaRefV1 { + content_hash: [9u8; 32], + media_type: V1_MEDIA_TYPE.into(), + byte_length: 50_000, + width: 256, + height: 256, + }); + p2.sig = sign_raw(&k, &profile_sign_payload(&p2)); + assert!(validate_profile(&owner, &bincode::serialize(&p2).unwrap()).is_ok()); + // Unbounded avatar refused; tamper refused. + let mut p3 = p2.clone(); + p3.avatar.as_mut().unwrap().width = 4096; + p3.sig = sign_raw(&k, &profile_sign_payload(&p3)); + assert_eq!( + validate_profile(&owner, &bincode::serialize(&p3).unwrap()), + Err(ProfileInvalid::AvatarUnbounded) + ); + let mut p4 = p2.clone(); + p4.display_name = "Mallory".into(); + assert_eq!( + validate_profile(&owner, &bincode::serialize(&p4).unwrap()), + Err(ProfileInvalid::BadSignature) + ); + } + + #[test] + fn asset_roundtrip_and_hash_binding() { + let k = kp(1); + let owner = k.verifying_key().to_bytes(); + let mut a = MediaAssetV1 { + schema_version: SCHEMA_VERSION, + owner, + asset_id: [4u8; 16], + revision: 1, + media_type: V1_MEDIA_TYPE.into(), + width: V1_DIMENSION, + height: V1_DIMENSION, + sanitized_static_bytes: vec![7u8; 1000], + sig: vec![], + }; + a.sig = sign_raw(&k, &asset_sign_payload(&a)); + let hash = *blake3::hash(&a.sanitized_static_bytes).as_bytes(); + let b = bincode::serialize(&a).unwrap(); + assert!(validate_asset(&owner, &hash, &b).is_ok()); + assert_eq!(validate_asset(&owner, &[0u8; 32], &b), Err(AssetInvalid::HashMismatch)); + } +} + +/// blake3 of raw bytes — the content-addressing hash used across the +/// persona/media contract families. +pub fn content_hash(bytes: &[u8]) -> [u8; 32] { + *blake3::hash(bytes).as_bytes() +} diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index dafa60e..eaa1cf1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -29,6 +29,8 @@ image.workspace = true tokio.workspace = true base64 = "0.22" +bincode = "1" +bs58 = "0.5" # Shazam signature packets (shazam.rs) carry a CRC-32 of their body. crc32fast = "1" # Inflate for the deno release zip (ytdlp.rs) — already in the lock via the @@ -46,6 +48,8 @@ keyring = { version = "3", features = ["windows-native"] } sysinfo = "0.33" soulseek-proto = { path = "../crates/soulseek-proto" } soulseek-client = { path = "../crates/soulseek-client" } +freenet-adapter = { path = "../crates/freenet-adapter" } +persona-state = { path = "../crates/persona-state" } player = { path = "../crates/player" } tagger = { path = "../crates/tagger" } metadata = { path = "../crates/metadata" } diff --git a/src-tauri/assets/identity_delegate.wasm b/src-tauri/assets/identity_delegate.wasm new file mode 100644 index 0000000000000000000000000000000000000000..910b751908061c67f7d61c7f652a24a1db565104 GIT binary patch literal 202026 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 literal 0 HcmV?d00001 diff --git a/src-tauri/assets/media_contract.wasm b/src-tauri/assets/media_contract.wasm new file mode 100644 index 0000000000000000000000000000000000000000..34d1a46bec1370298e4c09dab336177ba6da5e63 GIT binary patch literal 171945 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

h2Y}i_KwN7y1rGdLYv?!f6B0TkH=pA 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 z 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 literal 0 HcmV?d00001 diff --git a/src-tauri/assets/persona_contract.wasm b/src-tauri/assets/persona_contract.wasm new file mode 100644 index 0000000000000000000000000000000000000000..1c7b38302ec41665a5a1a9f2708f1f87a5df9ead GIT binary patch literal 184115 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%0DVPUEhKvVy^L~(#@?{_st65S`^L!|kr{sdt4ZeK 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 z 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, + /// The experimental Freenet social layer (crates/freenet-adapter). + /// None → false: strictly opt-in, and flipping it off is the kill + /// switch — the adapter drops its connection and stops retrying. A + /// missing or broken node never affects Soulseek or playback. + #[serde(default)] + pub freenet_enabled: Option, + /// WebSocket API port of the EXTERNAL local Freenet node. None → 7509. + #[serde(default)] + pub freenet_ws_port: Option, + /// Whether profile avatars fetched over Freenet may be decoded and + /// shown. None → true (the pipeline sanitizes them regardless); false + /// degrades every remote avatar to the identicon, no fetch at all. + #[serde(default)] + pub freenet_load_remote_images: Option, + /// The Community area's local view of a Soulseek contact: petname, group, + /// note and the two local marks. Private to this device by design — none + /// of it is ever published or sent to the person it describes. + #[serde(default)] + pub contacts: Vec, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ContactMeta { + pub username: String, + #[serde(default)] + pub petname: Option, + #[serde(default)] + pub group: Option, + #[serde(default)] + pub note: Option, + #[serde(default)] + pub trusted: bool, + #[serde(default)] + pub favorite: bool, } /// Default longest edge for embedded covers when the user hasn't chosen. diff --git a/src-tauri/src/freenet.rs b/src-tauri/src/freenet.rs new file mode 100644 index 0000000..aca223c --- /dev/null +++ b/src-tauri/src/freenet.rs @@ -0,0 +1,355 @@ +//! The app's Freenet surface — deliberately tiny. +//! +//! The webview gets STATUS ONLY: whether the experimental layer is enabled, +//! and what the adapter sees (absent / occupied / incompatible / connected). +//! The privileged node API stays entirely inside the Rust boundary +//! (crates/freenet-adapter); no command here moves contract state, keys, or +//! node operations across the bridge. Future Community services call the +//! adapter crate directly from Rust. +//! +//! Off by default. `freenet_set_enabled(true)` is the explicit opt-in and +//! persists to config.json; the kill switch is the same call with `false` +//! and takes effect immediately (drops the connection, ends every retry). + +use serde::Serialize; +use tauri::{Emitter, Manager}; + +use crate::config; +use crate::state::AppState; + +#[derive(Serialize)] +pub struct FreenetStatus { + pub enabled: bool, + pub ws_port: u16, + pub status: freenet_adapter::AdapterStatus, + /// Whether remote profile avatars may be fetched and decoded at all. + pub load_remote_images: bool, +} + +/// Wire the adapter at startup: apply config (port + opt-in) and forward +/// adapter events to the webview as `freenet:status` — status frames only. +pub fn init(app: &tauri::AppHandle) { + let cfg = config::load(app); + let state = app.state::(); + let adapter = state.freenet.clone(); + adapter.set_ws_port(cfg.freenet_ws_port.unwrap_or(freenet_adapter::DEFAULT_WS_PORT)); + + let handle = app.clone(); + let mut events = adapter.subscribe(); + tauri::async_runtime::spawn(async move { + loop { + match events.recv().await { + Ok(freenet_adapter::AdapterEvent::Status(s)) => { + let _ = handle.emit("freenet:status", &s); + } + // Contract updates carry ids/lengths only, and nothing in + // the UI consumes them yet — swallow rather than emit noise. + Ok(freenet_adapter::AdapterEvent::ContractUpdate { .. }) => {} + Err(tokio::sync::broadcast::error::RecvError::Lagged(_)) => continue, + Err(tokio::sync::broadcast::error::RecvError::Closed) => break, + } + } + }); + + if cfg.freenet_enabled.unwrap_or(false) { + adapter.enable(); + // The peer the app set up follows the switch (see ensure_node). + tauri::async_runtime::spawn(ensure_node(app.clone())); + } +} + +#[tauri::command] +pub fn freenet_status(app: tauri::AppHandle, state: tauri::State<'_, AppState>) -> FreenetStatus { + FreenetStatus { + enabled: state.freenet.is_enabled(), + ws_port: state.freenet.ws_port(), + status: state.freenet.status(), + load_remote_images: config::load(&app).freenet_load_remote_images.unwrap_or(true), + } +} + +/// The reader-side policy gate for avatars (profile.rs checks it BEFORE any +/// fetch). Off degrades every remote avatar to the identicon. +#[tauri::command] +pub fn freenet_set_load_remote_images( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + on: bool, +) -> Result { + let mut cfg = config::load(&app); + cfg.freenet_load_remote_images = Some(on); + config::save(&app, &cfg); + Ok(freenet_status(app, state)) +} + +/// The explicit opt-in / kill switch. Persisted, then applied immediately. +#[tauri::command] +pub fn freenet_set_enabled( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + enabled: bool, +) -> Result { + let mut cfg = config::load(&app); + cfg.freenet_enabled = Some(enabled); + config::save(&app, &cfg); + if enabled { + state.freenet.enable(); + tauri::async_runtime::spawn(ensure_node(app.clone())); + } else { + state.freenet.disable(); + } + Ok(freenet_status(app, state)) +} + +/// One-shot detection — works while disabled, touches no adapter state. +#[tauri::command] +pub async fn freenet_detect( + state: tauri::State<'_, AppState>, +) -> Result { + Ok(state.freenet.detect().await) +} + +// ---- the local peer ----------------------------------------------------------- +// Starting the installed node from the app, the way the research did it by +// hand (research/freenet-f0, -f2): the peer writes its config.toml on first +// boot with telemetry ON (the alpha default, even in local mode), so a first +// start runs it only until that file exists, stops it, pins +// `telemetry-enabled = false`, and only then launches the real session. The +// peer is a detached background process — it outlives the app on purpose +// (the design's "desktop background peer") and stops with its own button. + +use std::path::{Path, PathBuf}; +use std::process::{Child, Command, Stdio}; +use std::time::{Duration, Instant}; + +#[derive(Debug, Serialize)] +pub struct NodeInfo { + /// Where the peer binary was found, if anywhere. + pub binary: Option, + pub version: Option, + pub config_dir: String, + pub data_dir: String, + pub config_exists: bool, + pub telemetry_off: bool, + /// True while a node THIS app launched is alive. + pub started_by_app: bool, +} + +const TELEMETRY_ON: &str = "telemetry-enabled = true"; +const TELEMETRY_OFF: &str = "telemetry-enabled = false"; +const FIRST_BOOT_WAIT: Duration = Duration::from_secs(20); + +struct NodeDirs { + base: PathBuf, + config: PathBuf, + data: PathBuf, +} + +fn node_dirs(app: &tauri::AppHandle) -> Result { + let base = app + .path() + .app_data_dir() + .map_err(|e| e.to_string())? + .join("freenet"); + Ok(NodeDirs { config: base.join("config"), data: base.join("data"), base }) +} + +/// No console window for child processes on Windows. +fn quiet(mut c: Command) -> Command { + #[cfg(windows)] + { + use std::os::windows::process::CommandExt; + c.creation_flags(0x0800_0000); + } + c +} + +fn find_binary(app: &tauri::AppHandle) -> Option { + let name = if cfg!(windows) { "freenet.exe" } else { "freenet" }; + if let Ok(home) = app.path().home_dir() { + let p = home.join(".cargo").join("bin").join(name); + if p.is_file() { + return Some(p); + } + } + let on_path = quiet(Command::new("freenet")) + .arg("--version") + .output() + .map(|o| o.status.success()) + .unwrap_or(false); + on_path.then(|| PathBuf::from("freenet")) +} + +fn version_of(bin: &Path) -> Option { + let out = quiet(Command::new(bin)).arg("--version").output().ok()?; + let text = String::from_utf8_lossy(&out.stdout); + let line = text.lines().next()?.trim(); + let v = line + .trim_start_matches("Freenet version:") + .trim() + .trim_end_matches("()") + .trim(); + (!v.is_empty()).then(|| v.to_string()) +} + +fn telemetry_off(config: &Path) -> bool { + std::fs::read_to_string(config) + .map(|s| s.contains(TELEMETRY_OFF)) + .unwrap_or(false) +} + +fn pin_telemetry_off(config: &Path) -> Result<(), String> { + let s = std::fs::read_to_string(config).map_err(|e| format!("read config.toml: {e}"))?; + if s.contains(TELEMETRY_OFF) { + return Ok(()); + } + if !s.contains(TELEMETRY_ON) { + return Err("config.toml has no telemetry-enabled line to pin".into()); + } + std::fs::write(config, s.replace(TELEMETRY_ON, TELEMETRY_OFF)) + .map_err(|e| format!("write config.toml: {e}")) +} + +fn spawn_node(bin: &Path, dirs: &NodeDirs, log: &Path) -> Result { + let out = std::fs::File::create(log).map_err(|e| format!("node log: {e}"))?; + let err = out.try_clone().map_err(|e| e.to_string())?; + quiet(Command::new(bin)) + .arg("network") + .arg("--config-dir") + .arg(&dirs.config) + .arg("--data-dir") + .arg(&dirs.data) + .stdin(Stdio::null()) + .stdout(Stdio::from(out)) + .stderr(Stdio::from(err)) + .spawn() + .map_err(|e| format!("start the peer: {e}")) +} + +fn node_info(app: &tauri::AppHandle, state: &AppState) -> Result { + let dirs = node_dirs(app)?; + let bin = find_binary(app); + let config = dirs.config.join("config.toml"); + let started_by_app = { + let mut guard = state.freenet_node.lock().unwrap(); + match guard.as_mut().map(|c| c.try_wait()) { + Some(Ok(None)) => true, + _ => { + *guard = None; + false + } + } + }; + Ok(NodeInfo { + version: bin.as_deref().and_then(version_of), + binary: bin.map(|p| p.display().to_string()), + config_dir: dirs.config.display().to_string(), + data_dir: dirs.data.display().to_string(), + config_exists: config.is_file(), + telemetry_off: telemetry_off(&config), + started_by_app, + }) +} + +#[tauri::command] +pub fn freenet_node_info( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + node_info(&app, &state) +} + +/// Start the peer under the app's folder (the first-boot recipe when its +/// config does not exist yet). Returns the running child. +async fn start_node_inner(app: &tauri::AppHandle) -> Result { + let handle = app.clone(); + tauri::async_runtime::spawn_blocking(move || -> Result { + let bin = find_binary(&handle) + .ok_or("no Freenet peer found on this machine — install it (cargo install freenet) and try again")?; + let dirs = node_dirs(&handle)?; + std::fs::create_dir_all(&dirs.config).map_err(|e| e.to_string())?; + std::fs::create_dir_all(&dirs.data).map_err(|e| e.to_string())?; + let config = dirs.config.join("config.toml"); + if !config.is_file() { + let first_log = dirs.base.join("first-boot.log"); + let mut first = spawn_node(&bin, &dirs, &first_log)?; + let deadline = Instant::now() + FIRST_BOOT_WAIT; + while !config.is_file() && Instant::now() < deadline { + if let Ok(Some(status)) = first.try_wait() { + return Err(format!( + "the peer exited during its first boot ({status}) — see {}", + first_log.display() + )); + } + std::thread::sleep(Duration::from_millis(100)); + } + let _ = first.kill(); + let _ = first.wait(); + if !config.is_file() { + return Err("the peer wrote no config.toml within 20s".into()); + } + log::info!("freenet node: first boot wrote {}", config.display()); + } + pin_telemetry_off(&config)?; + let child = spawn_node(&bin, &dirs, &dirs.base.join("node.log"))?; + log::info!("freenet node started (pid {}) from {}", child.id(), bin.display()); + Ok(child) + }) + .await + .map_err(|e| e.to_string())? +} + +/// A peer the app set up follows the switch: whenever the layer is on and +/// the peer is absent, start it — at launch, and when the switch goes on. +/// First-time setup stays explicit (the Start button), so a user who never +/// asked for a peer never gets one; after that it is simply kept running. +/// (A dev-harness restart takes the child down with the app — observed +/// 2026-09-02 — and a reboot does the same; this is what brings it back.) +pub async fn ensure_node(app: tauri::AppHandle) { + let state = app.state::(); + if !state.freenet.is_enabled() { + return; + } + let Ok(dirs) = node_dirs(&app) else { return }; + if !dirs.config.join("config.toml").is_file() { + return; + } + if state.freenet_node.lock().unwrap().is_some() { + return; + } + if !matches!(state.freenet.detect().await, freenet_adapter::AdapterStatus::NodeAbsent) { + return; + } + match start_node_inner(&app).await { + Ok(child) => *state.freenet_node.lock().unwrap() = Some(child), + Err(e) => log::warn!("freenet node: could not start the peer: {e}"), + } +} + +#[tauri::command] +pub async fn freenet_node_start( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + if node_info(&app, &state)?.started_by_app { + return node_info(&app, &state); + } + let child = start_node_inner(&app).await?; + *state.freenet_node.lock().unwrap() = Some(child); + node_info(&app, &state) +} + +/// Stops only a node this app started; a hand-started peer is left alone. +#[tauri::command] +pub async fn freenet_node_stop( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + let child = state.freenet_node.lock().unwrap().take(); + if let Some(mut c) = child { + let _ = c.kill(); + let _ = c.wait(); + log::info!("freenet node stopped"); + } + node_info(&app, &state) +} diff --git a/src-tauri/src/persona.rs b/src-tauri/src/persona.rs new file mode 100644 index 0000000..2e8a30a --- /dev/null +++ b/src-tauri/src/persona.rs @@ -0,0 +1,395 @@ +//! PersonaService — the SoulStream identity, held by the bundled Freenet +//! identity delegate and reached only through the FreenetAdapter. +//! +//! The delegate wasm ships as an app asset (`assets/identity_delegate.wasm`, +//! sha256 84dd8dbb…, the generation every F1–F2b spike validated). Its key +//! namespace is (code hash, params), so THESE BYTES ARE A COMMITMENT: +//! changing them re-keys the delegate and strands every user's persona — +//! and the platform's copy-forward is disabled (GHSA-824h-7x5x-wfmf), so +//! the only migration is export-artifact → new generation → import, +//! verified by reading the identity back (F1's record). Treat any change +//! as a migration event, never a routine rebuild. +//! +//! Privilege rules, same as everywhere on this boundary: +//! - the PRIVATE key never leaves the delegate; what crosses to the webview +//! is the public key, the key version, and status strings; +//! - the passphrase-sealed recovery artifact is written/read by RUST at a +//! caller-chosen path — its bytes never transit the webview; +//! - signing stays Rust-internal (`sign` is pub(crate) for future +//! Community services, not a Tauri command). +//! +//! Wire pin: `InMsg`/`OutMsg` are bincode enums whose VARIANT ORDER must +//! match research/freenet-f1/identity-delegate/src/lib.rs exactly — bincode +//! encodes the variant index, so reordering is a silent protocol break. + +use freenet_adapter::FreenetAdapter; +use serde::{Deserialize, Serialize}; + +use crate::state::AppState; + +const DELEGATE_WASM: &[u8] = include_bytes!("../assets/identity_delegate.wasm"); +const DELEGATE_PARAMS: &[u8] = b"soulstream-identity-v1"; + +/// Recovery-artifact KDF defaults: Argon2id inside the delegate's wasm. +/// 64 MiB / 3 passes measured comfortably inside the delegate's caps +/// (8–64 MiB, t ≤ 8 — F1). The artifact itself is 93 bytes. +const EXPORT_M_COST_KIB: u32 = 64 * 1024; +const EXPORT_T_COST: u32 = 3; + +// ---- delegate protocol (bincode; variant order is the wire) ---- + +#[derive(Debug, Serialize, Deserialize)] +enum InMsg { + CreateIdentity { force: bool }, + GetPublicKey, + Sign { domain: String, payload: Vec }, + ExportIdentity { passphrase: String, m_cost_kib: u32, t_cost: u32 }, + ImportIdentity { artifact: Vec, passphrase: String, force: bool }, + RotateIdentity, + GetTransition, + RemoveIdentity, +} + +#[derive(Debug, Serialize, Deserialize)] +enum OutMsg { + Identity { public_key: [u8; 32], key_version: u32, created: bool }, + NotInitialized, + Signature { public_key: [u8; 32], key_version: u32, sig: Vec }, + Artifact { bytes: Vec }, + Rotated { old_public: [u8; 32], new_public: [u8; 32], key_version: u32, transition_sig: Vec }, + Transition { old_public: [u8; 32], new_public: [u8; 32], key_version: u32, transition_sig: Vec }, + NoTransition, + Removed, + Refused { reason: String }, +} + +// ---- public shapes (webview-safe: public data only) ---- + +#[derive(Debug, Clone, Serialize)] +pub struct PersonaInfo { + pub public_key: String, + pub key_version: u32, +} + +#[derive(Debug, Serialize)] +pub struct PersonaStatus { + /// Adapter reachable and enabled — persona ops can run at all. + pub available: bool, + pub adapter: freenet_adapter::AdapterStatus, + /// None when available but no identity exists yet. + pub persona: Option, + /// This build's delegate generation (b58 key) — diagnostics, and the + /// value that must not drift between releases. + pub delegate_key: String, +} + +#[derive(Debug, Serialize)] +pub struct RotationInfo { + pub old_public: String, + pub new_public: String, + pub key_version: u32, +} + +// ---- core (adapter-facing, testable without Tauri) ---- + +async fn call(adapter: &FreenetAdapter, msg: InMsg) -> Result { + // Registration is idempotent and cheap; doing it per-op means the + // service self-heals across node restarts and adapter reconnects. + adapter + .delegate_register(DELEGATE_WASM.to_vec(), DELEGATE_PARAMS) + .await + .map_err(|e| e.to_string())?; + let payload = bincode::serialize(&msg).map_err(|e| e.to_string())?; + let reply = adapter + .delegate_message(DELEGATE_WASM.to_vec(), DELEGATE_PARAMS, payload) + .await + .map_err(|e| e.to_string())?; + bincode::deserialize(&reply).map_err(|e| format!("delegate reply did not decode: {e}")) +} + +fn info(public_key: [u8; 32], key_version: u32) -> PersonaInfo { + PersonaInfo { + public_key: bs58::encode(public_key).into_string(), + key_version, + } +} + +pub(crate) async fn current(adapter: &FreenetAdapter) -> Result, String> { + match call(adapter, InMsg::GetPublicKey).await? { + OutMsg::Identity { public_key, key_version, .. } => Ok(Some(info(public_key, key_version))), + OutMsg::NotInitialized => Ok(None), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +pub(crate) async fn create(adapter: &FreenetAdapter) -> Result { + match call(adapter, InMsg::CreateIdentity { force: false }).await? { + OutMsg::Identity { public_key, key_version, .. } => Ok(info(public_key, key_version)), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +/// Seal the identity to a passphrase and write the artifact at `path`. +/// The bytes go disk-direct from Rust; nothing crosses the webview. +pub(crate) async fn export_to( + adapter: &FreenetAdapter, + passphrase: &str, + path: &str, +) -> Result { + match call( + adapter, + InMsg::ExportIdentity { + passphrase: passphrase.to_string(), + m_cost_kib: EXPORT_M_COST_KIB, + t_cost: EXPORT_T_COST, + }, + ) + .await? + { + OutMsg::Artifact { bytes } => { + let n = bytes.len(); + std::fs::write(path, bytes).map_err(|e| format!("writing artifact: {e}"))?; + Ok(n) + } + OutMsg::NotInitialized => Err("no persona exists yet".into()), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +/// Restore from a recovery artifact file. Refuses to overwrite an existing +/// persona unless `force` — same trust-reset semantics the F1 record set. +pub(crate) async fn import_from( + adapter: &FreenetAdapter, + passphrase: &str, + path: &str, + force: bool, +) -> Result { + let artifact = std::fs::read(path).map_err(|e| format!("reading artifact: {e}"))?; + match call( + adapter, + InMsg::ImportIdentity { artifact, passphrase: passphrase.to_string(), force }, + ) + .await? + { + OutMsg::Identity { public_key, key_version, .. } => Ok(info(public_key, key_version)), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +pub(crate) async fn rotate(adapter: &FreenetAdapter) -> Result { + match call(adapter, InMsg::RotateIdentity).await? { + OutMsg::Rotated { old_public, new_public, key_version, .. } => Ok(RotationInfo { + old_public: bs58::encode(old_public).into_string(), + new_public: bs58::encode(new_public).into_string(), + key_version, + }), + OutMsg::NotInitialized => Err("no persona exists yet".into()), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +pub(crate) async fn remove(adapter: &FreenetAdapter) -> Result<(), String> { + match call(adapter, InMsg::RemoveIdentity).await? { + OutMsg::Removed => Ok(()), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +/// Domain-separated signing for the Rust services (profiles today; +/// playlists, links next). Deliberately not a Tauri command. +pub(crate) async fn sign( + adapter: &FreenetAdapter, + domain: &str, + payload: Vec, +) -> Result, String> { + match call(adapter, InMsg::Sign { domain: domain.to_string(), payload }).await? { + OutMsg::Signature { sig, .. } => Ok(sig), + OutMsg::NotInitialized => Err("no persona exists yet".into()), + OutMsg::Refused { reason } => Err(reason), + other => Err(format!("unexpected delegate reply: {other:?}")), + } +} + +// ---- Tauri surface ---- + +#[tauri::command] +pub async fn persona_status(state: tauri::State<'_, AppState>) -> Result { + let adapter = state.freenet.clone(); + let delegate_key = FreenetAdapter::delegate_key_b58(DELEGATE_WASM.to_vec(), DELEGATE_PARAMS); + let adapter_status = adapter.status(); + let available = adapter.is_enabled() + && adapter_status == freenet_adapter::AdapterStatus::Connected; + let persona = if available { current(&adapter).await.ok().flatten() } else { None }; + Ok(PersonaStatus { available, adapter: adapter_status, persona, delegate_key }) +} + +#[tauri::command] +pub async fn persona_create( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + let info = create(&state.freenet.clone()).await?; + // Minted here: the profile ledger knows nothing can exist on the + // network yet, so no search is ever spent looking for it. + crate::profile::ledger_note_persona(&app, &info.public_key, true); + Ok(info) +} + +#[tauri::command] +pub async fn persona_export( + state: tauri::State<'_, AppState>, + passphrase: String, + path: String, +) -> Result { + export_to(&state.freenet.clone(), &passphrase, &path).await +} + +#[tauri::command] +pub async fn persona_import( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + passphrase: String, + path: String, + force: bool, +) -> Result { + let info = import_from(&state.freenet.clone(), &passphrase, &path, force).await?; + // Imported: another device may have published — the first read asks. + crate::profile::ledger_note_persona(&app, &info.public_key, false); + Ok(info) +} + +#[tauri::command] +pub async fn persona_rotate( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + let info = rotate(&state.freenet.clone()).await?; + // A new key addresses a new profile contract: nothing published there yet. + crate::profile::ledger_note_persona(&app, &info.new_public, true); + crate::profile::ledger_forget_persona(&app, &info.old_public); + Ok(info) +} + +#[tauri::command] +pub async fn persona_remove( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result<(), String> { + let adapter = state.freenet.clone(); + let gone = current(&adapter).await.ok().flatten(); + remove(&adapter).await?; + if let Some(info) = gone { + crate::profile::ledger_forget_persona(&app, &info.public_key); + } + Ok(()) +} + +// ---- tests ---- + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn wire_shapes_roundtrip() { + // The variant ORDER is the wire; this pins encode/decode symmetry + // for the message we depend on most. + let msg = InMsg::ImportIdentity { + artifact: vec![1, 2, 3], + passphrase: "pw".into(), + force: true, + }; + let bytes = bincode::serialize(&msg).unwrap(); + // Variant index 4 (0-based) leads the encoding as a u32. + assert_eq!(&bytes[..4], &4u32.to_le_bytes()); + let out = OutMsg::Identity { public_key: [7; 32], key_version: 3, created: false }; + let bytes = bincode::serialize(&out).unwrap(); + let back: OutMsg = bincode::deserialize(&bytes).unwrap(); + assert!(matches!(back, OutMsg::Identity { key_version: 3, .. })); + } + + #[test] + fn bundled_delegate_generation_is_pinned() { + // If this changes, a migration event is happening — see the module + // docs. Update deliberately, never in passing. + let key = FreenetAdapter::delegate_key_b58(DELEGATE_WASM.to_vec(), DELEGATE_PARAMS); + // The gen-2 identity delegate — the generation every F2→F2b spike + // validated (research/freenet-f1's upgrade probe minted it). + assert_eq!(key, "EtHTvPUtxbZ8TXGZJrmkj21xjQNqVmWdWAohVgydBgst"); + assert_eq!(DELEGATE_WASM.len(), 202026); + } + + #[tokio::test] + async fn ops_refuse_while_disabled() { + let adapter = FreenetAdapter::default(); + let err = current(&adapter).await.unwrap_err(); + assert!(err.contains("disabled"), "{err}"); + } + + /// Live: needs a local freenet node on 7509. + /// cargo test -p app --release persona_live -- --ignored + /// Mutates the node's persona namespace (create/remove/rotate) — run + /// against a throwaway node, not one holding an identity you keep. + #[tokio::test] + #[ignore = "needs a local freenet node on 7509; mutates its persona"] + async fn persona_live_full_loop() { + let adapter = FreenetAdapter::default(); + adapter.enable(); + let mut tries = 0; + while adapter.status() != freenet_adapter::AdapterStatus::Connected { + tokio::time::sleep(std::time::Duration::from_millis(200)).await; + tries += 1; + assert!(tries < 50, "adapter never connected: {:?}", adapter.status()); + } + + // Clean slate, then the full lifecycle. + let _ = remove(&adapter).await; + assert!(current(&adapter).await.unwrap().is_none()); + let created = create(&adapter).await.expect("create"); + assert_eq!(created.key_version, 1); + // No silent overwrite. + let dup = create(&adapter).await; + assert!(dup.is_err()); + + // Export → remove → import reproduces the fingerprint. + let dir = std::env::temp_dir().join("soulstream-persona-test"); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("recovery.ssid"); + let path_str = path.to_string_lossy().to_string(); + let n = export_to(&adapter, "correct horse battery", &path_str).await.expect("export"); + assert_eq!(n, 93, "the artifact is 93 bytes by construction"); + remove(&adapter).await.expect("remove"); + let restored = import_from(&adapter, "correct horse battery", &path_str, false) + .await + .expect("import"); + assert_eq!(restored.public_key, created.public_key); + // Wrong passphrase refuses. + let bad = import_from(&adapter, "wrong passphrase!", &path_str, true).await; + assert!(bad.is_err()); + + // Rotation bumps the version and changes the key. + let rot = rotate(&adapter).await.expect("rotate"); + assert_eq!(rot.old_public, created.public_key); + assert_eq!(rot.key_version, 2); + let now = current(&adapter).await.unwrap().unwrap(); + assert_eq!(now.public_key, rot.new_public); + + // Signing works for Rust callers under an allowed domain. + let sig = sign(&adapter, "soulstream.profile/v1", b"payload".to_vec()) + .await + .expect("sign"); + assert_eq!(sig.len(), 64); + // ...and refuses an unapproved domain with a typed reason. + let refused = sign(&adapter, "evil.domain/v1", b"payload".to_vec()).await; + assert!(refused.is_err()); + + adapter.disable(); + let _ = std::fs::remove_file(&path); + } +} diff --git a/src-tauri/src/profile.rs b/src-tauri/src/profile.rs new file mode 100644 index 0000000..1ec9a21 --- /dev/null +++ b/src-tauri/src/profile.rs @@ -0,0 +1,786 @@ +//! ProfileService — the persona's publishable face: display name, bio, and +//! a sanitized avatar, published through the bundled persona/media +//! contracts and signed by the identity delegate (persona.rs). +//! +//! Contract bytes are commitments like the delegate's (see persona.rs): +//! `assets/persona_contract.wasm` (gen-2, avatar-accepting) and +//! `assets/media_contract.wasm` (immutable content-addressed images), both +//! straight from the F2/F2b validation runs, code hashes pinned by tests. +//! +//! The avatar pipeline is F2b's, verbatim in spirit: +//! - PUBLISH: bounded decode → center-crop → 256×256 CatmullRom → RGB → +//! deterministic PNG → budget gate. Metadata cannot survive (pixels in, +//! critical chunks out). +//! - VIEW: policy gates BEFORE any fetch → structural verification (hash, +//! signature, declared bounds vs the signed reference) BEFORE decode → +//! bounded decode (sniff, header-dims refusal pre-allocation) → only +//! then do the sanitized bytes go to the webview. Any failure degrades +//! to "no avatar" with a reason, never an error surface. + +use std::collections::BTreeMap; +use std::io::Cursor; +use std::path::PathBuf; +use std::time::{SystemTime, UNIX_EPOCH}; + +use freenet_adapter::FreenetAdapter; +use image::{imageops::FilterType, ImageEncoder, ImageReader, Limits}; +use persona_state as ps; +use serde::{Deserialize, Serialize}; +use tauri::Manager; + +use crate::state::AppState; +use crate::{config, persona}; + +const PROFILE_CONTRACT_WASM: &[u8] = include_bytes!("../assets/persona_contract.wasm"); +const MEDIA_CONTRACT_WASM: &[u8] = include_bytes!("../assets/media_contract.wasm"); + +const SOURCE_MAX_BYTES: usize = 16 * 1024 * 1024; +const SOURCE_MAX_DIM: u32 = 8192; +const READER_MAX_DIM: u32 = 512; +const READER_MAX_ALLOC: u64 = 32 * 1024 * 1024; + +// ---------------------------------------------------------------- pipeline + +fn limits(max_dim: u32) -> Limits { + let mut l = Limits::default(); + l.max_image_width = Some(max_dim); + l.max_image_height = Some(max_dim); + l.max_alloc = Some(READER_MAX_ALLOC); + l +} + +fn decode_bounded( + bytes: &[u8], + max_dim: u32, + expect_png: bool, +) -> Result { + let mut reader = ImageReader::new(Cursor::new(bytes)) + .with_guessed_format() + .map_err(|e| format!("format sniff failed: {e}"))?; + let fmt = reader + .format() + .ok_or_else(|| "unrecognized image format".to_string())?; + if expect_png && fmt != image::ImageFormat::Png { + return Err(format!("declared image/png but bytes are {fmt:?}")); + } + reader.limits(limits(max_dim)); + reader.decode().map_err(|e| format!("bounded decode refused: {e}")) +} + +/// Publisher normalization — F2b's recipe. Deterministic for a given input. +pub(crate) fn normalize_avatar(source: &[u8]) -> Result, String> { + if source.len() > SOURCE_MAX_BYTES { + return Err(format!("source over {SOURCE_MAX_BYTES} bytes")); + } + let img = decode_bounded(source, SOURCE_MAX_DIM, false)?; + let (w, h) = (img.width(), img.height()); + let side = w.min(h); + let cropped = img.crop_imm((w - side) / 2, (h - side) / 2, side, side); + let resized = cropped.resize_exact(ps::V1_DIMENSION, ps::V1_DIMENSION, FilterType::CatmullRom); + let rgb = resized.to_rgb8(); + let mut out = Vec::new(); + image::codecs::png::PngEncoder::new(&mut out) + .write_image(rgb.as_raw(), ps::V1_DIMENSION, ps::V1_DIMENSION, image::ExtendedColorType::Rgb8) + .map_err(|e| e.to_string())?; + if out.len() > ps::MAX_MEDIA_BYTES { + return Err(format!( + "normalized avatar is {} bytes, over the {} budget — this image compresses poorly; pick another", + out.len(), + ps::MAX_MEDIA_BYTES + )); + } + Ok(out) +} + +/// Reader decode — the LAST gate before bytes reach the webview. Runs only +/// after structural verification against the signed reference. +fn reader_verify_decode(asset: &ps::MediaAssetV1) -> Result<(), String> { + let img = decode_bounded(&asset.sanitized_static_bytes, READER_MAX_DIM, true)?; + if img.width() != asset.width || img.height() != asset.height { + return Err(format!( + "decoded {}x{} contradicts declared {}x{}", + img.width(), + img.height(), + asset.width, + asset.height + )); + } + Ok(()) +} + +// ---------------------------------------------------------------- service + +#[derive(Debug, Serialize)] +pub struct ProfileView { + pub owner: String, + pub sequence: u64, + pub display_name: String, + pub bio: String, + /// Base64 PNG of the VERIFIED, sanitized avatar — present only when the + /// whole gauntlet passed. + pub avatar_png_base64: Option, + /// Why there is no avatar image ("none published", policy, or the + /// failure reason) — the UI renders its identicon on any of these. + pub avatar_note: Option, + /// True when this came from the device's own ledger (what it last + /// published) rather than a network read. + pub from_ledger: bool, +} + +fn decode_owner(b58: &str) -> Result<[u8; 32], String> { + bs58::decode(b58) + .into_vec() + .map_err(|e| format!("bad persona key: {e}"))? + .as_slice() + .try_into() + .map_err(|_| "persona key is not 32 bytes".to_string()) +} + +async fn fetch_profile( + adapter: &FreenetAdapter, + owner: &[u8; 32], +) -> Result, String> { + let ids = FreenetAdapter::contract_ids( + PROFILE_CONTRACT_WASM.to_vec(), + &ps::make_profile_params(owner), + ); + match adapter.contract_get(&ids.instance, false).await { + Ok(bytes) if bytes.is_empty() => Ok(None), + Ok(bytes) => ps::validate_profile(owner, &bytes) + .map(Some) + .map_err(|e| format!("published profile failed verification: {e}")), + Err(e) if e.to_string().contains("not found") => Ok(None), + Err(e) => Err(e.to_string()), + } +} + +// ---------------------------------------------------------------- the ledger +// +// What THIS device knows about its own persona's profile, kept beside the +// node as /freenet/profile-ledger.json, with verified avatar bytes +// cached by content hash next to it. Reading our own profile from the ledger +// is instant and works offline. Asking the network for a profile that was +// never published is not: every such GET is a 12–30 s search of the ring that +// ends in "retry loop exhausted" (observed live 2026-09-02 — three of them +// behind one avatar change, a minute of nothing happening). The network is +// asked only when it might know more than this device: an imported key never +// searched, an UPDATE the network refuses, or an explicit refresh. + +const ABSENT_RECHECK_SECS: u64 = 3600; + +#[derive(Default, Serialize, Deserialize)] +struct Ledger { + #[serde(default)] + personas: BTreeMap, +} + +#[derive(Default, Serialize, Deserialize)] +struct LedgerEntry { + /// Minted on this device: nothing can exist on the network until this + /// device publishes it. + #[serde(default)] + created_here: bool, + /// The last state this device published (bincode, base64) — the truth + /// for the next read-and-bump while this device is the only writer. + #[serde(default)] + published: Option, + /// Unix seconds of the last network search that found nothing. + #[serde(default)] + absent_checked_at: Option, +} + +/// Where this device keeps what it knows. `None` in tests: network only. +pub struct Local { + ledger: PathBuf, + avatars: PathBuf, +} + +impl Local { + pub fn for_app(app: &tauri::AppHandle) -> Result { + let base = app + .path() + .app_data_dir() + .map_err(|e| e.to_string())? + .join("freenet"); + Ok(Self { ledger: base.join("profile-ledger.json"), avatars: base.join("avatars") }) + } + fn load(&self) -> Ledger { + std::fs::read(&self.ledger) + .ok() + .and_then(|b| serde_json::from_slice(&b).ok()) + .unwrap_or_default() + } + fn save(&self, ledger: &Ledger) { + if let Some(dir) = self.ledger.parent() { + let _ = std::fs::create_dir_all(dir); + } + match serde_json::to_vec_pretty(ledger) { + Ok(b) => { + if let Err(e) = std::fs::write(&self.ledger, b) { + log::warn!("profile ledger not saved: {e}"); + } + } + Err(e) => log::warn!("profile ledger not encoded: {e}"), + } + } + fn note_published(&self, owner: &[u8; 32], bytes: &[u8]) { + use base64::Engine; + let mut l = self.load(); + let e = l.personas.entry(owner_b58(owner)).or_default(); + e.published = Some(base64::engine::general_purpose::STANDARD.encode(bytes)); + e.absent_checked_at = None; + self.save(&l); + } + fn note_absent(&self, owner: &[u8; 32]) { + let mut l = self.load(); + l.personas.entry(owner_b58(owner)).or_default().absent_checked_at = Some(now_secs()); + self.save(&l); + } + fn avatar_path(&self, hash: &[u8; 32]) -> PathBuf { + self.avatars.join(format!("{}.png", hex(hash))) + } + fn cache_avatar(&self, hash: &[u8; 32], png: &[u8]) { + let _ = std::fs::create_dir_all(&self.avatars); + let _ = std::fs::write(self.avatar_path(hash), png); + } + /// Cached bytes only while they still hash to what the signed + /// reference says; anything else is simply not used. + fn cached_avatar(&self, hash: &[u8; 32]) -> Option> { + let bytes = std::fs::read(self.avatar_path(hash)).ok()?; + (blake3_hash(&bytes) == *hash).then_some(bytes) + } +} + +fn owner_b58(owner: &[u8; 32]) -> String { + bs58::encode(owner).into_string() +} +fn hex(bytes: &[u8]) -> String { + bytes.iter().map(|b| format!("{b:02x}")).collect() +} +fn now_secs() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|d| d.as_secs()) + .unwrap_or(0) +} + +/// persona.rs tells the ledger when a key is minted here or imported. +pub(crate) fn ledger_note_persona(app: &tauri::AppHandle, public_key_b58: &str, created_here: bool) { + let Ok(local) = Local::for_app(app) else { return }; + let mut l = local.load(); + l.personas.insert( + public_key_b58.to_string(), + LedgerEntry { created_here, published: None, absent_checked_at: None }, + ); + local.save(&l); +} +/// ...and when it is gone. +pub(crate) fn ledger_forget_persona(app: &tauri::AppHandle, public_key_b58: &str) { + let Ok(local) = Local::for_app(app) else { return }; + let mut l = local.load(); + if l.personas.remove(public_key_b58).is_some() { + local.save(&l); + } +} + +/// Our own profile from what this device knows; the network only when it +/// might know more (an imported key never searched, or `force`). The bool +/// says which one answered. +async fn fetch_own_profile( + adapter: &FreenetAdapter, + owner: &[u8; 32], + local: Option<&Local>, + force: bool, +) -> Result<(Option, bool), String> { + if let (Some(l), false) = (local, force) { + let ledger = l.load(); + if let Some(e) = ledger.personas.get(&owner_b58(owner)) { + if let Some(b64) = &e.published { + use base64::Engine; + let known = base64::engine::general_purpose::STANDARD + .decode(b64) + .ok() + .and_then(|b| ps::validate_profile(owner, &b).ok()); + if let Some(p) = known { + return Ok((Some(p), true)); + } + } else if e.created_here { + return Ok((None, true)); + } else if e + .absent_checked_at + .is_some_and(|t| now_secs().saturating_sub(t) < ABSENT_RECHECK_SECS) + { + return Ok((None, true)); + } + } + } + let found = fetch_profile(adapter, owner).await?; + if let Some(l) = local { + match &found { + Some(p) => { + if let Ok(b) = bincode::serialize(p) { + l.note_published(owner, &b); + } + } + None => l.note_absent(owner), + } + } + Ok((found, false)) +} + +/// Publish a signed profile revision. Read-and-bump (F5's rule) against what +/// this device knows; if the network refuses the update because another +/// writer moved first, read it for real once and bump past it. +async fn publish_profile( + adapter: &FreenetAdapter, + owner: [u8; 32], + display_name: String, + bio: String, + avatar: Option, + local: Option<&Local>, +) -> Result { + if display_name.len() > ps::MAX_NAME_BYTES { + return Err(format!("display name over {} bytes", ps::MAX_NAME_BYTES)); + } + if bio.len() > ps::MAX_BIO_BYTES { + return Err(format!("bio over {} bytes", ps::MAX_BIO_BYTES)); + } + let (existing, _) = fetch_own_profile(adapter, &owner, local, false).await?; + let mut sequence = existing.as_ref().map(|p| p.sequence + 1).unwrap_or(1); + let params = ps::make_profile_params(&owner); + let mut retried = false; + loop { + let mut p = ps::ProfileState { + schema_version: ps::SCHEMA_VERSION, + owner, + sequence, + display_name: display_name.clone(), + bio: bio.clone(), + avatar: avatar.clone(), + sig: vec![], + }; + p.sig = persona::sign(adapter, ps::SIGN_DOMAIN, ps::profile_sign_payload(&p)).await?; + let bytes = bincode::serialize(&p).map_err(|e| e.to_string())?; + let result = if existing.is_some() { + adapter + .contract_update(PROFILE_CONTRACT_WASM.to_vec(), ¶ms, bytes.clone()) + .await + .map(|_| ()) + } else { + adapter + .contract_put(PROFILE_CONTRACT_WASM.to_vec(), ¶ms, bytes.clone(), false) + .await + .map(|_| ()) + }; + match result { + Ok(_) => { + if let Some(l) = local { + l.note_published(&owner, &bytes); + } + return Ok(p); + } + Err(e) if existing.is_some() && local.is_some() && !retried => { + retried = true; + match fetch_profile(adapter, &owner).await? { + Some(fresh) if fresh.sequence >= sequence => { + log::info!( + "profile: network is at rev {}, ledger said {} — bumping past it", + fresh.sequence, + sequence - 1 + ); + sequence = fresh.sequence + 1; + } + _ => return Err(e.to_string()), + } + } + Err(e) => return Err(e.to_string()), + } + } +} + +async fn own_key(adapter: &FreenetAdapter) -> Result<[u8; 32], String> { + let info = persona::current(adapter) + .await? + .ok_or("no persona exists yet — create one first")?; + decode_owner(&info.public_key) +} + +fn verify_png_dims(bytes: &[u8], w: u32, h: u32) -> Result<(), String> { + let img = decode_bounded(bytes, READER_MAX_DIM, true)?; + if img.width() != w || img.height() != h { + return Err(format!("decoded {}x{} contradicts declared {w}x{h}", img.width(), img.height())); + } + Ok(()) +} + +/// The avatar half of the read gauntlet, in the design's order: policy → +/// cache by hash → single fetch → verify chain → bounded decode → note. +async fn render_view( + adapter: &FreenetAdapter, + owner: [u8; 32], + p: ps::ProfileState, + load_remote_images: bool, + local: Option<&Local>, + from_ledger: bool, +) -> ProfileView { + use base64::Engine; + let mut v = ProfileView { + owner: owner_b58(&owner), + sequence: p.sequence, + display_name: p.display_name.clone(), + bio: p.bio.clone(), + avatar_png_base64: None, + avatar_note: None, + from_ledger, + }; + let Some(r) = &p.avatar else { + v.avatar_note = Some("none published".into()); + return v; + }; + if !load_remote_images { + v.avatar_note = Some("remote profile images disabled".into()); + return v; + } + if let Some(png) = local.and_then(|l| l.cached_avatar(&r.content_hash)) { + if png.len() as u32 == r.byte_length + && verify_png_dims(&png, r.width as u32, r.height as u32).is_ok() + { + v.avatar_png_base64 = Some(base64::engine::general_purpose::STANDARD.encode(&png)); + return v; + } + } + let ids = FreenetAdapter::contract_ids( + MEDIA_CONTRACT_WASM.to_vec(), + &ps::make_media_params(&owner, &r.content_hash), + ); + // Single attempt (no retry storm — F2b): failure degrades to a note. + let state_bytes = match adapter.contract_get(&ids.instance, false).await { + Ok(b) => b, + Err(e) => { + v.avatar_note = Some(format!("avatar unavailable: {e}")); + return v; + } + }; + match ps::validate_asset(&owner, &r.content_hash, &state_bytes) { + Ok(asset) => { + let matches_ref = asset.media_type == r.media_type + && asset.sanitized_static_bytes.len() as u32 == r.byte_length + && asset.width == r.width as u32 + && asset.height == r.height as u32; + if !matches_ref { + v.avatar_note = Some("asset contradicts the signed reference".into()); + } else if let Err(e) = reader_verify_decode(&asset) { + v.avatar_note = Some(format!("decode refused: {e}")); + } else { + if let Some(l) = local { + l.cache_avatar(&r.content_hash, &asset.sanitized_static_bytes); + } + v.avatar_png_base64 = Some( + base64::engine::general_purpose::STANDARD.encode(&asset.sanitized_static_bytes), + ); + } + } + Err(e) => v.avatar_note = Some(format!("verification failed: {e}")), + } + v +} + +/// The full read gauntlet for anyone's profile — always the network. +async fn view( + adapter: &FreenetAdapter, + owner: [u8; 32], + load_remote_images: bool, + local: Option<&Local>, +) -> Result, String> { + let Some(p) = fetch_profile(adapter, &owner).await? else { + return Ok(None); + }; + Ok(Some(render_view(adapter, owner, p, load_remote_images, local, false).await)) +} + +/// Our own profile — what this device knows, unless `force` asks the network. +async fn view_own( + adapter: &FreenetAdapter, + owner: [u8; 32], + load_remote_images: bool, + local: Option<&Local>, + force: bool, +) -> Result, String> { + let (p, from_ledger) = fetch_own_profile(adapter, &owner, local, force).await?; + let Some(p) = p else { + return Ok(None); + }; + Ok(Some(render_view(adapter, owner, p, load_remote_images, local, from_ledger).await)) +} + +async fn set_avatar( + adapter: &FreenetAdapter, + image_path: &str, + local: Option<&Local>, +) -> Result { + let owner = own_key(adapter).await?; + let source = std::fs::read(image_path).map_err(|e| format!("reading image: {e}"))?; + let png = normalize_avatar(&source)?; + let content_hash = blake3_hash(&png); + let (current, _) = fetch_own_profile(adapter, &owner, local, false).await?; + let revision = current.as_ref().map(|p| p.sequence + 1).unwrap_or(1) as u32; + let mut asset_id = [0u8; 16]; + asset_id.copy_from_slice(&blake3_hash(&[&owner[..], b"avatar"].concat())[..16]); + let mut asset = ps::MediaAssetV1 { + schema_version: ps::SCHEMA_VERSION, + owner, + asset_id, + revision, + media_type: ps::V1_MEDIA_TYPE.into(), + width: ps::V1_DIMENSION, + height: ps::V1_DIMENSION, + sanitized_static_bytes: png.clone(), + sig: vec![], + }; + asset.sig = persona::sign(adapter, ps::SIGN_DOMAIN, ps::asset_sign_payload(&asset)).await?; + let asset_bytes = bincode::serialize(&asset).map_err(|e| e.to_string())?; + // Media object FIRST (design order), then the profile that points at it. + adapter + .contract_put( + MEDIA_CONTRACT_WASM.to_vec(), + &ps::make_media_params(&owner, &content_hash), + asset_bytes, + false, + ) + .await + .map_err(|e| e.to_string())?; + // Ours by construction — cache it so the view never has to fetch it back. + if let Some(l) = local { + l.cache_avatar(&content_hash, &png); + } + let avatar_ref = ps::MediaRefV1 { + content_hash, + media_type: ps::V1_MEDIA_TYPE.into(), + byte_length: png.len() as u32, + width: ps::V1_DIMENSION as u16, + height: ps::V1_DIMENSION as u16, + }; + let (name, bio) = current + .map(|p| (p.display_name, p.bio)) + .unwrap_or_else(|| (String::new(), String::new())); + publish_profile(adapter, owner, name, bio, Some(avatar_ref), local).await?; + view_own(adapter, owner, true, local, false) + .await? + .ok_or("profile vanished after publish".into()) +} + +fn blake3_hash(bytes: &[u8]) -> [u8; 32] { + // Route through persona-state's blake3 so src-tauri needs no direct dep. + ps::content_hash(bytes) +} + +// ---------------------------------------------------------------- commands + +#[tauri::command] +pub async fn profile_get( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + persona: Option, + force: Option, +) -> Result, String> { + let adapter = state.freenet.clone(); + let load = config::load(&app).freenet_load_remote_images.unwrap_or(true); + let local = Local::for_app(&app)?; + match persona { + Some(b58) => view(&adapter, decode_owner(&b58)?, load, Some(&local)).await, + None => { + let owner = own_key(&adapter).await?; + view_own(&adapter, owner, load, Some(&local), force.unwrap_or(false)).await + } + } +} + +#[tauri::command] +pub async fn profile_publish( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + display_name: String, + bio: String, +) -> Result { + let adapter = state.freenet.clone(); + let local = Local::for_app(&app)?; + let owner = own_key(&adapter).await?; + let (current, _) = fetch_own_profile(&adapter, &owner, Some(&local), false).await?; + let avatar = current.and_then(|p| p.avatar); + publish_profile(&adapter, owner, display_name, bio, avatar, Some(&local)).await?; + view_own(&adapter, owner, true, Some(&local), false) + .await? + .ok_or("profile vanished after publish".into()) +} + +#[tauri::command] +pub async fn profile_set_avatar( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, + image_path: String, +) -> Result { + let local = Local::for_app(&app)?; + set_avatar(&state.freenet.clone(), &image_path, Some(&local)).await +} + +/// Withdraw the avatar pointer. Truthful semantics (F2b): previously +/// published copies of the old image remain fetchable on the network — +/// this changes what the profile points at, it does not erase. +#[tauri::command] +pub async fn profile_clear_avatar( + app: tauri::AppHandle, + state: tauri::State<'_, AppState>, +) -> Result { + let adapter = state.freenet.clone(); + let local = Local::for_app(&app)?; + let owner = own_key(&adapter).await?; + let (current, _) = fetch_own_profile(&adapter, &owner, Some(&local), false).await?; + let current = current.ok_or("no profile published yet")?; + publish_profile(&adapter, owner, current.display_name, current.bio, None, Some(&local)).await?; + view_own(&adapter, owner, true, Some(&local), false) + .await? + .ok_or("profile vanished after publish".into()) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn photo_jpeg() -> Vec { + let w = 900u32; + let h = 600u32; + let mut rgb = image::RgbImage::new(w, h); + for (x, y, p) in rgb.enumerate_pixels_mut() { + *p = image::Rgb([(x * 255 / w) as u8, (y * 255 / h) as u8, (((x + y) * 255) / (w + h)) as u8]); + } + let mut jpeg = Vec::new(); + image::codecs::jpeg::JpegEncoder::new_with_quality(&mut jpeg, 85) + .encode_image(&image::DynamicImage::ImageRgb8(rgb)) + .unwrap(); + // Splice an EXIF APP1 + COM segment after SOI — must not survive. + let exif = b"Exif\0\0SPIKEGPS-LAT51-LON7"; + let com = b"SECRETCOMMENT-nope"; + let mut out = Vec::new(); + out.extend_from_slice(&jpeg[..2]); + out.extend_from_slice(&[0xFF, 0xE1]); + out.extend_from_slice(&((exif.len() + 2) as u16).to_be_bytes()); + out.extend_from_slice(exif); + out.extend_from_slice(&[0xFF, 0xFE]); + out.extend_from_slice(&((com.len() + 2) as u16).to_be_bytes()); + out.extend_from_slice(com); + out.extend_from_slice(&jpeg[2..]); + out + } + + #[test] + fn contract_generations_are_pinned() { + // Commitment bytes, like the delegate's — changing either is a + // migration event (copy-forward is disabled upstream). + let p = FreenetAdapter::contract_ids(PROFILE_CONTRACT_WASM.to_vec(), b"x"); + assert_eq!(p.code_hash, "EeQoECY38qpiHSqMwd4W1KHQMDyRqKqVsq3fV56Me7g4"); + let m = FreenetAdapter::contract_ids(MEDIA_CONTRACT_WASM.to_vec(), b"x"); + assert_eq!(m.code_hash, "6miQr6YTLEzjnoTCr9kFuapQLMq4z2PVqK6QSQzJpotT"); + } + + #[test] + fn normalize_is_deterministic_and_strips_metadata() { + let src = photo_jpeg(); + let a = normalize_avatar(&src).unwrap(); + let b = normalize_avatar(&src).unwrap(); + assert_eq!(a, b, "same input must produce identical bytes"); + assert!(a.len() <= ps::MAX_MEDIA_BYTES); + for pat in [&b"SPIKEGPS"[..], &b"SECRETCOMMENT"[..], &b"Exif"[..]] { + assert!(!a.windows(pat.len()).any(|w| w == pat)); + } + } + + #[test] + fn reader_refuses_lies_and_bombs() { + let png = normalize_avatar(&photo_jpeg()).unwrap(); + let asset = |bytes: Vec, w: u32, h: u32| ps::MediaAssetV1 { + schema_version: ps::SCHEMA_VERSION, + owner: [1; 32], + asset_id: [2; 16], + revision: 1, + media_type: ps::V1_MEDIA_TYPE.into(), + width: w, + height: h, + sanitized_static_bytes: bytes, + sig: vec![0; 64], + }; + // dimension lie + assert!(reader_verify_decode(&asset(png.clone(), 64, 64)).is_err()); + // SVG declared png → sniff refusal + let svg = b"".to_vec(); + assert!(reader_verify_decode(&asset(svg, 256, 256)).is_err()); + // IHDR bomb: tiny bytes claiming 60000x60000 — refused pre-allocation + let mut bomb = png.clone(); + bomb[16..20].copy_from_slice(&60000u32.to_be_bytes()); + bomb[20..24].copy_from_slice(&60000u32.to_be_bytes()); + let mut h = crc32fast::Hasher::new(); + h.update(&bomb[12..29]); + let crc = h.finalize(); + bomb[29..33].copy_from_slice(&crc.to_be_bytes()); + let t0 = std::time::Instant::now(); + assert!(reader_verify_decode(&asset(bomb, 256, 256)).is_err()); + assert!(t0.elapsed().as_millis() < 500, "bomb refusal must be immediate"); + } + + /// Live: needs a local freenet node on 7509. Mutates its persona and + /// profile namespaces — throwaway node only. + /// cargo test -p app --release profile_live -- --ignored + #[tokio::test] + #[ignore = "needs a local freenet node on 7509; mutates persona+profile"] + async fn profile_live_full_loop() { + let adapter = FreenetAdapter::default(); + adapter.enable(); + let mut tries = 0; + while adapter.status() != freenet_adapter::AdapterStatus::Connected { + tokio::time::sleep(std::time::Duration::from_millis(200)).await; + tries += 1; + assert!(tries < 50, "adapter never connected: {:?}", adapter.status()); + } + // Fresh persona for the run. + let _ = persona::remove(&adapter).await; + let created = persona::create(&adapter).await.expect("create persona"); + let owner = decode_owner(&created.public_key).unwrap(); + + // Publish name + bio; read back through the network. + publish_profile(&adapter, owner, "Kyle".into(), "first face".into(), None, None) + .await + .expect("publish"); + let v = view(&adapter, owner, true, None).await.unwrap().expect("view"); + assert_eq!(v.display_name, "Kyle"); + assert_eq!(v.sequence, 1); + assert_eq!(v.avatar_note.as_deref(), Some("none published")); + + // Avatar: temp jpeg → normalize → publish → view carries the PNG. + let dir = std::env::temp_dir().join("soulstream-profile-test"); + std::fs::create_dir_all(&dir).unwrap(); + let img_path = dir.join("source.jpg"); + std::fs::write(&img_path, photo_jpeg()).unwrap(); + let v = set_avatar(&adapter, &img_path.to_string_lossy(), None) + .await + .expect("set avatar"); + assert!(v.avatar_png_base64.is_some(), "note: {:?}", v.avatar_note); + assert_eq!(v.sequence, 2); + + // Policy gate: remote images off → no avatar bytes, honest note. + let v = view(&adapter, owner, false, None).await.unwrap().unwrap(); + assert!(v.avatar_png_base64.is_none()); + assert_eq!(v.avatar_note.as_deref(), Some("remote profile images disabled")); + + // Withdraw: pointer clears; sequence bumps. + let owner_key = owner; + let cur = fetch_profile(&adapter, &owner_key).await.unwrap().unwrap(); + publish_profile(&adapter, owner_key, cur.display_name, cur.bio, None, None) + .await + .expect("clear"); + let v = view(&adapter, owner, true, None).await.unwrap().unwrap(); + assert!(v.avatar_png_base64.is_none()); + assert_eq!(v.sequence, 3); + + adapter.disable(); + let _ = std::fs::remove_file(&img_path); + } +} diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index d50724b..d0204ad 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -9,4 +9,10 @@ pub struct AppState { /// never routes it — so the resolver strips these terms up front instead /// of discovering the silence by timeout. Lowercased on receipt. pub excluded_search_phrases: Mutex>, + /// The experimental Freenet layer's one handle (default: disabled, inert). + /// The privilege boundary: node operations never leave the Rust side. + pub freenet: freenet_adapter::FreenetAdapter, + /// The local Freenet peer THIS app launched (freenet.rs), if any. A node + /// started by hand is not here — the adapter finds it all the same. + pub freenet_node: std::sync::Mutex>, }