From 253686b62867b0265f2555bf5d83bdd102d87604 Mon Sep 17 00:00:00 2001 From: jm Date: Wed, 14 Oct 2026 20:49:44 +0000 Subject: [PATCH] test(relay): align managed-memory golden codec Co-authored-by: Codex Signed-off-by: jm Co-authored-by: Codex --- .../examples/generate_ifc_fixture.rs | 93 ++++++++++++----- crates/buzz-relay/src/ifc.rs | 99 +++++++++++++++++-- .../ifc-managed-memory-v2-fields.json | 1 + .../ifc-managed-memory-v2-plaintext.json | 1 + .../tests/fixtures/ifc-v1-golden.json | 54 +++++++--- 5 files changed, 208 insertions(+), 40 deletions(-) create mode 100644 crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-fields.json create mode 100644 crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-plaintext.json diff --git a/crates/buzz-relay/examples/generate_ifc_fixture.rs b/crates/buzz-relay/examples/generate_ifc_fixture.rs index c996681432..ac661e6bf1 100644 --- a/crates/buzz-relay/examples/generate_ifc_fixture.rs +++ b/crates/buzz-relay/examples/generate_ifc_fixture.rs @@ -3,9 +3,20 @@ use hmac::{Hmac, Mac}; use nostr::nips::nip44::v2; use nostr::secp256k1::rand::RngCore; use nostr::{EventBuilder, Keys, Kind, Tag, Timestamp}; -use serde_json::json; +use serde_json::{json, Value}; use sha2::{Digest, Sha256}; +const MANAGED_MEMORY_PLAINTEXT: &str = + include_str!("../tests/fixtures/ifc-managed-memory-v2-plaintext.json"); +const MANAGED_MEMORY_FIELDS: &str = + include_str!("../tests/fixtures/ifc-managed-memory-v2-fields.json"); + +fn required_string<'a>(value: &'a Value, field: &str) -> anyhow::Result<&'a str> { + value[field] + .as_str() + .ok_or_else(|| anyhow::anyhow!("managed-memory field {field} must be a string")) +} + struct FixedNonce(u8); impl RngCore for FixedNonce { @@ -93,40 +104,73 @@ fn main() -> anyhow::Result<()> { .custom_created_at(Timestamp::from(1_791_999_900u64)) .build(broker.public_key()) .sign_with_ctx(nostr::SECP256K1, &mut FixedNonce(0x23), &broker)?; - let memory_slug = "mem/fixture"; let memory_key = v2::ConversationKey::derive(broker.secret_key(), &broker.public_key())?; - let mut audience_principals = [human.public_key().to_hex(), broker.public_key().to_hex()]; - audience_principals.sort(); - let audience_bytes = serde_json::to_vec(&json!([ - community, - broker.public_key().to_hex(), - human.public_key().to_hex(), - "restricted", - audience_principals - ]))?; + let memory_fields: Value = serde_json::from_str(MANAGED_MEMORY_FIELDS)?; + let broker_pubkey = broker.public_key().to_hex(); + let owner = human.public_key().to_hex(); + anyhow::ensure!(memory_fields["format"] == "buzz-ifc-managed-memory-golden-fields"); + anyhow::ensure!(memory_fields["version"] == 1); + anyhow::ensure!(memory_fields["envelope_version"] == 2); + anyhow::ensure!(memory_fields["community"] == community); + anyhow::ensure!(memory_fields["source_conversation"] == source); + anyhow::ensure!(memory_fields["source_generation"] == "17"); + anyhow::ensure!(memory_fields["agent_pubkey"] == broker_pubkey); + anyhow::ensure!(memory_fields["human_owner_pubkey"] == owner); + anyhow::ensure!(memory_fields["audience"] == json!([owner])); + anyhow::ensure!(memory_fields["recipient_pubkey"] == broker_pubkey); + anyhow::ensure!(memory_fields["p"] == broker_pubkey); + anyhow::ensure!(memory_fields["kind"] == 30174); + anyhow::ensure!(memory_fields["expected_revision"] == "none"); + + let plaintext_sha256 = hex::encode(Sha256::digest(MANAGED_MEMORY_PLAINTEXT.as_bytes())); + anyhow::ensure!(memory_fields["plaintext_sha256"] == plaintext_sha256); + let scope_canonical_json = required_string(&memory_fields, "canonical_scope_utf8")?; + anyhow::ensure!( + serde_json::from_str::(scope_canonical_json)? + == json!([community, broker_pubkey, owner, "restricted", [owner]]) + ); let mut scope = as hmac::digest::KeyInit>::new_from_slice(memory_key.as_bytes())?; scope.update(b"agent-memory/ifc/v1/scope"); scope.update(&[0]); - scope.update(&audience_bytes); + scope.update(scope_canonical_json.as_bytes()); let memory_namespace = hex::encode(scope.finalize().into_bytes()); + anyhow::ensure!(memory_fields["namespace"] == memory_namespace); + anyhow::ensure!(memory_fields["s"] == memory_namespace); + + let logical_slug = required_string(&memory_fields, "logical_slug")?; + let mut memory_name_hmac = + as hmac::digest::KeyInit>::new_from_slice(memory_key.as_bytes())?; + memory_name_hmac.update(b"agent-memory/ifc/v1/name"); + memory_name_hmac.update(&[0]); + memory_name_hmac.update(logical_slug.as_bytes()); + let memory_name = hex::encode(memory_name_hmac.finalize().into_bytes()); + anyhow::ensure!(memory_fields["name"] == memory_name); + let memory_slug = format!("mem/ifc1/{memory_namespace}/{memory_name}"); + anyhow::ensure!(memory_fields["physical_slug"] == memory_slug); + let mut memory_address = as hmac::digest::KeyInit>::new_from_slice(memory_key.as_bytes())?; memory_address.update(b"agent-memory/v1/d-tag"); memory_address.update(&[0]); memory_address.update(memory_slug.as_bytes()); let memory_d = hex::encode(memory_address.finalize().into_bytes()); - let memory_plaintext = format!( - "{{\"slug\":\"{memory_slug}\",\"value\":\"fixture protected memory\",\"ifc\":{{\"version\":1,\"community_id\":\"{community}\",\"sources\":[{{\"channel_id\":\"{source}\",\"generation\":\"17\"}}],\"provenance\":[{{\"event_id\":\"{}\"}}]}}}}", - resource.id.to_hex() + anyhow::ensure!(memory_fields["identifier"] == memory_d); + anyhow::ensure!(memory_fields["d"] == memory_d); + let protected_memory: Value = serde_json::from_str(MANAGED_MEMORY_PLAINTEXT)?; + anyhow::ensure!(protected_memory["slug"] == memory_slug); + anyhow::ensure!(protected_memory["ifc"]["version"] == 2); + anyhow::ensure!(protected_memory["ifc"]["logical_slug"] == logical_slug); + anyhow::ensure!(protected_memory["ifc"]["agent_pubkey"] == broker_pubkey); + anyhow::ensure!(protected_memory["ifc"]["human_owner_pubkey"] == owner); + anyhow::ensure!( + protected_memory["ifc"]["derivation_event_ids"] == json!([resource.id.to_hex()]) ); let memory_payload = v2::encrypt_to_bytes_with_rng( &mut FixedNonce(0x44), &memory_key, - memory_plaintext.as_bytes(), + MANAGED_MEMORY_PLAINTEXT.as_bytes(), )?; let memory_ciphertext = base64::engine::general_purpose::STANDARD.encode(memory_payload); - let owner = human.public_key().to_hex(); - let broker_pubkey = broker.public_key().to_hex(); let managed_memory = EventBuilder::new(Kind::Custom(30174), memory_ciphertext) .tags([ Tag::parse(["d", memory_d.as_str()])?, @@ -178,14 +222,19 @@ fn main() -> anyhow::Result<()> { "channel_publication_event": publication, "managed_memory": { "event": managed_memory, - "canonical_slug": memory_slug, + "logical_slug": logical_slug, + "physical_slug": memory_slug, + "name": memory_name, "d_tag": memory_d, "namespace": memory_namespace, "recipient": broker_pubkey, "saved_human_owner": owner, - "scope_canonical_json_utf8": String::from_utf8(audience_bytes)?, - "plaintext_utf8": memory_plaintext, - "application_metadata_status": "illustrative until the exact Kotlin protected version-two object is supplied" + "human_readers": memory_fields["audience"], + "scope_canonical_json_utf8": scope_canonical_json, + "plaintext_utf8": MANAGED_MEMORY_PLAINTEXT, + "plaintext_sha256": plaintext_sha256, + "application_fields": memory_fields, + "application_metadata_status": "actual interim Kotlin version-two export; immutable contributing-source provenance is not yet frozen" }, "owner_telemetry": { "event": owner_telemetry, diff --git a/crates/buzz-relay/src/ifc.rs b/crates/buzz-relay/src/ifc.rs index a102765eff..c72549c017 100644 --- a/crates/buzz-relay/src/ifc.rs +++ b/crates/buzz-relay/src/ifc.rs @@ -507,6 +507,20 @@ mod tests { #[test] fn golden_fixture_has_valid_signatures_and_exact_request_digest() { let fixture_text = include_str!("../tests/fixtures/ifc-v1-golden.json"); + let managed_plaintext = + include_str!("../tests/fixtures/ifc-managed-memory-v2-plaintext.json"); + let managed_fields_text = + include_str!("../tests/fixtures/ifc-managed-memory-v2-fields.json"); + assert_eq!( + hex::encode(Sha256::digest(managed_plaintext.as_bytes())), + "531b1a1093050826f6f7556c344d3d4b6bf1464c2281d8c9fdf5ae8c6e2148b7" + ); + assert_eq!( + hex::encode(Sha256::digest(managed_fields_text.as_bytes())), + "7b1e786fe7407b910c1b53995613b61d59f6465a56feb342b39ce57e31004397" + ); + let managed_fields: Value = + serde_json::from_str(managed_fields_text).expect("managed-memory fields"); assert!(!fixture_text.contains("REPLACE_WITH")); let fixture: Value = serde_json::from_str(fixture_text).expect("parse fixture"); let request = fixture["request_body_utf8"] @@ -597,6 +611,33 @@ mod tests { fixture["managed_memory"]["saved_human_owner"], human.public_key().to_hex() ); + assert_eq!( + fixture["managed_memory"]["application_fields"], + managed_fields + ); + assert_eq!( + fixture["managed_memory"]["human_readers"], + serde_json::json!([human.public_key().to_hex()]) + ); + assert_ne!( + fixture["managed_memory"]["human_readers"], + serde_json::json!([broker.public_key().to_hex()]) + ); + assert_eq!( + serde_json::from_str::( + fixture["managed_memory"]["scope_canonical_json_utf8"] + .as_str() + .expect("canonical scope bytes") + ) + .expect("canonical scope JSON"), + serde_json::json!([ + "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", + broker.public_key().to_hex(), + human.public_key().to_hex(), + "restricted", + [human.public_key().to_hex()] + ]) + ); assert_eq!( memory .tags @@ -608,9 +649,9 @@ mod tests { assert_eq!( d_tag( &memory_key, - fixture["managed_memory"]["canonical_slug"] + fixture["managed_memory"]["physical_slug"] .as_str() - .expect("memory slug") + .expect("physical memory slug") ), expected_d ); @@ -629,16 +670,60 @@ mod tests { hex::encode(namespace_hmac.finalize().into_bytes()), expected_namespace ); + let logical_slug = fixture["managed_memory"]["logical_slug"] + .as_str() + .expect("logical memory slug"); + let mut name_hmac = + as hmac::digest::KeyInit>::new_from_slice(memory_key.as_bytes()) + .expect("name HMAC key"); + name_hmac.update(b"agent-memory/ifc/v1/name"); + name_hmac.update(&[0]); + name_hmac.update(logical_slug.as_bytes()); + assert_eq!( + hex::encode(name_hmac.finalize().into_bytes()), + fixture["managed_memory"]["name"] + ); + assert_eq!( + fixture["managed_memory"]["physical_slug"], + format!( + "mem/ifc1/{expected_namespace}/{}", + fixture["managed_memory"]["name"] + .as_str() + .expect("memory name") + ) + ); let payload = base64::engine::general_purpose::STANDARD .decode(memory.content.as_bytes()) .expect("memory base64"); let plaintext = v2::decrypt_to_bytes(&memory_key, &payload).expect("memory decrypt"); + assert_eq!(plaintext, managed_plaintext.as_bytes()); assert_eq!( - plaintext, - fixture["managed_memory"]["plaintext_utf8"] - .as_str() - .expect("memory plaintext") - .as_bytes() + fixture["managed_memory"]["plaintext_utf8"], + managed_plaintext + ); + assert_eq!( + fixture["managed_memory"]["plaintext_sha256"], + hex::encode(Sha256::digest(managed_plaintext.as_bytes())) + ); + let protected_memory: Value = + serde_json::from_slice(&plaintext).expect("protected managed memory"); + assert_eq!( + protected_memory["slug"], + fixture["managed_memory"]["physical_slug"] + ); + assert_eq!(protected_memory["ifc"]["version"], 2); + assert_eq!(protected_memory["ifc"]["logical_slug"], logical_slug); + assert_eq!( + protected_memory["ifc"]["agent_pubkey"], + broker.public_key().to_hex() + ); + assert_eq!( + protected_memory["ifc"]["human_owner_pubkey"], + human.public_key().to_hex() + ); + assert_eq!( + protected_memory["ifc"]["derivation_event_ids"], + serde_json::json!([resource.id.to_hex()]) ); let owner_key = conversation_key(human.secret_key(), &broker.public_key()); assert!(v2::decrypt_to_bytes(&owner_key, &payload).is_err()); diff --git a/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-fields.json b/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-fields.json new file mode 100644 index 0000000000..28be4786a0 --- /dev/null +++ b/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-fields.json @@ -0,0 +1 @@ +{"format":"buzz-ifc-managed-memory-golden-fields","version":1,"envelope_version":2,"community":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","source_conversation":"11111111-1111-4111-8111-111111111111","source_generation":"17","agent_pubkey":"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","human_owner_pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","audience":["c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"],"canonical_scope_utf8":"[\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"restricted\",[\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\"]]","namespace":"2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640","s":"2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640","logical_slug":"mem/ifc-golden","physical_slug":"mem/ifc1/2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640/506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160","name":"506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160","identifier":"a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343","d":"a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343","kind":30174,"recipient_pubkey":"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","p":"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","expected_revision":"none","plaintext_sha256":"531b1a1093050826f6f7556c344d3d4b6bf1464c2281d8c9fdf5ae8c6e2148b7"} \ No newline at end of file diff --git a/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-plaintext.json b/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-plaintext.json new file mode 100644 index 0000000000..5be365828f --- /dev/null +++ b/crates/buzz-relay/tests/fixtures/ifc-managed-memory-v2-plaintext.json @@ -0,0 +1 @@ +{"slug":"mem/ifc1/2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640/506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160","value":"fixture protected memory","ifc":{"version":2,"logical_slug":"mem/ifc-golden","agent_pubkey":"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","human_owner_pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","binding_json":"{\"version\":1,\"community\":\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"agent\":\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"owner\":\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"audience\":{\"public\":false,\"readers\":[\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\"]},\"context\":{\"type\":\"conversation\",\"conversation\":\"11111111-1111-4111-8111-111111111111\"},\"capability_ceiling\":[\"READ_CORE_MEMORY\",\"READ_NAMED_MEMORY\",\"WRITE_MEMORY\"],\"model_history_conversation\":\"11111111-1111-4111-8111-111111111111\",\"model_history_id\":\"ifc-v1-golden-memory-history\",\"source_generation\":\"17\",\"unknown_managed_input\":false}","derivation_event_ids":["9d66eb8ad4dbc6990b835f895dc7a0c4bb4bec7535848cd56f3c03ff59e67226"],"release":null}} \ No newline at end of file diff --git a/crates/buzz-relay/tests/fixtures/ifc-v1-golden.json b/crates/buzz-relay/tests/fixtures/ifc-v1-golden.json index 1e73f7ad14..b935e30df2 100644 --- a/crates/buzz-relay/tests/fixtures/ifc-v1-golden.json +++ b/crates/buzz-relay/tests/fixtures/ifc-v1-golden.json @@ -31,20 +31,45 @@ }, "contract": "buzz-ifc-v1", "managed_memory": { - "application_metadata_status": "illustrative until the exact Kotlin protected version-two object is supplied", - "canonical_slug": "mem/fixture", - "d_tag": "0b9b4ad03afac3515462d87cd388142ca5bc79ed3575a8c7bc8b968b2f89fc9b", + "application_fields": { + "agent_pubkey": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "audience": [ + "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + ], + "canonical_scope_utf8": "[\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"restricted\",[\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\"]]", + "community": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", + "d": "a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343", + "envelope_version": 2, + "expected_revision": "none", + "format": "buzz-ifc-managed-memory-golden-fields", + "human_owner_pubkey": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "identifier": "a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343", + "kind": 30174, + "logical_slug": "mem/ifc-golden", + "name": "506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160", + "namespace": "2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640", + "p": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "physical_slug": "mem/ifc1/2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640/506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160", + "plaintext_sha256": "531b1a1093050826f6f7556c344d3d4b6bf1464c2281d8c9fdf5ae8c6e2148b7", + "recipient_pubkey": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "s": "2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640", + "source_conversation": "11111111-1111-4111-8111-111111111111", + "source_generation": "17", + "version": 1 + }, + "application_metadata_status": "actual interim Kotlin version-two export; immutable contributing-source provenance is not yet frozen", + "d_tag": "a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343", "event": { - "content": "AkREREREREREREREREREREREREREREREREREREREREREQyeDCXIKMB6Cl7kRHCVPj5H6qYt0cdDfscZBFEP2ExIdJ7ANgaiiWXarVduJns4Wb7A7MqXKITuswUqZZCXTxpuGF3LmIW4qfeLLQVReOg7Pe3lIkzwCqndl9xf5DkjTL9lkH4xC0MDU0wxDd6pSJetjf8+BffF1VlrB0VYPX0GXPTLCrEd5mr4AGFALcL2antXb68eVMbjAS/7zBXOnvISLI+We7QSSQ9DHa+WhrTqMoZNwgMNxjgFoycb+Gg+YfxOz9XBPlQAAyNciGehG0WeDQ0bqcgPZHTj+8g+gz0HzJRwoQW0QO9RuY8Tiwq8dFg/Xi156AE8OASlvpytS4wjH9Me0vmc5cNVakmoyEM9jmE1TStPaCtiGIsdwfJkUQNMCvHCQyAMz7gj3t559Z9y9esRg0R0UcfN6BJrYkLX3C6Msu6vIpAFDV+LX7qehD5izB/wnDwiAJu66CpCphW7Q", + "content": "AkRERERERERERERERERERERERERERERERERERERERERERs2DCXIKMB6Cl7kRHCVPgJ7h7NE0d5SV8tEQGQCrCUlbJLsTx7/hDWHtRYXOyZsEPuUoZ/aWdnzsgAWDPHeI0MLKAjCwZSV6cLTZSFFLKgiVICAN0mBG5U4/q1GhFUiDe4AxHYxHnsOMhQ9YdalXIadreMiBMaUsDgOYhFNXXROTZHaLvwwg2agHTxUdfN/R2o6CvJnZePbpQ/akWnOsr9PTaqDarkyDApOZMrTz6G7Fuc8k3IEyxhJ12p6pSByTNQDnvCBbmQELmIxkXKVEnDrIERCkUC2ZSi+up1uoxE2yLx9pVlEEddV9aIi6v6ceUVuB7Uo5VEEJQGoxsSkJsw7GrMfnv2Y5Lo5Qlj5lHp1nzx8JHYGAVt+EJcZ8JpgfEtQPviObmAVmsVegvsN9YN/pfdcu7gMMQcBMYqP6vJeffoJi6AAHEMVLQ79OCz6atMu0WPNeyHw9eRq4ZvPVvwPaBzLyA+9/RQuQ8VYnp9FUKklTGNtf2JxIe9wO3s3kiA3tbeXMccGkE6woxaw10OmXpHfD0SWq86bvm4v5pWJROTIbvnOHzUbv45FumezB6YqByJz1GTESAGrb1eqezzhedTP+nMkADBxZh+FG6HLDYui+q54qUs2h/kgnep294M54edCVfdBprngz+0dmF6dGmWyGQXZvX7tLZvWVR9JF+JQt8yE/gEL4WZa38z6TjJbByZwHa+cJx2/GVLFKYrjeZvGiGYKZ/ojelJLxNktxOAOTa6EupNsQYwsN/D/utiNOjZMs2NcCnhpk8yNrZ++MheLu8Tj3zwCTyASVXjIn6+IAFoSb2QqAzrmMqqTnWSPaYfGnixbkCW65Who61/cAmCc0jeE9g2VjYlRSj1UzcKlwmk+NTBtCptJ7kxi+JfgaHHnCY/X/KFHWMH4mOdLzcfIBPMUZ29RYgvx2zba4BoS6HaZNLU4wh0T64GXSHTuzPoC5UZsJkYbVqgvTmWMWFqFZYIv7FHF3zGtt4sX0/ziEr0kgvuGJLFrR2hqHxGwc1y/UHzz5YDD8S11Xj/o7U5fHNGdRF7vv0Tga4zd9n8BYQa3Zbds9HZocXVo3hjZejUFjZAvdlqdfTl+VpdnqXCdhHdk6lrFN1FEoeGcSl8K0tV6qIDwcxInPsNF0QutGlfbjJhLDWGXVVFlWxWpS0OOIoXiPGDlT7bNAcZS7Q9/Z+SlINJVfNQZD7QYKxy8Boc0nuq+Da4cyuwepLqxUwbW+lKbkJaONuHYIGkRxF5VjpmbNMx/oO95yTKB29h7GzJUc1Rvgxyp9FqtmhzGiWobzgrA2Y8Mto+WDZkJJVkSFbqfPfAD1fzdwrg74Q1ufSNSoF5M+ZkXWac9DVdKHvsPHfUDN0vnVZrE+sZAjkx4IcbGshXt4o6N3z/Qkxp+1USfakrJ+3APkJJL1iRt/QE2NC4U4bFGSPTfmNPgVlldtZYKHiJII5yGfDcufnbJ8547HsBnVx02d+3/5YQ6q4JyUX2Y6XYE0h6JHLqR3tUrgL84HCHXGaZZN6tpgqluojGnCLGechP6SREP4rZ60V5N6tXh5T5AGSnXVIuqP8XBl24hUqEZ4zTIDSQP+FaqaBMga7PedGcRXZG1qXIEKxSdxaCnEelcXHgr16rfDEHcY9eV7FvmYTiGwLAdJ0pqs0Hg8ZmX/Gtg5/lsRrr+h609HNUAlGpO4ub6pJMBIC0/8DNbNzlKFfQ1klTuXBPc/gR7UiVUhXGbaw517kR/y", "created_at": 1791999920, - "id": "e83145b7910fb28b9698bfda3512cb613d85c710eea6f24a6a430b829c5cf7cf", + "id": "3523d9334ad2c1ba117d51f8a99c7ca388296836eb17e926bccca75b43ceb523", "kind": 30174, "pubkey": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", - "sig": "b806a0093646c3e88074666874fa6eabf5ea58855caa1d220586b8fdd4aaa39d82e7d33c0b39719daf37385fd59c3c8c68b0d175cfb563d8587264cfd154a6ca", + "sig": "d459c0ccedf48c8569f4f7d0d6b208ac310ac5842445d0d12678130ed93bb8184a8ccc2fc2bc4582b10776f53da990aaddd10f8e349e961fa024519a179b8228", "tags": [ [ "d", - "0b9b4ad03afac3515462d87cd388142ca5bc79ed3575a8c7bc8b968b2f89fc9b" + "a8c8ea1f18fdf50079905e1e49c9f212c5f796f3822d8fd56cee610761305343" ], [ "p", @@ -67,7 +92,7 @@ ], [ "s", - "45e1406b5f47f4745839990578415c705644e318ad2570d35882b2e72b0f369d" + "2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640" ], [ "expected-revision", @@ -75,11 +100,18 @@ ] ] }, - "namespace": "45e1406b5f47f4745839990578415c705644e318ad2570d35882b2e72b0f369d", - "plaintext_utf8": "{\"slug\":\"mem/fixture\",\"value\":\"fixture protected memory\",\"ifc\":{\"version\":1,\"community_id\":\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"sources\":[{\"channel_id\":\"11111111-1111-4111-8111-111111111111\",\"generation\":\"17\"}],\"provenance\":[{\"event_id\":\"9d66eb8ad4dbc6990b835f895dc7a0c4bb4bec7535848cd56f3c03ff59e67226\"}]}}", + "human_readers": [ + "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + ], + "logical_slug": "mem/ifc-golden", + "name": "506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160", + "namespace": "2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640", + "physical_slug": "mem/ifc1/2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640/506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160", + "plaintext_sha256": "531b1a1093050826f6f7556c344d3d4b6bf1464c2281d8c9fdf5ae8c6e2148b7", + "plaintext_utf8": "{\"slug\":\"mem/ifc1/2cffaa0a688adebf2b1176b1326f413861859cc81484c7743689b803492e5640/506f38db9a1584cadcb97b66bdea0ffaa589884d9c3e8fe1866dd264690f8160\",\"value\":\"fixture protected memory\",\"ifc\":{\"version\":2,\"logical_slug\":\"mem/ifc-golden\",\"agent_pubkey\":\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"human_owner_pubkey\":\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"binding_json\":\"{\\\"version\\\":1,\\\"community\\\":\\\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\\\",\\\"agent\\\":\\\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\\\",\\\"owner\\\":\\\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\\\",\\\"audience\\\":{\\\"public\\\":false,\\\"readers\\\":[\\\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\\\"]},\\\"context\\\":{\\\"type\\\":\\\"conversation\\\",\\\"conversation\\\":\\\"11111111-1111-4111-8111-111111111111\\\"},\\\"capability_ceiling\\\":[\\\"READ_CORE_MEMORY\\\",\\\"READ_NAMED_MEMORY\\\",\\\"WRITE_MEMORY\\\"],\\\"model_history_conversation\\\":\\\"11111111-1111-4111-8111-111111111111\\\",\\\"model_history_id\\\":\\\"ifc-v1-golden-memory-history\\\",\\\"source_generation\\\":\\\"17\\\",\\\"unknown_managed_input\\\":false}\",\"derivation_event_ids\":[\"9d66eb8ad4dbc6990b835f895dc7a0c4bb4bec7535848cd56f3c03ff59e67226\"],\"release\":null}}", "recipient": "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", "saved_human_owner": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", - "scope_canonical_json_utf8": "[\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"restricted\",[\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\"]]" + "scope_canonical_json_utf8": "[\"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa\",\"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9\",\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\",\"restricted\",[\"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5\"]]" }, "owner_telemetry": { "application_payload_status": "deterministic wire example; backend preserves its existing encrypted telemetry envelope",