Repository: aranya-project/aranya
Pull request #129: 101/create rust example app in example dir
Author: login: smckeon-so
Created: 2025-03-15T16:48:20Z | Merged: 2025-03-28T20:19:02Z

There was some confusion from a client about running the Rust example. This PR adds a Rest example alongside the C example in the examples directory. This will give the user several ways to run a Rust example. 

- Question regarding https://github.com/aranya-project/aranya/pull/107. The way we had the old template dependencies configured, we're pulling from the crate.io releases. Which does not include the afc prefix changes. Do we want to continue with this? Should we instead switch to pulling in the latest `main` changes (use workspace dependencies)? I had to back out the prefix changes.

- This recreates a previous PR. https://github.com/aranya-project/aranya/pull/108

To test cargo generate on this PR branch run `cargo generate aranya-project/aranya --branch 101/Create-rust-example-app-in-example-dir examples/rust --name test-rust-example`

Closes #101, Closes #106 

Linked issue #101: Create a rust example app in the examples directory
Even though we have the rust template, we should also have a rust example app alongside the c example in the examples directory. The user should be able to run this example app from the dir. 

Diff:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 17cdfe9b5..13ac014cf 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -54,3 +54,22 @@ jobs:
         run: |
           export CC=clang
           cargo make run-capi-example
+
+  rust-example-application:
+    strategy:
+      matrix:
+        runner:
+          - ubuntu-latest
+          - ubuntu2404-arm64-4core
+    runs-on: ${{ matrix.runner }}
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Setup Environment
+        uses: ./.github/actions/setup
+
+      - name: Rust Example Application
+        run: |
+          cargo build --release
+          ARANYA_EXAMPLE=info ./target/release/aranya-example
+        working-directory: ./examples/rust
diff --git a/Makefile.toml b/Makefile.toml
index 6df1bd180..6015b8be4 100644
--- a/Makefile.toml
+++ b/Makefile.toml
@@ -250,3 +250,10 @@ description = "Run C example application"
 cwd = "examples/c"
 script = "./run.bash"
 dependencies = ["build-capi-header", "build-capi-lib"]
+
+# Rust Example
+[tasks.run-rust-example]
+category = "examples"
+description = "Run Rust example application"
+cwd = "examples/rust"
+script = "./run.bash"
diff --git a/crates/aranya-client/tests/tests.rs b/crates/aranya-client/tests/tests.rs
index eeda9d9a9..17f82c386 100644
--- a/crates/aranya-client/tests/tests.rs
+++ b/crates/aranya-client/tests/tests.rs
@@ -283,141 +283,6 @@ impl Drop for DeviceCtx {
     }
 }
 
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
-    let sync_interval = Duration::from_millis(100);
-    let sleep_interval = sync_interval * 6;
-
-    let tmp = tempdir()?;
-    let work_dir = tmp.path().to_path_buf();
-
-    let mut team = TeamCtx::new("integration_test".into(), work_dir).await?;
-
-    // create team.
-    let team_id = team
-        .owner
-        .client
-        .create_team()
-        .await
-        .expect("expected to create team");
-    info!(?team_id);
-    // TODO: implement add_team.
-    /*
-    team.admin.client.add_team(team_id).await?;
-    team.operator.client.add_team(team_id).await?;
-    team.membera.client.add_team(team_id).await?;
-    */
-
-    // get sync addresses.
-    let owner_addr = team.owner.aranya_local_addr().await?;
-    let admin_addr = team.admin.aranya_local_addr().await?;
-    let operator_addr = team.operator.aranya_local_addr().await?;
-    let membera_addr = team.membera.aranya_local_addr().await?;
-
-    // setup sync peers.
-    let mut owner_team = team.owner.client.team(team_id);
-    let mut admin_team = team.admin.client.team(team_id);
-    let mut operator_team = team.operator.client.team(team_id);
-    let mut member_team = team.membera.client.team(team_id);
-
-    owner_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    owner_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-    owner_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    admin_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    admin_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-    admin_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    operator_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    operator_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    operator_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    member_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    member_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    member_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-
-    // add admin to team.
-    info!("adding admin to team");
-    owner_team.add_device_to_team(team.admin.pk.clone()).await?;
-    owner_team.assign_role(team.admin.id, Role::Admin).await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // add operator to team.
-    info!("adding operator to team");
-    owner_team
-        .add_device_to_team(team.operator.pk.clone())
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    admin_team
-        .assign_role(team.operator.id, Role::Operator)
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // add member to team.
-    info!("adding member to team");
-    operator_team
-        .add_device_to_team(team.membera.pk.clone())
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // remove devices from team.
-    info!("removing member");
-    owner_team.remove_device_from_team(team.membera.id).await?;
-    info!("removing operator");
-    owner_team
-        .revoke_role(team.operator.id, Role::Operator)
-        .await?;
-    owner_team.remove_device_from_team(team.operator.id).await?;
-    info!("removing admin");
-    owner_team.revoke_role(team.admin.id, Role::Admin).await?;
-    owner_team.remove_device_from_team(team.admin.id).await?;
-
-    Ok(())
-}
-
 #[test(tokio::test(flavor = "multi_thread"))]
 async fn test_afc_one_way_two_chans() -> Result<()> {
     let sync_interval = Duration::from_millis(100);
diff --git a/examples/rust/.gitignore b/examples/rust/.gitignore
new file mode 100644
index 000000000..9b20f1f45
--- /dev/null
+++ b/examples/rust/.gitignore
@@ -0,0 +1,2 @@
+# ignore build files
+target/
diff --git a/templates/aranya-example/Cargo.lock b/examples/rust/Cargo.lock
similarity index 83%
rename from templates/aranya-example/Cargo.lock
rename to examples/rust/Cargo.lock
index 28a2cd81c..36b006f04 100644
--- a/templates/aranya-example/Cargo.lock
+++ b/examples/rust/Cargo.lock
@@ -102,149 +102,99 @@ dependencies = [
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.6"
+version = "3.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
 dependencies = [
  "anstyle",
+ "once_cell",
  "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.94"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
+checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
 
 [[package]]
 name = "aranya-afc-util"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3813c9abf60b265f70c300887908595da2185b45ebe3770f7ca142b409508519"
+checksum = "4facc29a9d9559909391589a8c7222171486204661c936ceb624ecbbf2cbbc0a"
 dependencies = [
  "aranya-crypto",
  "aranya-fast-channels",
  "aranya-policy-vm",
+ "buggy",
  "postcard",
  "serde",
+ "spin",
+ "thiserror 2.0.12",
  "tracing",
 ]
 
-[[package]]
-name = "aranya-base58"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fe988570b39738fd06cee8dfe9141cb1b6511717f9a0c3bb66a806abe8872ef"
-dependencies = [
- "aranya-buggy",
- "byteorder",
-]
-
-[[package]]
-name = "aranya-buggy"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd12ad901a90557f29d9cdfc4486083576b80644e0b9aeaa857e66c644e5cb8f"
-dependencies = [
- "cfg-if",
-]
-
 [[package]]
 name = "aranya-client"
 version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05433dafe99d3a0ca99cafe44f6deef432dcd639000dfbbcc12cd2b09d7927aa"
 dependencies = [
  "anyhow",
- "aranya-base58",
- "aranya-buggy",
  "aranya-crypto",
  "aranya-daemon-api",
  "aranya-fast-channels",
  "aranya-util",
+ "buggy",
  "indexmap",
  "libc",
  "postcard",
  "serde",
+ "spideroak-base58",
  "tarpc",
- "thiserror 2.0.8",
+ "thiserror 2.0.12",
  "tokio",
  "tracing",
 ]
 
 [[package]]
 name = "aranya-crypto"
-version = "0.2.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63e2a4d42208f18e7380a7692ed18b05e9c3342cb4c459be506d952c9848cd6d"
+checksum = "74ae6c36b9b4af1a141ddb91b4cb96dd31543f145390275c2fe8773cc1f5d30b"
 dependencies = [
- "aes-gcm",
- "aranya-base58",
- "aranya-buggy",
- "aranya-crypto-derive",
- "aranya-trouble",
+ "buggy",
  "byteorder",
  "cfg-if",
  "ciborium",
  "ciborium-io",
- "crypto-common",
- "der",
- "ecdsa",
- "ed25519-dalek",
- "elliptic-curve",
- "generic-array 1.1.1",
- "getrandom",
- "more-asserts",
- "p256",
- "p384",
  "postcard",
  "proptest",
- "rand",
- "rand_core",
- "rustix",
+ "rustix 0.38.44",
  "serde",
- "serde_json",
- "sha2",
  "siphasher",
- "spin",
- "subtle",
- "typenum",
- "zeroize",
-]
-
-[[package]]
-name = "aranya-crypto-derive"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7826ccf8d822529d1559a31f988b7e22cd6d26d4e1f951f8eaee086480137b10"
-dependencies = [
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn 2.0.90",
+ "spideroak-base58",
+ "spideroak-crypto",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-crypto-ffi"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3725a117d4162561e0e68b7447c2d4269dd4d6d595ba3deec186a398316c4c2"
+checksum = "e648eef21cca6a42adc27475976092a11066215f673f25440cd37e747df4b9f9"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-vm",
  "postcard",
+ "thiserror 2.0.12",
  "tracing",
 ]
 
 [[package]]
 name = "aranya-daemon"
 version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8b5a4ed7d2986d27e9885aa56035bea5f32d48349c5657c458775917d39f9c7"
 dependencies = [
  "anyhow",
  "aranya-afc-util",
- "aranya-buggy",
  "aranya-crypto",
  "aranya-crypto-ffi",
  "aranya-daemon-api",
@@ -262,6 +212,7 @@ dependencies = [
  "aranya-runtime",
  "aranya-util",
  "bimap",
+ "buggy",
  "ciborium",
  "clap",
  "deser-hjson",
@@ -278,25 +229,23 @@ dependencies = [
 [[package]]
 name = "aranya-daemon-api"
 version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c7cb04b509606a75ecbb52c90cf0bd9994f7d56acc11d38caeb007d8a45d5d0"
 dependencies = [
  "anyhow",
- "aranya-base58",
  "aranya-crypto",
  "aranya-fast-channels",
  "aranya-util",
  "postcard",
  "serde",
+ "spideroak-base58",
  "tarpc",
  "tracing",
 ]
 
 [[package]]
 name = "aranya-device-ffi"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "466e433d52912d920ad2fc7bfa1ce2af0a8eabaa9b19d669eb8c2dc57b3fd58d"
+checksum = "5369c088d32a82874145478ca973b25e076bd251a099b956e84c42e896b17b68"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-vm",
@@ -304,12 +253,13 @@ dependencies = [
 
 [[package]]
 name = "aranya-envelope-ffi"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3674c2d330ab3b02730d37b70be87959d9423be2b8d5cb65afb5403645d4596d"
+checksum = "5039b9a3b4629d5b83ce05485999a83e278d40a668a9ab6483d43b0e87d7146b"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-vm",
+ "thiserror 2.0.12",
  "tracing",
 ]
 
@@ -321,8 +271,10 @@ dependencies = [
  "aranya-client",
  "aranya-daemon",
  "aranya-daemon-api",
+ "aranya-fast-channels",
  "aranya-util",
  "backon",
+ "buggy",
  "tempfile",
  "tokio",
  "tracing",
@@ -331,37 +283,37 @@ dependencies = [
 
 [[package]]
 name = "aranya-fast-channels"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "542a7f86d14ce9605728dfea4428703720173f90a04382a1a04a2bd466c386c0"
+checksum = "72162ccd54603d1d89c0d2f0a46120b924dbef33e19f139f7136bdf31ce8328d"
 dependencies = [
- "aranya-buggy",
  "aranya-crypto",
+ "buggy",
  "byteorder",
  "cfg-if",
  "const_format",
- "heapless",
+ "heapless 0.7.17",
  "libc",
  "serde",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-idam-ffi"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88b3e772751a40b78b93385d32006860608e9959d7445676726ee7d1c89d89df"
+checksum = "33c7c4d763f5e6c7278d4e242bad2a29418dfe50745a881af1aa3152b5fa0231"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-vm",
  "postcard",
+ "thiserror 2.0.12",
  "tracing",
 ]
 
 [[package]]
 name = "aranya-keygen"
 version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0618c7769bcb3772276200aa8cec2a8ea114abd625a5c2c320ec6b6b7246779"
 dependencies = [
  "anyhow",
  "aranya-crypto",
@@ -370,21 +322,22 @@ dependencies = [
 
 [[package]]
 name = "aranya-libc"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d1f49337bfb62452ace5f54ae6b455cc91771c06999cdfc9b7993b76f10b00e"
+checksum = "3014003bd1c0fad20bd014370899786df8686501fa9e6928d7150f524e7b94f7"
 dependencies = [
  "cfg-if",
  "libc",
  "memchr",
+ "thiserror 2.0.12",
  "tracing",
 ]
 
 [[package]]
 name = "aranya-perspective-ffi"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e57ab75824ed06eaa46ad23979d9fbe038a1ce06df381202366e366fe77d42a1"
+checksum = "1124fa3e31e3359448a14161e0430a255cdcc5815be3c3965201ab6c0b93519f"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-vm",
@@ -392,57 +345,60 @@ dependencies = [
 
 [[package]]
 name = "aranya-policy-ast"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52c253270189e1179c074576b26b4b0f4ea7f0591a60159f9770aa516708de7b"
+checksum = "f10783c550254fef5725ef5374fced285e663e3f9fdb2124154496ab6941538c"
 dependencies = [
  "serde",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-policy-compiler"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0be2ad9499e25dae48f2b10340ab3b0797a5e3c477f911cbab105f7de9b5089"
+checksum = "2a47386a864f4146c3edade8ca0c091d0a98dc48a638d5ba1565ebfeac88b562"
 dependencies = [
- "aranya-buggy",
  "aranya-policy-ast",
  "aranya-policy-lang",
  "aranya-policy-module",
+ "buggy",
  "ciborium",
  "clap",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-policy-derive"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a9a80d382fb19584249fca5fbeb9fab46d6b1999496e6c7d7b397821d000d2c"
+checksum = "98722aaa44162551c8e130d55eb4efc304f698e9ec55f3c8cfdef73d75a3acd4"
 dependencies = [
  "aranya-policy-lang",
  "prettyplease",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "aranya-policy-ifgen"
-version = "0.3.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1699aeff39d6a01be03161904361d4b65e958d51db93edbc968111c612e7356"
+checksum = "70b001d8b7d59b8b3885f66a6a0bb0b6317d83beaed59c9301808894f0c946bd"
 dependencies = [
  "aranya-policy-ifgen-macro",
  "aranya-policy-vm",
  "aranya-runtime",
  "serde",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-policy-ifgen-build"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b877a868b8bf1457644b2235d0cfa4dcf988b3738ef1778fb20f0faa7872192c"
+checksum = "5c9b13675bb4b9d1cac7ba45574c741bc4c2da12d550d204ac52885817e165fc"
 dependencies = [
  "anyhow",
  "aranya-policy-ast",
@@ -450,29 +406,29 @@ dependencies = [
  "prettyplease",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "aranya-policy-ifgen-macro"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a34c577253e735d1024b229c1cbe82ff7a613bf0cc966ea7b4d41dd03bf0dda"
+checksum = "125121393e4bdc97794f3e472000a9f0e5db126af2703ea298debc9b98e8ad55"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "aranya-policy-lang"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22b1aca8bc7aa07cb8c4e36fb66f539c9d69ae616f8b322d89711fd8d8b83972"
+checksum = "b9a5776310532328d1ec57bed49981d0fd4dabdc53e6ec44edea7282d249bc0a"
 dependencies = [
  "anyhow",
- "aranya-buggy",
  "aranya-policy-ast",
+ "buggy",
  "clap",
  "markdown",
  "pest",
@@ -483,65 +439,59 @@ dependencies = [
 
 [[package]]
 name = "aranya-policy-module"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a7f86f2c832cc3509b2f723b8e9f664620b0dc44a81770fc1da201d672c4ab8"
+checksum = "fa6b14b907bcf8b6fc4129848db3a29d072a17af0428ad02d17857926f10bf6d"
 dependencies = [
  "aranya-crypto",
  "aranya-policy-ast",
  "serde",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-policy-vm"
-version = "0.3.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d296472f2eb9739c59f3f25cc291584f14d1eaea98d3d57f16f2a64319ffa7"
+checksum = "740d384f4861f7fccc91ca29eeaf592b55046a80dacaa60627fbc7d3f980a0b9"
 dependencies = [
- "aranya-buggy",
  "aranya-crypto",
  "aranya-policy-ast",
  "aranya-policy-derive",
  "aranya-policy-module",
- "heapless",
+ "buggy",
+ "heapless 0.8.0",
  "postcard",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "aranya-runtime"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60c6a8a4e6c7a46a8acd113ac7e1981f6db0c3df654c6535402ca6036363a26a"
+checksum = "d3f4d51aef80587c7780674d841d1427bbe386d5734dc20e1ae91fba5cb57bcf"
 dependencies = [
- "aranya-buggy",
  "aranya-crypto",
  "aranya-libc",
  "aranya-policy-vm",
- "heapless",
+ "buggy",
+ "heapless 0.8.0",
  "postcard",
  "serde",
  "spin",
- "thiserror 2.0.8",
+ "thiserror 2.0.12",
  "tracing",
  "vec1",
  "yoke",
 ]
 
-[[package]]
-name = "aranya-trouble"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c292729db9cbe6ad3c699bae15416c2e0596a9815046b49e27ad5d30ad54732d"
-
 [[package]]
 name = "aranya-util"
 version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df943f3e6a0f398f7fa7d9e024438d2baebd5b347c2fbe2b82f090d34c31977f"
 dependencies = [
  "anyhow",
- "aranya-buggy",
  "aranya-fast-channels",
+ "buggy",
  "serde",
  "tokio",
  "tracing",
@@ -549,13 +499,13 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.83"
+version = "0.1.88"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
+checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -575,9 +525,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "backon"
-version = "1.3.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba5289ec98f68f28dd809fd601059e6aa908bb8f6108620930828283d4ee23d7"
+checksum = "970d91570c01a8a5959b36ad7dd1c30642df24b6b3068710066f6809f7033bb7"
 dependencies = [
  "fastrand",
  "gloo-timers",
@@ -607,9 +557,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
 
 [[package]]
 name = "base64ct"
-version = "1.6.0"
+version = "1.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
 
 [[package]]
 name = "bimap"
@@ -619,9 +569,9 @@ checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7"
 
 [[package]]
 name = "bitflags"
-version = "2.6.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
 
 [[package]]
 name = "block-buffer"
@@ -632,11 +582,20 @@ dependencies = [
  "generic-array 0.14.7",
 ]
 
+[[package]]
+name = "buggy"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a411728d8b4a7e6cbbda3f13a2f202a1fdc7244c14300c1f84c4d1c0139052"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "bumpalo"
-version = "3.16.0"
+version = "3.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 
 [[package]]
 name = "byteorder"
@@ -646,9 +605,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.9.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
 
 [[package]]
 name = "cfg-if"
@@ -695,9 +654,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.23"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
+checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -705,9 +664,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.23"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
+checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
 dependencies = [
  "anstream",
  "anstyle",
@@ -717,14 +676,14 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.18"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
 dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -779,9 +738,9 @@ dependencies = [
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
 dependencies = [
  "libc",
 ]
@@ -794,9 +753,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
 
 [[package]]
 name = "crunchy"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
 
 [[package]]
 name = "crypto-bigint"
@@ -853,7 +812,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -934,7 +893,7 @@ dependencies = [
  "enum-ordinalize",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -959,7 +918,7 @@ dependencies = [
 
 [[package]]
 name = "embedded-io"
-version = "0.5.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
 
@@ -986,14 +945,14 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
 name = "errno"
@@ -1013,9 +972,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
 name = "ff"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
 dependencies = [
  "rand_core",
  "subtle",
@@ -1089,7 +1048,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1153,7 +1112,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi 0.14.2+wasi-0.2.4",
 ]
 
 [[package]]
@@ -1197,9 +1168,9 @@ dependencies = [
 
 [[package]]
 name = "half"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1"
 dependencies = [
  "cfg-if",
  "crunchy",
@@ -1214,6 +1185,15 @@ dependencies = [
  "byteorder",
 ]
 
+[[package]]
+name = "hash32"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
+dependencies = [
+ "byteorder",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.15.2"
@@ -1227,13 +1207,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
 dependencies = [
  "atomic-polyfill",
- "hash32",
+ "hash32 0.2.1",
  "rustc_version",
  "serde",
  "spin",
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "heapless"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
+dependencies = [
+ "hash32 0.3.1",
+ "serde",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "heck"
 version = "0.5.0"
@@ -1260,15 +1251,15 @@ dependencies = [
 
 [[package]]
 name = "humantime"
-version = "2.1.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
 
 [[package]]
 name = "indexmap"
-version = "2.7.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -1276,9 +1267,9 @@ dependencies = [
 
 [[package]]
 name = "inout"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
 dependencies = [
  "generic-array 0.14.7",
 ]
@@ -1291,15 +1282,15 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 
 [[package]]
 name = "itoa"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
 [[package]]
 name = "js-sys"
-version = "0.3.76"
+version = "0.3.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
 dependencies = [
  "once_cell",
  "wasm-bindgen",
@@ -1313,9 +1304,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.169"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 
 [[package]]
 name = "libm"
@@ -1325,9 +1316,15 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.14"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
 
 [[package]]
 name = "lock_api"
@@ -1341,9 +1338,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.22"
+version = "0.4.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
 
 [[package]]
 name = "markdown"
@@ -1371,9 +1368,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.2"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
 dependencies = [
  "adler2",
 ]
@@ -1385,16 +1382,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
 dependencies = [
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys 0.52.0",
 ]
 
-[[package]]
-name = "more-asserts"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fafa6961cabd9c63bcd77a45d7e3b7f3b552b70417831fb0f56db717e72407e"
-
 [[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
@@ -1417,18 +1408,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.36.5"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
 
 [[package]]
 name = "opaque-debug"
@@ -1493,9 +1484,9 @@ dependencies = [
 
 [[package]]
 name = "p384"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
+checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
 dependencies = [
  "ecdsa",
  "elliptic-curve",
@@ -1516,7 +1507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
 dependencies = [
  "memchr",
- "thiserror 2.0.8",
+ "thiserror 2.0.12",
  "ucd-trie",
 ]
 
@@ -1540,7 +1531,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1556,29 +1547,29 @@ dependencies = [
 
 [[package]]
 name = "pin-project"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.15"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
 
 [[package]]
 name = "pin-utils"
@@ -1617,7 +1608,7 @@ dependencies = [
  "cobs",
  "embedded-io 0.4.0",
  "embedded-io 0.6.1",
- "heapless",
+ "heapless 0.7.17",
  "postcard-derive",
  "serde",
 ]
@@ -1635,21 +1626,21 @@ dependencies = [
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.20"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
 dependencies = [
  "zerocopy",
 ]
 
 [[package]]
 name = "prettyplease"
-version = "0.2.25"
+version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb"
 dependencies = [
  "proc-macro2",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1663,9 +1654,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.92"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
 dependencies = [
  "unicode-ident",
 ]
@@ -1688,13 +1679,19 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -1722,7 +1719,7 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.15",
 ]
 
 [[package]]
@@ -1780,7 +1777,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
 [[package]]
 name = "rfc6979"
-version = "0.5.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
 dependencies = [
@@ -1796,7 +1793,7 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 
 [[package]]
 name = "rustc_version"
-version = "0.5.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
 dependencies = [
@@ -1805,22 +1802,41 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.42"
+version = "0.38.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
 dependencies = [
  "bitflags",
  "errno",
  "libc",
- "linux-raw-sys",
+ "linux-raw-sys 0.4.15",
  "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "rustix"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.9.3",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
+
 [[package]]
 name = "ryu"
-version = "1.0.18"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "scopeguard"
@@ -1844,35 +1860,35 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.24"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
 
 [[package]]
 name = "serde"
-version = "1.0.216"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.216"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.133"
+version = "1.0.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
 dependencies = [
  "itoa",
  "memchr",
@@ -1904,6 +1920,15 @@ dependencies = [
  "digest",
 ]
 
+[[package]]
+name = "sha3-utils"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e19df53912f231b1348a1af81c59202ca43d9a1b8d7455ece97c2e17a597f491"
+dependencies = [
+ "typenum",
+]
+
 [[package]]
 name = "sharded-slab"
 version = "0.1.7"
@@ -1940,9 +1965,9 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.13.2"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
 
 [[package]]
 name = "socket2"
@@ -1954,6 +1979,61 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "spideroak-base58"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09b719743eccf9f6ef06ac55f6b315a9c825bf26500b7c703ad7978a92aedf9f"
+dependencies = [
+ "buggy",
+ "byteorder",
+]
+
+[[package]]
+name = "spideroak-crypto"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71b5091ebcf7bc8fc98c07cc571cb1c22e7034d7decd5adb48a86c48f3890ec7"
+dependencies = [
+ "aes-gcm",
+ "buggy",
+ "cfg-if",
+ "crypto-common",
+ "der",
+ "ecdsa",
+ "ed25519-dalek",
+ "elliptic-curve",
+ "generic-array 1.1.1",
+ "getrandom 0.2.15",
+ "p256",
+ "p384",
+ "postcard",
+ "rand",
+ "rand_chacha",
+ "rand_core",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sha3-utils",
+ "spideroak-crypto-derive",
+ "spin",
+ "subtle",
+ "typenum",
+ "zeroize",
+]
+
+[[package]]
+name = "spideroak-crypto-derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17eb41e55e0b7786ee1ab9c618babb79c4d643771c85be8f9dbceb623e1235c"
+dependencies = [
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
 [[package]]
 name = "spin"
 version = "0.9.8"
@@ -2010,9 +2090,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.90"
+version = "2.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2027,7 +2107,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2063,19 +2143,19 @@ checksum = "e0e3d9676af494694e11a3e367a4bfa7f6d1d5566bd0fe9aceb4aa9281122ab8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "tempfile"
-version = "3.14.0"
+version = "3.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
+checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
 dependencies = [
- "cfg-if",
  "fastrand",
+ "getrandom 0.3.2",
  "once_cell",
- "rustix",
+ "rustix 1.0.3",
  "windows-sys 0.59.0",
 ]
 
@@ -2090,11 +2170,11 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "2.0.8"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
 dependencies = [
- "thiserror-impl 2.0.8",
+ "thiserror-impl 2.0.12",
 ]
 
 [[package]]
@@ -2105,18 +2185,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.8"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2131,9 +2211,9 @@ dependencies = [
 
 [[package]]
 name = "tokio"
-version = "1.42.0"
+version = "1.44.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
+checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
 dependencies = [
  "backtrace",
  "bytes",
@@ -2147,13 +2227,13 @@ dependencies = [
 
 [[package]]
 name = "tokio-macros"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2173,9 +2253,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.13"
+version = "0.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
+checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
 dependencies = [
  "bytes",
  "futures-core",
@@ -2205,7 +2285,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2265,9 +2345,9 @@ dependencies = [
 
 [[package]]
 name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 
 [[package]]
 name = "ucd-trie"
@@ -2289,9 +2369,9 @@ checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.14"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-xid"
@@ -2323,9 +2403,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "valuable"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
 
 [[package]]
 name = "vec1"
@@ -2348,36 +2428,46 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.99"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
 dependencies = [
  "cfg-if",
  "once_cell",
+ "rustversion",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.99"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
 dependencies = [
  "bumpalo",
  "log",
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.99"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -2385,22 +2475,25 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.99"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.99"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
 
 [[package]]
 name = "web-time"
@@ -2424,13 +2517,13 @@ dependencies = [
 
 [[package]]
 name = "winapi-i686-pc-windows-gnu"
-version = "0.5.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
-version = "0.5.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
@@ -2516,6 +2609,15 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags",
+]
+
 [[package]]
 name = "yoke"
 version = "0.7.5"
@@ -2536,49 +2638,48 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
  "synstructure",
 ]
 
 [[package]]
 name = "zerocopy"
-version = "0.7.35"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
 dependencies = [
- "byteorder",
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.35"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "zerofrom"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
  "synstructure",
 ]
 
@@ -2599,5 +2700,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.90",
+ "syn 2.0.100",
 ]
diff --git a/templates/aranya-example/Cargo.toml b/examples/rust/Cargo.toml
similarity index 74%
rename from templates/aranya-example/Cargo.toml
rename to examples/rust/Cargo.toml
index ec1f2ac03..77b6fef97 100644
--- a/templates/aranya-example/Cargo.toml
+++ b/examples/rust/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "{{project-name}}"
+name = "aranya-example"
 description = "Example Rust program using the Aranya client library"
 version = "0.1.0"
 authors = ["SpiderOak, Inc."]
@@ -29,20 +29,16 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { path = "../../crates/aranya-client" }
+aranya-daemon = { path = "../../crates/aranya-daemon" }
+aranya-daemon-api = { path = "../../crates/aranya-daemon-api" }
+aranya-fast-channels = { version = "0.5.0", features = ["posix", "std", "memory"] }
+aranya-util = { path = "../../crates/aranya-util" }
 
 anyhow = { version = "1.0.94" }
 backon = { version = "1.3.0" }
+buggy = { version = "0.1.0" }
 tempfile = { version = "3.14.0" }
 tokio = { version = "1.42.0", features = ["io-util", "macros", "net", "sync"] }
 tracing = { version = "0.1.41" }
 tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
-
-[[bin]]
-name = "aranya-example"
-path = "src/main.rs"
-test = false
diff --git a/templates/aranya-example/README.md b/examples/rust/README.md
similarity index 54%
rename from templates/aranya-example/README.md
rename to examples/rust/README.md
index 7aecbb905..85532d586 100644
--- a/templates/aranya-example/README.md
+++ b/examples/rust/README.md
@@ -1,6 +1,6 @@
 # Example Rust Application
 
-This crate contains example code showing how to use Aranya in a Rust application. In order to set it up, you'll need to install [`cargo-generate`](https://crates.io/crates/cargo-generate), which will allow you to create a new Rust project with some boilerplate example code that you can then modify as needed.
+This crate contains example code showing how to use Aranya in a Rust application.
 
 This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
 - [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
@@ -10,37 +10,47 @@ This example shows how to use the [`aranya-client`](../../crates/aranya-client)
 
 During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
 
-# Generate a New Project
-Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`. 
+## Running the example
+We've provided a few different ways to run the Aranya example.
 
+## 1. Running the example with cargo-make
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
 
-Install [cargo-generate](https://crates.io/crates/cargo-generate) using cargo:
-```
-cargo install --locked cargo-generate
-```
+Install [cargo-make](https://github.com/sagiegurari/cargo-make?tab=readme-ov-file#installation) (v0.37.23).
 
-Then, generate a new project from the template, which will prompt you for the name of the new project you wish to create:
-```
-cargo generate aranya-project/aranya templates/aranya-example
-```
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
 
-# Building the Example
+# Change into the directory
+$ cd aranya
 
-You can then build your new project (release mode will provide faster binaries):
-```
-cargo build --release
+# Run the make command
+$ cargo make run-rust-example
 ```
 
-# Running the Example
+This starts the example and automatically runs through the aforementioned
+steps.
 
-Finally, you can run your newly created project[^1]:
-```
-target/release/aranya-example
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
 ```
 
 You can optionally set the [tracing log level](https://docs.rs/tracing/latest/tracing/struct.Level.html#impl-Level) by adding a prefix to the command:
+```bash
+# Run the binary with extra logging:
+$ ARANYA_EXAMPLE=info target/release/aranya-example
 ```
-ARANYA_EXAMPLE=info target/release/aranya-example
-```
-
-[^1]: "aranya-example" is the default binary name, you can change it in the `[[bin]]` section of the `Cargo.toml`.
diff --git a/examples/rust/run.bash b/examples/rust/run.bash
new file mode 100755
index 000000000..e6e5126a7
--- /dev/null
+++ b/examples/rust/run.bash
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
+
+set -xeuo pipefail
+
+# Change into the example directory if needed
+SCRIPT_PATH=$(dirname "$0")
+cd $SCRIPT_PATH
+
+# Build and run the example
+cargo build --release
+./target/release/aranya-example
diff --git a/templates/aranya-example/src/main.rs b/examples/rust/src/main.rs
similarity index 96%
rename from templates/aranya-example/src/main.rs
rename to examples/rust/src/main.rs
index ab973149a..8d87065b8 100644
--- a/templates/aranya-example/src/main.rs
+++ b/examples/rust/src/main.rs
@@ -5,12 +5,13 @@ use std::{
 };
 
 use anyhow::{bail, Context as _, Result};
-use aranya_client::{AfcMsg, Client, Label};
+use aranya_client::{afc::Message, client::Client};
 use aranya_daemon::{
     config::{AfcConfig, Config},
     Daemon,
 };
 use aranya_daemon_api::{DeviceId, KeyBundle, NetIdentifier, Role};
+use aranya_fast_channels::Label;
 use aranya_util::Addr;
 use backon::{ExponentialBuilder, Retryable};
 use buggy::BugExt;
@@ -117,11 +118,11 @@ impl UserCtx {
     }
 
     async fn aranya_local_addr(&self) -> Result<SocketAddr> {
-        Ok(self.client.aranya_local_addr().await?)
+        Ok(self.client.local_addr().await?)
     }
 
-    async fn afc_local_addr(&self) -> Result<SocketAddr> {
-        Ok(self.client.afc_local_addr().await?)
+    async fn afc_local_addr(&mut self) -> Result<SocketAddr> {
+        Ok(self.client.afc().local_addr().await?)
     }
 }
 
@@ -373,7 +374,7 @@ async fn main() -> Result<()> {
     sleep(Duration::from_millis(100)).await;
     do_poll!(team.membera.client, team.memberb.client);
 
-    let Some(AfcMsg { data, label, .. }) = team.memberb.client.afc().try_recv_data() else {
+    let Some(Message { data, label, .. }) = team.memberb.client.afc().try_recv_data() else {
         bail!("no message available!")
     };
     debug!(
@@ -383,7 +384,7 @@ async fn main() -> Result<()> {
         core::str::from_utf8(&data)?
     );
 
-    let Some(AfcMsg { data, label, .. }) = team.memberb.client.afc().try_recv_data() else {
+    let Some(Message { data, label, .. }) = team.memberb.client.afc().try_recv_data() else {
         bail!("no message available!")
     };
     debug!(
diff --git a/templates/README.md b/templates/README.md
deleted file mode 100644
index 9d234fa87..000000000
--- a/templates/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# cargo-generate templates
-
-This folder contains [`cargo-generate`](https://crates.io/crates/cargo-generate) templates.
diff --git a/templates/aranya-example/.gitignore b/templates/aranya-example/.gitignore
deleted file mode 100644
index 8c03474c8..000000000
--- a/templates/aranya-example/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# saves user the hassle of creating their own .gitignore after running `cargo-generate`
-target/


Reviews:
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T01:58:34Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:01:07Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:01:44Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:11:15Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T22:22:11Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T22:31:09Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T22:32:26Z
user: login: smckeon-so
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T23:17:52Z
user: login: smckeon-so
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T23:18:34Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T23:24:34Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T23:26:08Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T23:12:50Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T23:14:29Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T23:15:31Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T23:19:22Z
user: login: smckeon-so
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T17:09:06Z
user: login: smckeon-so
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T17:26:33Z
user: login: nikki-aranya
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T17:27:13Z
user: login: nikki-aranya
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T18:17:43Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:08:55Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:18:13Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:22:55Z
user: login: gknopf-aranya
body: lgtm pending open feedback
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:24:13Z
user: login: smckeon-so
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:31:47Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T16:33:50Z
user: login: djohnson-spideroak
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T14:47:50Z
user: login: djohnson-spideroak
body: LGTM if the integration test isnt removed. I dont see a reason not to keep it.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T14:53:36Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T16:30:03Z
user: login: djohnson-spideroak
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T17:36:33Z
user: login: gknopf-aranya
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T17:51:40Z
user: login: djohnson-spideroak
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T18:40:32Z
user: login: gknopf-aranya
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T18:52:31Z
user: login: ssweetney-spok
body: LGTM. I like that Rust Analyzer works for the example now that it's contained in a proper Rust project
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T20:17:24Z

Review comments:
diff_hunk: @@ -0,0 +1,80 @@
+# Example Rust Application
+
+This crate contains example code showing how to use Aranya in a Rust application.
+
+This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
+- [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
+- [Sync Aranya graphs](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#syncer)
+- [Create an Aranya Fast Channel](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#off-graph-messaging)
+- [Send encrypted data between peers](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#send-messages)
+
+During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
+
+## Running the example
+We've provided a few different ways to run the Aranya example.
+
+## 1. Running the example from a script
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya
+
+# Run the make command
+$ cargo make run-rust-example
+```
+
+This starts the example and automatically runs through the aforementioned
+steps.
+
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
+```
+
+You can optionally set the [tracing log level](https://docs.rs/tracing/latest/tracing/struct.Level.html#impl-Level) by adding a prefix to the command:
+```bash
+# Run the binary with extra logging:
+$ ARANYA_EXAMPLE=info target/release/aranya-example
+```
+
+## 3. Create a project template
+You can also create a standalone project from a template:
+
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+Install [cargo-generate](https://crates.io/crates/cargo-generate) using cargo:
+```bash
+#  Install cargo-generate
+$ cargo install --locked cargo-generate
+```
+
+Navigate to your desired destination parent directory. Then, generate a new project from the template, which will prompt you for the name of the new project you wish to create:
+```bash
+# Create Aranya example project
+$ cargo generate aranya-project/aranya examples/rust
path: examples/rust/README.md
user: login: gknopf-aranya
body: By using `--name` the user would no longer need to manually enter the name of the project:
```suggestion
$ cargo generate aranya-project/aranya examples/rust --name rust-example
```
created_at: 2025-03-18T01:58:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
+
+cargo build --release
path: examples/rust/run.bash
user: login: gknopf-aranya
body: What if `run.bash` is executed in a different directory than `examples/rust`? There is a way to get the directory where the script lives so commands can be executed relative to `examples/rust`, making `cd examples/rust` optional.
https://stackoverflow.com/questions/59895/how-do-i-get-the-directory-where-a-bash-script-is-located-from-within-the-script
created_at: 2025-03-18T02:01:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -124,7 +124,7 @@ impl UserCtx {
     }
 }
 
-/// Repeatedly calls `poll_afc_data`, followed by `handle_afc_data`, until all
+/// Repeatedly calls `poll_data`, followed by `handle_data`, until all
path: examples/rust/src/main.rs
user: login: gknopf-aranya
body: Changes removing `afc` prefix should be reverted.
created_at: 2025-03-18T02:01:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -250,3 +250,10 @@ description = "Run C example application"
 cwd = "examples/c"
 script = "./run.bash"
 dependencies = ["build-capi-header", "build-capi-lib"]
+
+# Rust Example
+[tasks.run-rust-example]
path: Makefile.toml
user: login: gknopf-aranya
body: Let's invoke this from `tests.yml` to add it to ci
created_at: 2025-03-18T02:11:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,20 +29,14 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
path: examples/rust/Cargo.toml
user: login: gknopf-aranya
body: If we use a path here, we can ensure the example/ci job is running on the current checked out branch of the repo rather than `main`.
```suggestion
aranya-client = { path = "../../crates/aranya-client" }
```
@jdygert-spok any better ideas for handling this?
created_at: 2025-03-18T22:22:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,83 @@
+# Example Rust Application
+
+This crate contains example code showing how to use Aranya in a Rust application.
+
+This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
+- [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
+- [Sync Aranya graphs](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#syncer)
+- [Create an Aranya Fast Channel](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#off-graph-messaging)
+- [Send encrypted data between peers](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#send-messages)
+
+During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
+
+## Running the example
+We've provided a few different ways to run the Aranya example.
+
+## 1. Running the example from a script
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya
+
+# Run the make command
+$ cargo make run-rust-example
+```
+
+This starts the example and automatically runs through the aforementioned
+steps.
+
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
+```
+
+You can optionally set the [tracing log level](https://docs.rs/tracing/latest/tracing/struct.Level.html#impl-Level) by adding a prefix to the command:
+```bash
+# Run the binary with extra logging:
+$ ARANYA_EXAMPLE=info target/release/aranya-example
+```
+
+## 3. Create a project template
+You can also create a standalone project from a template:
+
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+Install [cargo-generate](https://crates.io/crates/cargo-generate) using cargo:
+```bash
+#  Install cargo-generate
+$ cargo install --locked cargo-generate
+```
+
+Navigate to your desired destination parent directory. Then, generate a new project from the template, which will prompt you for the name of the new project you wish to create:
+```bash
+# Create Aranya example project
+$ cargo generate aranya-project/aranya examples/rust --name rust-example
path: examples/rust/README.md
user: login: gknopf-aranya
body: It's possible to specify a specific branch or tag to generate the template from. `cargo generate --help`:
```
-b, --branch <BRANCH>
    Branch to use when installing from git
-t, --tag <TAG>
    Tag to use when installing from git
```
created_at: 2025-03-18T22:31:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,20 +29,14 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
path: examples/rust/Cargo.toml
user: login: gknopf-aranya
body: My concern is this may not work when a user is trying to generate a template from the repo without checking out the repo first.
created_at: 2025-03-18T22:32:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,20 +29,14 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
path: examples/rust/Cargo.toml
user: login: smckeon-so
body: The path approach won't work with the cargo-generate command. It will create the new project, but still look for a relative path which wouldn't exist. 

What we may want to do is loose the cargo generate approach all together and just focus on using the aranya-example. Then, we can use relative paths and be able to test the current state of the codebase in CI.
created_at: 2025-03-18T23:17:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,83 @@
+# Example Rust Application
+
+This crate contains example code showing how to use Aranya in a Rust application.
+
+This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
+- [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
+- [Sync Aranya graphs](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#syncer)
+- [Create an Aranya Fast Channel](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#off-graph-messaging)
+- [Send encrypted data between peers](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#send-messages)
+
+During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
+
+## Running the example
+We've provided a few different ways to run the Aranya example.
+
+## 1. Running the example from a script
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya
+
+# Run the make command
+$ cargo make run-rust-example
+```
+
+This starts the example and automatically runs through the aforementioned
+steps.
+
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
+```
+
+You can optionally set the [tracing log level](https://docs.rs/tracing/latest/tracing/struct.Level.html#impl-Level) by adding a prefix to the command:
+```bash
+# Run the binary with extra logging:
+$ ARANYA_EXAMPLE=info target/release/aranya-example
+```
+
+## 3. Create a project template
+You can also create a standalone project from a template:
+
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+Install [cargo-generate](https://crates.io/crates/cargo-generate) using cargo:
+```bash
+#  Install cargo-generate
+$ cargo install --locked cargo-generate
+```
+
+Navigate to your desired destination parent directory. Then, generate a new project from the template, which will prompt you for the name of the new project you wish to create:
+```bash
+# Create Aranya example project
+$ cargo generate aranya-project/aranya examples/rust --name rust-example
path: examples/rust/README.md
user: login: smckeon-so
body: Yeah, that's not an issue 
`cargo generate aranya-project/aranya --branch 101/Create-rust-example-app-in-example-dir examples/rust --name aranya-example`
I use this command for testing.
created_at: 2025-03-18T23:18:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,20 +29,14 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
path: examples/rust/Cargo.toml
user: login: gknopf-aranya
body: I agree that the Rust example is more important than cargo generate working.
If we have a running example, it should be simple enough for a user to copy the example to another project.

Another idea: copy a different `Cargo.toml` file into the template directory when running the example than what's used for the template by default. This would allow `cargo generate` to work as expected and give us more control over what branch is used by `examples/rust` and ci.
If we do this, I'd want to copy the entire template to a temporary directory first that is `.gitignore`'ed so we don't end up checking in the alternate `Cargo.toml` to the template.
created_at: 2025-03-18T23:24:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,20 +29,14 @@ unwrap_used = "warn"
 wildcard_imports = "warn"
 
 [dependencies]
-# To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
path: examples/rust/Cargo.toml
user: login: gknopf-aranya
body: We should check with @mooreoak and @jdygert-spok first before removing the template since `cargo generate` is intended to make it easier for a user to setup an example repo.
created_at: 2025-03-18T23:26:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,54 @@
+# Example Rust Application
+
+This crate contains example code showing how to use Aranya in a Rust application.
+
+This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
+- [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
+- [Sync Aranya graphs](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#syncer)
+- [Create an Aranya Fast Channel](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#off-graph-messaging)
+- [Send encrypted data between peers](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#send-messages)
+
+During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
+
+## Running the example
+We've provided a few different ways to run the Aranya example.
+
+## 1. Running the example from a script
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya
+
+# Run the make command
+$ cargo make run-rust-example
+```
+
+This starts the example and automatically runs through the aforementioned
+steps.
+
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
path: examples/rust/README.md
user: login: gknopf-aranya
body: ```suggestion
# Run the example
$ ./run.bash
```
created_at: 2025-03-20T23:12:50Z
author_association: CONTRIBUTOR
path: examples/rust/src/main.rs
user: login: gknopf-aranya
body: Since this example has been added to ci, we could remove the `integration_test` unit tests as long as they have the same test coverage.
created_at: 2025-03-20T23:14:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,10 +30,10 @@ wildcard_imports = "warn"
 
 [dependencies]
 # To allow `cargo-generate` to work, explicitly define dependency versions rather than importing the repo's workspace `Cargo.toml`.
-aranya-client = { version = "0.5.1" }
-aranya-daemon = { version = "0.5.1" }
-aranya-daemon-api = { version = "0.5.1" }
-aranya-util = { version = "0.5.1" }
+aranya-client = { git = "https://github.com/aranya-project/aranya.git" }
+aranya-daemon = { git = "https://github.com/aranya-project/aranya.git" }
+aranya-daemon-api = { git = "https://github.com/aranya-project/aranya.git" }
+aranya-util = { git = "https://github.com/aranya-project/aranya.git" }
path: templates/aranya-example/Cargo.toml
user: login: gknopf-aranya
body: This change should be reverted. The example will run on the current branch. Template will continue to use released crate versions.
created_at: 2025-03-20T23:15:31Z
author_association: CONTRIBUTOR
path: examples/rust/src/main.rs
user: login: gknopf-aranya
body: Some changes to the `main.rs` for this example are needed to get things to compile:
https://github.com/aranya-project/aranya/actions/runs/13981036203/job/39146150253?pr=129

Looks like afc prefix differences and the user -> device rename.
created_at: 2025-03-20T23:19:22Z
author_association: CONTRIBUTOR
path: examples/rust/src/main.rs
user: login: smckeon-so
body: It was the client API changes
created_at: 2025-03-21T17:09:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,54 @@
+# Example Rust Application
+
+This crate contains example code showing how to use Aranya in a Rust application.
+
+This example shows how to use the [`aranya-client`](../../crates/aranya-client) library to:
+- [Setup a team](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#create-team)
+- [Sync Aranya graphs](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#syncer)
+- [Create an Aranya Fast Channel](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#off-graph-messaging)
+- [Send encrypted data between peers](https://aranya-project.github.io/aranya-docs/getting-started/walkthrough/#send-messages)
+
+During setup, the example application starts an instance of the [`aranya-daemon`](../../crates/aranya-daemon) for each Aranya device in the background. [The daemon](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-daemon) handles low-level operations such as automatically syncing graph states between different devices so that [the client](https://aranya-project.github.io/aranya-docs/technical-apis/rust-api/#aranya-client) can focus on the operations it wants to perform on the team.
+
+## Running the example
+We've provided a few different ways to run the Aranya example.
+
+## 1. Running the example from a script
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya
+
+# Run the make command
+$ cargo make run-rust-example
+```
+
+This starts the example and automatically runs through the aforementioned
+steps.
+
+## 2. Building and running the example manually from the repo
+Install the [Rust toolchain](https://www.rust-lang.org/tools/install), this will install the toolchain manager `rustup`, the rust compiler `rustc` and package manager/build tool `cargo`.
+
+```bash
+# First, download the source code from this repository:
+$ git clone git@github.com:aranya-project/aranya.git
+
+# Change into the directory
+$ cd aranya/examples/rust
+
+# Build the binary
+$ cargo build --release
+
+# Run the binary:
+$ target/release/aranya-example
path: examples/rust/README.md
user: login: smckeon-so
body: I wouldn't add the bash script to this section, we could add
```
# or
$ ./examples/rust/run.bash
```
to the "1. Running the example from a script" section though.
created_at: 2025-03-21T17:26:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,1096 +0,0 @@
-//! Integration tests for the user library.
-
-#![allow(
-    clippy::disallowed_macros,
-    clippy::expect_used,
-    clippy::indexing_slicing,
-    clippy::panic,
-    clippy::unwrap_used,
-    rust_2018_idioms
-)]
-
-use std::{
-    fmt,
-    net::SocketAddr,
-    path::{Path, PathBuf},
-    time::Duration,
-};
-
-use anyhow::{Context, Result};
-use aranya_client::{afc::Message, client::Client};
-use aranya_crypto::{hash::Hash, rust::Sha256};
-use aranya_daemon::{
-    config::{AfcConfig, Config},
-    Daemon,
-};
-use aranya_daemon_api::{DeviceId, KeyBundle, NetIdentifier, Role};
-use aranya_fast_channels::{Label, Seq};
-use aranya_util::addr::Addr;
-use backon::{ExponentialBuilder, Retryable};
-use buggy::BugExt;
-use spideroak_base58::ToBase58;
-use tempfile::tempdir;
-use test_log::test;
-use tokio::{
-    fs,
-    task::{self, AbortHandle},
-    time::{self, Sleep},
-};
-use tracing::{debug, info, instrument};
-
-#[instrument(skip_all, fields(%duration = FmtDuration(d)))]
-fn sleep(d: Duration) -> Sleep {
-    debug!("sleeping");
-
-    time::sleep(d)
-}
-
-/// Formats a [`Duration`].
-///
-/// It uses the same syntax as Go's `time.Duration`.
-pub struct FmtDuration(Duration);
-
-impl fmt::Display for FmtDuration {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.0 < Duration::ZERO {
-            write!(f, "-")?;
-        }
-        // Same as
-        //    let mut d self.0.abs_diff(Duration::ZERO);
-        // but for MSRV <= 1.80.
-        let mut d = if let Some(res) = self.0.checked_sub(Duration::ZERO) {
-            res
-        } else {
-            Duration::ZERO.checked_sub(self.0).unwrap()
-        };
-
-        // Small number, format it with small units.
-        if d < Duration::from_secs(1) {
-            if d.is_zero() {
-                return write!(f, "0s");
-            }
-
-            const MICROSECOND: u128 = 1000;
-            const MILLISECOND: u128 = 1000 * MICROSECOND;
-
-            // NB: the unwrap and error cases should never happen
-            // since `d` is less than one second.
-            let ns = d.as_nanos();
-            if ns < MICROSECOND {
-                return write!(f, "{ns}ns");
-            }
-
-            let (v, width, fmt) = if ns < MILLISECOND {
-                (MICROSECOND, 3, "µs")
-            } else {
-                (MILLISECOND, 6, "ms")
-            };
-
-            let quo = ns / v;
-            let rem = ns % v;
-            write!(f, "{quo}")?;
-            if rem > 0 {
-                let (rem, width) = trim(rem, width);
-                write!(f, ".{rem:0width$}")?;
-            }
-            return write!(f, "{fmt}");
-        }
-
-        let hours = d.as_secs() / 3600;
-        if hours > 0 {
-            write!(f, "{hours}h")?;
-            d -= Duration::from_secs(hours * 3600);
-        }
-
-        let mins = d.as_secs() / 60;
-        if mins > 0 {
-            write!(f, "{mins}m")?;
-            d -= Duration::from_secs(mins * 60);
-        }
-
-        let secs = d.as_secs();
-        write!(f, "{secs}")?;
-        d -= Duration::from_secs(secs);
-
-        if !d.is_zero() {
-            // NB: the unwrap and error cases should never happen
-            // since `d` is less than one second.
-            let (ns, width) = trim(d.as_nanos(), 9);
-            write!(f, ".{ns:0width$}")?;
-        }
-        write!(f, "s")
-    }
-}
-
-/// Trim up to `width` trailing zeros from `d`.
-fn trim(mut d: u128, mut width: usize) -> (u128, usize) {
-    while width > 0 {
-        if d % 10 != 0 {
-            break;
-        }
-        d /= 10;
-        width -= 1;
-    }
-    (d, width)
-}
-
-/// Repeatedly calls `poll_data`, followed by `handle_data`, until all of the
-/// clients are pending.
-// TODO(nikki): alternative to select!{} to resolve lifetime issues
-macro_rules! do_poll {
-    ($($client:expr),*) => {
-        debug!(
-            clients = stringify!($($client),*),
-            "start `do_poll`",
-        );
-        loop {
-            let mut afcs = [ $($client.afc()),* ];
-            let mut afcs = afcs.iter_mut();
-            tokio::select! {
-                biased;
-                $(data = afcs.next().assume("macro enforces client count")?.poll_data() => {
-                    $client.afc().handle_data(data?).await?
-                },)*
-                _ = async {} => break,
-            }
-        }
-        debug!(
-            clients = stringify!($($client),*),
-            "finish `do_poll`",
-        );
-    };
-}
-
-struct TeamCtx {
-    owner: DeviceCtx,
-    admin: DeviceCtx,
-    operator: DeviceCtx,
-    membera: DeviceCtx,
-    memberb: DeviceCtx,
-}
-
-impl TeamCtx {
-    pub async fn new(name: String, work_dir: PathBuf) -> Result<Self> {
-        let owner = DeviceCtx::new(name.clone(), "owner".into(), work_dir.join("owner")).await?;
-        let admin = DeviceCtx::new(name.clone(), "admin".into(), work_dir.join("admin")).await?;
-        let operator =
-            DeviceCtx::new(name.clone(), "operator".into(), work_dir.join("operator")).await?;
-        let membera =
-            DeviceCtx::new(name.clone(), "membera".into(), work_dir.join("membera")).await?;
-        let memberb =
-            DeviceCtx::new(name.clone(), "memberb".into(), work_dir.join("memberb")).await?;
-
-        Ok(Self {
-            owner,
-            admin,
-            operator,
-            membera,
-            memberb,
-        })
-    }
-}
-
-struct DeviceCtx {
-    client: Client,
-    pk: KeyBundle,
-    id: DeviceId,
-    daemon: AbortHandle,
-}
-
-impl DeviceCtx {
-    pub async fn new(team_name: String, name: String, work_dir: PathBuf) -> Result<Self> {
-        fs::create_dir_all(work_dir.clone()).await?;
-
-        let mut shm_path = format!("/{team_name}_{name}");
-        if cfg!(target_os = "macos") && shm_path.len() > 31 {
-            // Shrink the size of the team name down to 22 bytes
-            // to work within macOS's limits.
-            let d = Sha256::hash(shm_path.as_bytes());
-            let t: [u8; 16] = d[..16].try_into().unwrap();
-            shm_path = format!("/{}", t.to_base58())
-        };
-
-        // Setup daemon config.
-        let uds_api_path = work_dir.join("uds.sock");
-        let max_chans = 100;
-        let cfg = Config {
-            name: "daemon".into(),
-            work_dir: work_dir.clone(),
-            uds_api_path: uds_api_path.clone(),
-            pid_file: work_dir.join("pid"),
-            sync_addr: Addr::new("localhost", 0)?,
-            afc: AfcConfig {
-                shm_path: shm_path.clone(),
-                unlink_on_startup: true,
-                unlink_at_exit: true,
-                create: true,
-                max_chans,
-            },
-        };
-        // Load daemon from config.
-        let daemon = Daemon::load(cfg.clone())
-            .await
-            .context("unable to init daemon")?;
-        // Start daemon.
-        let handle = task::spawn(async move {
-            daemon
-                .run()
-                .await
-                .expect("expected no errors running daemon")
-        })
-        .abort_handle();
-        // give daemon time to setup UDS API.
-        sleep(Duration::from_millis(100)).await;
-
-        // Initialize the user library.
-        let mut client = (|| {
-            Client::connect(
-                &uds_api_path,
-                Path::new(&shm_path),
-                max_chans,
-                "localhost:0",
-            )
-        })
-        .retry(ExponentialBuilder::default())
-        .await
-        .context("unable to init client")?;
-        client.afc().set_name(name);
-
-        // Get device id and key bundle.
-        let pk = client.get_key_bundle().await.expect("expected key bundle");
-        let id = client.get_device_id().await.expect("expected device id");
-
-        Ok(Self {
-            client,
-            pk,
-            id,
-            daemon: handle,
-        })
-    }
-
-    async fn aranya_local_addr(&self) -> Result<SocketAddr> {
-        Ok(self.client.local_addr().await?)
-    }
-
-    async fn afc_local_addr(&mut self) -> Result<SocketAddr> {
-        Ok(self.client.afc().local_addr().await?)
-    }
-}
-
-impl Drop for DeviceCtx {
-    fn drop(&mut self) {
-        self.daemon.abort();
-    }
-}
-
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
-    let sync_interval = Duration::from_millis(100);
-    let sleep_interval = sync_interval * 6;
-
-    let tmp = tempdir()?;
-    let work_dir = tmp.path().to_path_buf();
-
-    let mut team = TeamCtx::new("integration_test".into(), work_dir).await?;
-
-    // create team.
-    let team_id = team
-        .owner
-        .client
-        .create_team()
-        .await
-        .expect("expected to create team");
-    info!(?team_id);
-    // TODO: implement add_team.
-    /*
-    team.admin.client.add_team(team_id).await?;
-    team.operator.client.add_team(team_id).await?;
-    team.membera.client.add_team(team_id).await?;
-    */
-
-    // get sync addresses.
-    let owner_addr = team.owner.aranya_local_addr().await?;
-    let admin_addr = team.admin.aranya_local_addr().await?;
-    let operator_addr = team.operator.aranya_local_addr().await?;
-    let membera_addr = team.membera.aranya_local_addr().await?;
-
-    // setup sync peers.
-    let mut owner_team = team.owner.client.team(team_id);
-    let mut admin_team = team.admin.client.team(team_id);
-    let mut operator_team = team.operator.client.team(team_id);
-    let mut member_team = team.membera.client.team(team_id);
-
-    owner_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    owner_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-    owner_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    admin_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    admin_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-    admin_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    operator_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    operator_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    operator_team
-        .add_sync_peer(membera_addr.into(), sync_interval)
-        .await?;
-
-    member_team
-        .add_sync_peer(owner_addr.into(), sync_interval)
-        .await?;
-    member_team
-        .add_sync_peer(admin_addr.into(), sync_interval)
-        .await?;
-    member_team
-        .add_sync_peer(operator_addr.into(), sync_interval)
-        .await?;
-
-    // add admin to team.
-    info!("adding admin to team");
-    owner_team.add_device_to_team(team.admin.pk.clone()).await?;
-    owner_team.assign_role(team.admin.id, Role::Admin).await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // add operator to team.
-    info!("adding operator to team");
-    owner_team
-        .add_device_to_team(team.operator.pk.clone())
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    admin_team
-        .assign_role(team.operator.id, Role::Operator)
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // add member to team.
-    info!("adding member to team");
-    operator_team
-        .add_device_to_team(team.membera.pk.clone())
-        .await?;
-
-    // wait for syncing.
-    sleep(sleep_interval).await;
-
-    // remove devices from team.
-    info!("removing member");
-    owner_team.remove_device_from_team(team.membera.id).await?;
-    info!("removing operator");
-    owner_team
-        .revoke_role(team.operator.id, Role::Operator)
-        .await?;
-    owner_team.remove_device_from_team(team.operator.id).await?;
-    info!("removing admin");
-    owner_team.revoke_role(team.admin.id, Role::Admin).await?;
-    owner_team.remove_device_from_team(team.admin.id).await?;
-
-    Ok(())
-}
-
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn test_afc_one_way_two_chans() -> Result<()> {
path: crates/aranya-client/tests/tests.rs
user: login: gknopf-aranya
body: Removing `integration_test` is okay because that is covered by the Rust example.
However, the other tests in this file are testing cases that the example does not so we should leave them in.
created_at: 2025-03-24T16:08:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
path: examples/rust/run.bash
user: login: gknopf-aranya
body: We usually add this to the beginning of bash scripts to make them easier to debug:
```suggestion
#!/usr/bin/env bash

# Copyright (c) SpiderOak, Inc. All rights reserved.

set -xeuo pipefail
```
created_at: 2025-03-24T16:18:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
+
+# Change into the example directory if needed
+SCRIPT_PATH=$(dirname "$0")
+cd $SCRIPT_PATH
+
+# Build and run the example
+cargo build --release
+./target/release/aranya-example
path: examples/rust/run.bash
user: login: gknopf-aranya
body: The output in the ci run is not very verbose. Ideally, we want to print out enough info to troubleshoot ci failures.
```suggestion
ARANYA_EXAMPLE=info ./target/release/aranya-example
```
created_at: 2025-03-24T16:22:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
+
+# Change into the example directory if needed
+SCRIPT_PATH=$(dirname "$0")
+cd $SCRIPT_PATH
+
+# Build and run the example
+cargo build --release
+./target/release/aranya-example
path: examples/rust/run.bash
user: login: smckeon-so
body: Yes, but one of the goals with this example is to make things easier on the new user. This verbose output ran in that context can be a bit overwhelming. We could just run the info logging level in CI though. 
created_at: 2025-03-24T16:31:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+# Copyright (c) SpiderOak, Inc. All rights reserved.
+
+# Change into the example directory if needed
+SCRIPT_PATH=$(dirname "$0")
+cd $SCRIPT_PATH
+
+# Build and run the example
+cargo build --release
+./target/release/aranya-example
path: examples/rust/run.bash
user: login: gknopf-aranya
body: Yep, we'll want it to be verbose in CI
created_at: 2025-03-24T16:33:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,141 +283,6 @@ impl Drop for DeviceCtx {
     }
 }
 
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
path: crates/aranya-client/tests/tests.rs
user: login: djohnson-spideroak
body: do we know why this was being removed? edit: I see, the example is covering the same test essentially. I still think it should probably stay though
created_at: 2025-03-28T14:47:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,141 +283,6 @@ impl Drop for DeviceCtx {
     }
 }
 
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
path: crates/aranya-client/tests/tests.rs
user: login: gknopf-aranya
body: The integration test is being removed because the Rust example serves the same purpose (we were previously copying the same code into both places). The example is a better integration test anyways since it uses the Rust API in exactly the same way an application would.
The downside is that the example needs to maintain full test coverage just like an integration test would (which isn't really a much of a downside because it guarantees we're showing users how to use all the APIs). The upside is less maintenance.
created_at: 2025-03-28T16:30:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,141 +283,6 @@ impl Drop for DeviceCtx {
     }
 }
 
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
path: crates/aranya-client/tests/tests.rs
user: login: djohnson-spideroak
body: If the example is run during CI/tests, then its fine with me.
created_at: 2025-03-28T17:36:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,141 +283,6 @@ impl Drop for DeviceCtx {
     }
 }
 
-/// Integration test for the user library and daemon.
-/// Tests creating a team with the user library.
-/// More extensive integration testing is conducted inside the daemon crate.
-/// The goal of this integration test is to validate the user library's end-to-end functionality.
-/// This includes exercising the user library's idiomatic Rust API as well as the daemon's `tarpc` API.
-///
-/// Example of debugging test with tracing:
-/// `RUST_LOG="debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client::afc=debug" cargo test integration_test -- --show-output --nocapture`
-/// `RUST_LOG="aranya_client=debug,aranya_daemon=info" cargo test integration_test -- --show-output --nocapture`
-#[test(tokio::test(flavor = "multi_thread"))]
-async fn integration_test() -> Result<()> {
path: crates/aranya-client/tests/tests.rs
user: login: gknopf-aranya
body: The example ran in CI here:
https://github.com/aranya-project/aranya/actions/runs/14118108472/job/39552925911?pr=129
created_at: 2025-03-28T17:51:40Z
author_association: CONTRIBUTOR

PR comments:
user: login: nikki-aranya
created_at: 2025-03-17T17:30:51Z
body: As discussed previously, we should probably just pin the aranya crate dependencies to git, so eventually we can run the example in CI and see if any breakage occurred. 
author_association: CONTRIBUTOR
user: login: gknopf-aranya
created_at: 2025-03-17T20:06:49Z
body: I'd prefer the example run on whatever the current branch of the checked out repo is by default.
Instructions/arguments can be provided for how to run on a specific branch/commit.
We'll want a CI workflow to be able to easily run the example on whatever branch is being tested in CI.
author_association: CONTRIBUTOR
user: login: gknopf-aranya
created_at: 2025-03-18T02:04:01Z
body: I'm leaning towards keeping the template at `templates/aranya-example` while the `examples/rust/run.bash` script uses that template to execute the example.
Rather than moving the template to `examples/rust`.
The example could generate the template at `examples/rust/aranya-example` and add that directory to `examples/rust/.gitignore`.

To me, this would strike a good balance between the `examples` and `templates` directory conventions.
author_association: CONTRIBUTOR
user: login: gknopf-aranya
created_at: 2025-03-24T16:27:49Z
body: This could use review from @djohnson-spideroak, @jdygert-spok, or @elagergren-spideroak 
author_association: CONTRIBUTOR
user: login: jdygert-spok
created_at: 2025-03-28T21:27:51Z
body: There's some stale links in the main readme 
author_association: CONTRIBUTOR
user: login: gknopf-aranya
created_at: 2025-03-28T22:32:41Z
body: > There's some stale links in the main readme

Opened a PR to fix that:
https://github.com/aranya-project/aranya/pull/161
author_association: CONTRIBUTOR