feat(desktop): add persona event kind with client publish/read/retain#939
Draft
wpfleger96 wants to merge 7 commits into
Draft
feat(desktop): add persona event kind with client publish/read/retain#939wpfleger96 wants to merge 7 commits into
wpfleger96 wants to merge 7 commits into
Conversation
This was referenced Jun 10, 2026
wpfleger96
added a commit
that referenced
this pull request
Jun 10, 2026
Ties the secrets-exclusion rule to the env_vars field removed in #939, making the doc-to-code mapping unambiguous. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
added a commit
that referenced
this pull request
Jun 11, 2026
…Body PersonaEventContent is the public struct serialized in kind:30175 events. PR #939 removed env_vars from it (secrets must not travel in plaintext events). This commit removes the re-addition from #945 and instead carries env_vars in PersonaEngramBody, which is NIP-44 encrypted inside the agent's mem/persona engram. Co-authored-by: Will Pfleger <wpfleger@block.xyz> Signed-off-by: Will Pfleger <wpfleger@block.xyz>
wpfleger96
added a commit
that referenced
this pull request
Jun 11, 2026
…Body PersonaEventContent is the public struct serialized in kind:30175 events. PR #939 removed env_vars from it (secrets must not travel in plaintext events). This commit removes the re-addition from #945 and instead carries env_vars in PersonaEngramBody, which is NIP-44 encrypted inside the agent's mem/persona engram. Co-authored-by: Will Pfleger <wpfleger@block.xyz> Signed-off-by: Will Pfleger <wpfleger@block.xyz>
817e596 to
5952ae5
Compare
Squashed for rebase — original commits: - feat(desktop): add persona event kind with client publish/read/retain - fix(desktop): sign every migrated persona event and drop the sentinel file - fix(relay): validate kind:30175 persona d-tag slug grammar on ingest - fix(desktop): drop env_vars from public PersonaEventContent - docs: add NIP-AP spec for kind:30175 persona events - feat(ci): add relay E2E testing job and persona event tests
Missed during rebase: sprout_core→buzz_core_pkg imports in persona_events.rs and migration.rs, sprout-desktop→buzz-desktop in log messages, and cargo fmt on e2e_persona.rs.
cargo fmt requires buzz_core_pkg imports before nostr (alphabetical). Relay E2E git tests need git-credential-nostr built alongside the relay.
…ay behavior The relay now has a generic file upload path that accepts PDFs, random bytes, and unrecognised formats as application/octet-stream downloads. SVG with XML declaration is not detected by `infer` and also routes through the generic path. Updated four content validation tests from expecting rejection (400/415) to expecting acceptance (200). Additionally, three WebSocket imeta tests hit /api/events but the relay route is at /events (no /api prefix). Fixed the URL in all three. Co-authored-by: Will Pfleger <wpfleger@squareup.com> Signed-off-by: Will Pfleger <wpfleger@squareup.com>
infer detects XML-based SVG as text/xml (not image/svg+xml), which is not in the blocked list, so the relay accepts it through the generic file path with that MIME type. Co-authored-by: Will Pfleger <wpfleger96@gmail.com> Signed-off-by: Will Pfleger <wpfleger96@gmail.com>
Same class of issues as e2e_media_extended — tests assumed image-only policy and wrong API path. The relay ignores Content-Type headers (uses magic bytes) and the route is /events not /api/events. Co-authored-by: Will Pfleger <wpfleger96@gmail.com> Signed-off-by: Will Pfleger <wpfleger96@gmail.com>
The live_split_model_completes test is a manual runbook test requiring multiple serve nodes. Replace panic!() with println+return so it skips gracefully when CI runs --ignored tests. Co-authored-by: Will Pfleger <wpfleger96@gmail.com> Signed-off-by: Will Pfleger <wpfleger96@gmail.com>
9b8924a to
6c2e650
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the foundation for the personas-as-events architecture (PR 1 of 2 in the post-852 roadmap). Defines a new Nostr event kind for persona definitions, adds client-side serialization, a local SQLite retention store for offline boot, and migrates existing
personas.jsonentries to events.Stack: this PR → #945
Changes
Relay side
crates/sprout-core/src/kind.rs: RegisterKIND_PERSONA = 30175as NIP-33 parameterized replaceable, keyed by(pubkey, kind, d_tag)whered_tagis the plaintext persona slug. Compile-time assertion verifies range membership.crates/sprout-relay/src/handlers/ingest.rs: Allowlist kind:30175 underScope::UsersWrite, mark as global-only (never channel-scoped). New tests verify scope and global-only classification.Desktop client side
desktop/src-tauri/src/managed_agents/persona_events.rs(new): SerializePersonaRecord↔ kind:30175 event. JSON content body containsdisplay_name,system_prompt,avatar_url,runtime,model,provider,name_pool,env_vars. Publish/fetch functions via relay HTTP API.desktop/src-tauri/src/managed_agents/retention.rs(new): SQLite retention store withINSERT OR REPLACEon(kind, pubkey, d_tag)for NIP-33 latest-wins semantics. Pending-sync queue for deferred relay publish. Enables offline boot when relay is unreachable.desktop/src-tauri/src/managed_agents/personas.rs: Addload_from_retentionhelper (wired up but not yet activated as the primary read path — that is PR 2 territory).desktop/src-tauri/src/migration.rs:migrate_personas_to_eventsruns after identity resolution, signs every retained event with the owner's real keys (no placeholder events). Idempotent via retention-row-exists check (the data is the sentinel). Core logic extracted intomigrate_personas_in_dirfor unit testing.desktop/src-tauri/src/lib.rs: Migration call moved afterresolve_persisted_identityso keys are always available. Owner keys cloned fromAppStateand passed to migration.desktop/src-tauri/Cargo.toml: Addrusqlitedependency with bundled feature.Key design decisions
INSERT OR REPLACEkeyed on(kind, pubkey, d_tag)in SQLite. NIP-33 replaceable semantics handle relay-side idempotency.load_personasstill reads frompersonas.jsonas before. The retention-based load path is a helper for PR 2 (instantiation flow).Not in scope (PR 2 — #945)
mem/personaengram)