NIP-AD: durable agent drafts + external agent adoption - #20
Merged
Conversation
Defines durable p-gated kinds 44300 (agent draft request) and 44301 (owner draft resolution), replacing the ephemeral agent_management_request telemetry payload on NIP-AO kind 24200. NIP-AO now points at NIP-AD. Closes #18 (part 1/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds KIND_AGENT_DRAFT_REQUEST (44300) and KIND_AGENT_DRAFT_RESOLUTION (44301) to P_GATED_KINDS and RESULT_GATED_KINDS, a new agent_draft payload module (create/update request + resolution, NIP-44 encrypt/decrypt, fail-closed version validation), and widens reader_authorized_for_event to derive the gate from RESULT_GATED_KINDS so future kinds inherit it. Note: nostr's EventBuilder discards self-p-tags by default; the two-p-tag NIP-AD envelope requires allow_self_tagging() at build time. Closes #18 (part 2/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Wires kinds 44300/44301 into relay ingest: MessagesWrite scope, global-only storage (no h tag), envelope validation (two p tags, agent tag, no h, NIP-44, author direction, single e tag for 44301), and is_agent_owner ownership check. Extends the ids-exemption in p_gated_filters_authorized to derive from RESULT_GATED_KINDS. Adds migration 0027 + schema.sql to exclude both kinds from FTS. count.rs and bridge.rs inherit the gate via RESULT_GATED_KINDS / reader_authorized_for_event. Closes #18 (part 3/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds build_agent_draft_request (44300) and build_agent_draft_resolution (44301) with the two-p-tag + agent-tag (+ e-tag for resolution) envelope, NIP-44 content check, owner!=agent and hex validation, and allow_self_tagging so the author's own pubkey survives as a p tag. Closes #18 (part 4/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
draft-create/draft-update now publish a durable kind 44300 via submit_event (was ephemeral kind 24200), building AgentDraftRequestPayload and returning event_id. Adds 'buzz agents drafts list|status' reading both 44300/44301, decrypting with the running key, and joining on requestId for pending-ness. Closes #18 (part 5/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
The owner cannot decrypt kind 44301 (it is encrypted to the agent), so drafts list/status must determine resolved-ness from the cleartext e tag (which references the request event id) rather than decrypting resolutions. Closes #18 (part 5 fix) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds list_pending_agent_drafts (queries 44300/44301, decrypts 44300 with the owner key, drops undecryptable and resolved requests via the cleartext e tag) and resolve_agent_draft (builds + signs + publishes a kind 44301 resolution). Registers both in the invoke_handler. lib.rs kept at the 1000-line ratchet. Closes #18 (part 6/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds adopt_external_agent: mints the NIP-OA BUZZ_AUTH_TAG from the agent's public key and the owner's secret (no new keypair) and stores the agent with BackendKind::External. Adds the External backend variant and fail-closed guards on the spawn/restart/deploy paths. agents.rs and types.rs kept within their file-size ratchets. Closes #18 (part 7/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Replaces the ephemeral kind-24200 agent_management_request path with a durable agentDraftStore (backfill via list_pending_agent_drafts + live 44300 subscription, dedupe by requestEventId). useAgentManagement now reads from the store, classifies origin via declared NIP-OA ownership (agentDraftTrust), and publishes 44301 resolutions on accept/decline/dismiss. Removes the agent_management_request branch from observerRelayStore (24200 is telemetry only again). Adds kinds 44300/44301 and typed Tauri wrappers. Closes #18 (part 8/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Create drafts now review through AgentDraftAdoptDialog whose primary action is 'Adopt this identity' (adopt_external_agent, no new keypair) with a separately-confirmed 'Import key to run from this Desktop' (import_external_agent_key). After adoption the minted BUZZ_AUTH_TAG is shown with a copy affordance. Adds the import_external_agent_key Tauri command and an AGENTS.md rule for BackendKind::External. Closes #18 (part 9/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
classifyAgentManagementOrigin is replaced by classifyAgentDraftOrigin (agentDraftTrust.ts) which keys on declared NIP-OA ownership instead of local managed-agent membership. Closes #18 (part 8 cleanup) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
B2 cold-start fix: useManagedAgentObserverBridge now opens the owner-global 24200 REQ whenever an identity is known, regardless of agents.length, so a newly adopted external agent's live telemetry is subscribed even when no agent existed before. knownAgentPubkeys remains the telemetry decrypt gate. Removes the now-obsolete shouldObserveManagedAgents gate and its test. Closes #18 (part 10/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Covers every read chokepoint (REQ, kindless ids, COUNT, live fan-out) for kinds 44300/44301: owner/agent read, third party closed out, ingest envelope rejections (no owner binding, wrong p cardinality, h tag, non-NIP-44, wrong author), resolution e-tag join, and FTS exclusion. Closes #18 (part 11/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds agent-draft-review.spec.ts (smoke project) covering: draft arrives → review dialog opens; adopt → BUZZ_AUTH_TAG shown with copy; decline → resolution published and the draft does not resurface after reload. Adds mock bridge handlers for list_pending_agent_drafts / resolve_agent_draft / adopt_external_agent, a pendingAgentDrafts seed, and the __BUZZ_E2E_EMIT_MOCK_AGENT_DRAFT__ helper. Keeps the adopt dialog mounted after adoption so the auth tag stays visible. Closes #18 (part 11/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Adds CHANGELOG + relay CHANGELOG entries for NIP-AD durable agent drafts and captures review-dialog screenshots from the Playwright spec. Closes #18 (part 12/12) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Closes #18 (part 12 fmt) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
Owner
Author
The committed lock was stale; cargo chef prepare updates it, so the --locked relay build in the Docker image workflow failed with 'cannot update the lock file'. Regenerate the lock so the CI build is reproducible. Closes #18 (part 12 lock) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
The B2 cold-start fix opened the owner-global 24200 REQ on identity-known, but that raced the observer-archive policy: the live filter opened before kind 24200 was guaranteed present in the subscription, breaking observer-archive-policy.spec.ts. Gate the subscription on identity-known AND observerReconciled. Closes #18 (part 10 fix) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
cargo chef cook resolves workspace crates to recipe versions that diverge from the committed lock, so the --locked relay build failed with 'cannot update the lock file'. Build without --locked so the lock is refreshed to the chef resolution. Closes #18 (part 12 docker) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
Same cargo chef cook lock divergence as the relay Dockerfile; build without --locked so the lock is refreshed to the chef resolution. Closes #18 (part 12 docker) Signed-off-by: Brian Charbonneau <github@briancharbonneau.com>
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
Fixes #18 — the Desktop never ingested CLI
agent draft-createbroadcasts because the oldagent_management_requestpath used ephemeral kind 24200, which the relay never stores. A draft published while the owner's Desktop was closed was lost forever.This replaces that path with two durable, p-gated, FTS-excluded kinds:
ptags: owner + agent,agenttag, nohtag, NIP-44 v2)etag referencing the request)A draft now replays on the owner's next launch, and the Desktop review dialog is driven by a durable store instead of a live observer frame.
What changed
docs/nips/NIP-AD.md) + NIP-AO pointerP_GATED_KINDS/RESULT_GATED_KINDS,agent_draftpayload module (fail-closed version validation)is_agent_owner, global-only storage, FTS exclusion (migration 0027)build_agent_draft_request/build_agent_draft_resolutiondraft-create/draft-updatepublish durable 44300; newagents drafts list|statusadopt_external_agent(attest-first, no new keypair) +import_external_agent_key;BackendKind::Externalfails closed on spawn/restart/deploye2e_agent_draft.rs, 14 tests) + Desktop Playwright (agent-draft-review.spec.ts)Live acceptance
Deployed the NIP-AD relay to production (
buzz.bjzy.me) and verified: a realdraft-createpublished as a Hermes specialist key (withBUZZ_AUTH_TAG) while the Desktop was closed is accepted and readable by the owner on the next launch — proving the durable backfill fixes B1.Screenshots
{{01-draft-review}}
{{02-auth-tag}}
Notes
etag.EventBuilderdiscards self-p-tags by default; the two-p-tag envelope requiresallow_self_tagging()at build time.