Remove empty local-credential tombstones from spawned agent environments and defensively treat an empty CLI private-key value as absent, while continuing to reject all real key material.
Bound broker HTTP actions, terminate polling on rejected credentials, and document the cursor, restart, and thread-context limits that remain for real-host integration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joel Robotham <jrobotham@squareup.com>
Promote the HTTP broker transport into a shared crate and add an explicit runtime transport seam to buzz-acp. Broker mode rejects local keys, derives its identity through storage.address, polls configured channels through channel.read, validates returned events, and provisions agent subprocesses with broker-only credentials.
Relay-only housekeeping and enrichment stay disabled until the frozen contract grows an agreed host-owned path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joel Robotham <jrobotham@squareup.com>
Add an addressing-only bridge for encrypted memory while the end-to-end runtime storage semantics remain deferred.
- add mem address <slug> and normalize shorthand to the NIP-AE slug
- route storage.address through AgentBackend in broker mode and print its validated JSON outcome
- derive the same address locally for command parity
- extend the mock host, backend round-trip coverage, and keyless docs
The returned coordinates identify a record but do not yet fetch, decrypt, encrypt, or publish it; KEYLESS.md records that deliberate temporary limit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joel Robotham <jrobotham@squareup.com>
Extend the AgentBackend seam with reaction_add / profile_set and route
two more command groups through it in keyless mode:
- reactions add -> reaction.add (requires --channel, the host's scope;
refuses --emoji-url, which is host-owned custom-emoji handling)
- users set-profile -> profile.set (maps name/about/avatar; refuses
--nip05, absent from the contract; requires >=1 field)
BrokerBackend maps each to its ActionArgs and unwraps the EventPublished
outcome, same as message.post. LocalBackend implements both for parity
(reaction via build_reaction; profile as read-merge-write over the
current kind:0, emulating the contract's 'absent fields left as-is').
Local command paths are untouched. Mock host and KEYLESS.md gain the two
actions; two BrokerBackend round-trip tests added.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joel Robotham <jrobotham@squareup.com>
- examples/mock_broker.rs: a throwaway host that speaks just enough of the
contract (POST /v1/action, echoes requestId/action, canned outcomes) to
exercise the keyless CLI end to end before a real broker exists. Signs
nothing, touches no relay.
- KEYLESS.md: brief instructions — build, run against the mock, and point
the CLI at your own broker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Joel Robotham <jrobotham@squareup.com>