Skip to content

Latest commit

 

History

History
209 lines (175 loc) · 12.1 KB

File metadata and controls

209 lines (175 loc) · 12.1 KB

Changelog

All notable changes to this project are documented in this file.

[0.5.0] — 2026-08-22

Added — v3 protocol compatibility (bilingual broker)

The broker now speaks the self-use Python relay's v3 protocol alongside v2, closing the divergence that left v3 clients (the Hermes adapter and the Python relay agents) locked out of a v2-only broker:

  • Bilingual signatures: X-Agent-Relay-Key-Id present → v3 scheme (agent\nkeyId\nts\nMETHOD\npath\ndigest); absent → v2 scheme. Per-agent keyrings (agents.<name>.keys, with not_after expiry) support key rotation; the implicit legacy key is the agent's single secret. Unknown or expired key ids are rejected with 401 unknown_key. /healthz reports protocol_version: 3 and signature_schemes: ["v2", "v3"].
  • Lease credentials (v3): pull responses include lease_token / lease_until; POST /v1/ack with a token is guarded on the active lease (409 lease_mismatch on mismatch/replay); new POST /v1/lease/renew extends an active lease. Acks without a token keep v2 semantics.
  • allow_shared_write round-trips on requests (and is stripped from replies), matching the self-use workspace-leasing semantics.
  • Admin authz mirrors the self-use broker: security.admin_agents may act on anything; everyone else only on their own side (recipient requeues an unfinished request, originator cancels their request). Admin operations are audit-logged (ids only). queues in /healthz gains oldest_queued_at.
  • SQLite schema migration: pre-v3 databases gain the lease_token / allow_shared_write columns in place on startup.

Added — v3-aware clients and lease renewal

  • JS client (lib/client-v2.js): optional keyId opts the client into v3 signing; ack() accepts a leaseToken for the strict single-use guard; new renewLease() extends an active delivery lease.
  • Standalone relay agent (adapters/relay-agent.mjs): renews the broker delivery lease every 4 minutes while a backend CLI run is in flight, so a turn longer than the lease window is no longer re-queued and re-delivered mid-flight; acks with the lease token when the broker provides one.
  • Published Python client (adapters/hermes/relay_client_v2.py): key_id= constructor option (v3 scheme), ack(..., lease_token=) and a renew_lease() method — byte-compatible with the self-use relay/client.py.
  • v3 golden vectors locked in test/protocol_v2_golden.py and test/protocol-v2.test.mjs (generated by the self-use reference implementation), plus a v3 leg in the cross-language client round-trip test.
  • CI runs on Windows too — the primary deployment platform.

Fixed — broker correctness and resource use

  • v2 store dataDir resolves against the broker directory — a relative dataDir (the ./data default) no longer depends on the process CWD, so the v2 SQLite/JSONL files always land beside the v1 store. The broker entrypoint now creates the v2 store itself and closes it on shutdown (previously only the v1 store was closed); close() also runs PRAGMA wal_checkpoint(TRUNCATE).
  • Lifecycle transitions persist as single-row UPDATEs instead of rewriting the whole table on every ack/pull/requeue/cancel. Full-table rewrites caused heavy WAL growth (a multi-MB WAL against a 128 KB database was observed in production). The JSONL fallback keeps its rewrite semantics.
  • The idempotency index is pruned together with retention purges — it previously grew without bound for the lifetime of the process.
  • v2 POST /v1/ack requires the message to be leased (400 otherwise) — a late or duplicated ack can no longer resurrect a terminal message back to queued (e.g. a retry ack arriving after a redelivery was acked mid-flight).

Changed — admin endpoints and plugin configuration

  • /v1/admin/requeue and /v1/admin/cancel are restricted to the originator or the recipient of the message (403 otherwise), matching the visibility rules of /v1/status and the per-mode ACL.
  • dsh plugin: the credential-vault fallback for secretRef is configured, not built in. Resolving a secret through a Python module exposing reveal_entry(name) requires the new vaultModule setting (DSH_RELAY_VAULT_MODULE env / vault_module in ~/.dsh/agent-relay.json); no installation layout is hard-coded anymore.
  • dsh plugin: the system-prompt guidance and the agent_relay_send description derive the roster and broker endpoint from configuration (circleMembers / DSH_RELAY_CIRCLE_MEMBERS / circle_members), falling back to pointing at agent_relay_peers instead of a hard-coded member list.
  • dsh plugin: the default relay-session cwd falls back to the user's home directory instead of a Windows-specific C:/ path.

[0.4.0] — 2026-08-15

Added — v2 wire protocol (self-use compatible) + advanced dsh plugin

  • v2 wire protocol (docs/PROTOCOL-V2.md): canonical-JSON signing (sort_keys + compact + raw UTF-8), X-Agent-Relay-* headers, snake_case envelope (message_id/origin/target/kind/body/session_ref/created_at/expires_at/execution_mode/context/topic). Byte-for-byte compatible with the self-use Python relay/protocol.py (golden vectors locked in test/protocol-v2.test.mjs + test/protocol_v2_golden.py).
  • v2 broker endpoints: /healthz, /v1/messages, /v1/pull, /v1/ack, /v1/status, /v1/recent, /v1/messages/query, /v1/admin/requeue|cancel|status.
  • v2 state machine in the transitional store-v2.js: queued → leased → completed/failed/expired, (origin, idempotency_key) idempotency, TTL + 30-day retention, SQLite (node:sqlite) with JSONL fallback.
  • per-mode ACL (allowed_read/continue/write_targets; write closed by default) and undelivered notices (notify_failed_to_sender).
  • v2 clients: lib/client-v2.js (RelayClientV2), adapters/hermes/relay_client_v2.py (pure stdlib), CLI v2 <subcommand>.
  • dsh plugin upgrade (lib/index.js): adaptive-backoff inbox polling, per-root relay sessions (agent-relay-<root_id>) with archive + idle recycle, 5 tools (agent_relay_send/status/history/peers/retry), execution-mode permission presets, per-agent receipts/routes persistence, systemPrompt guidance. Replaces the v1 relay_send/recv/peers/history tools.
  • v1 compatibility preserved — every existing v1 endpoint/client/test still works (the v1 protocol is a separate path, documented in docs/PROTOCOL.md).

[0.3.0] — 2026-08-15

Added — v1.1 reliable delivery (backward compatible, protocol stays 1.0)

  • Lease-based delivery state machine: POST /v1/pull leases queued messages (queued → leased), POST /v1/ack finalizes (completed → done) or re-queues (retry, attempts+1, over maxAttemptsfailed); expired leases are re-queued by a sweep. Config: broker.leaseSeconds (600), broker.maxAttempts (3).
  • Request/reply correlation: optional envelope fields kind (message|request|reply), rootId, parentId; broker-visible status, attempts, leaseUntil.
  • History/status endpoints: POST /v1/status (batch lookup), POST /v1/recent, POST /v1/messages/query (read-only filtered search).
  • Routing ACL: optional agents.<name>.allowed_targets whitelist in broker/config.yaml; disallowed sends return 403 forbidden; absent entry = allow all (v1.0 default).
  • Client support: JS RelayClient (pull/ackOutcome/status/recent/query
    • kind/rootId/parentId on send), CLI subcommands (pull/ack/status/recent/query), Python client equivalents.
  • Plugin receipts: the dsh plugin polls via lease-pull and persists completed replies to ~/.dsh-agent-relay-receipts.json (TTL 1 day, atomic write); a redelivered request whose id is in the receipts is replayed (idempotent) and acked completed — never re-run after a restart. relay_send accepts replyTo.
  • Docs: PROTOCOL v1.1 extension, DEPLOY v1.1 config, SECURITY ACL, README/zh, AGENT-DEPLOY checklist.

Fixed

  • SQLite is now the default persistent backend, creates a missing data directory on first start, and falls back to JSONL on Node runtimes where node:sqlite cannot be loaded (Node < 22.5, and 22.5–22.12 which gate it behind --experimental-sqlite). GET / reports the active backend and optional capabilities without changing protocol 1.0 compatibility.
  • The Python adapter now sends legacy acknowledgements with the correct HTTP method and retries 408/429 responses consistently with the JavaScript client.
  • Configuration parsing now supports the documented nested agent ACL structure and rejects invalid safety, delivery, rate-limit, and lockout values at startup. The removed broker.tls label now fails loudly at startup (terminate TLS at a trusted reverse proxy) instead of being silently ignored — config templates no longer emit it.

Tests

  • test/lease.test.mjs (state machine, lease expiry, attempts, status/recent/query) and test/acl.test.mjs (whitelist allow/deny + v1.1 pull/ack round trip). 29/29 green.

[0.2.0] — 2026-08-15

Added

  • Agent-driven deployment: new docs/AGENT-DEPLOY.md deploy task book for DSH — the npm package now ships the broker + setup + adapters, so a single-machine deployment needs no git clone; DSH follows the task book to generate the secret, start the broker, wire the plugin/CLI/Python clients and verify the round trip.
  • npm package is self-contained: files now includes broker/, setup/, adapters/, docs/ and README.zh.md; a new .npmignore keeps secrets, runtime data and test/ out of the tarball.

Fixed

  • Broker version no longer hard-coded: broker/src/server.js reads its own manifest (broker/package.json) so / and selfcheck always report the real version (was stuck at 0.1.0), and the path works in both the repo and the Docker image layout.
  • Plugin protocol handshake: the dsh plugin now performs the PROTOCOL §4 version negotiation on first poll (matching the Python client), surfacing an incompatible-broker error instead of proceeding silently.
  • Plugin not-configured guidance: points to docs/AGENT-DEPLOY.md and is npm-aware (no longer assumes a git checkout with setup/setup.js).
  • CLI: peers/handshake no longer require --agent (docs already assumed it); removed a duplicated ack loop.
  • Docs accuracy: privacy claims now correctly state that message content lives only in the broker's TTL-limited queue (default 7 days) and is never written to application logs — aligning README/README.zh and the AGENT-DEPLOY.md checklist with the actual persistence behavior.

CI

  • Unit tests now run on macOS as well as Linux (matrix).

[0.1.1] — 2026-08-15

Fixed

  • setup.js selfcheck now reads host/port from broker/config.yaml (reusing the broker's own config loader) instead of hard-coding 127.0.0.1:19121 — a custom port no longer produces a false "broker not reachable" failure.

[0.1.0] — 2026-08-14

Added

  • Wire protocol v1.0 (docs/PROTOCOL.md): envelope, HMAC auth headers, version negotiation, error codes, retry/idempotency rules, brute-force protection.
  • Broker (broker/): zero-dependency Node HTTP service — register/heartbeat, peers, send, incremental poll, ack; JSONL persistence; 7-day TTL; per-agent lockout; per-IP rate limiting.
  • dsh plugin (repo root): relay_send / relay_recv / relay_peers / relay_history model tools; background heartbeat + inbox polling; optional sidebar status panel; graceful degradation when not configured.
  • CLI client (adapters/cli/relay.mjs): zero-dependency, send/recv/peers/register/watch/handshake.
  • Python client (adapters/hermes/relay_client.py): pure stdlib, Hermes-style integration example included.
  • Setup: setup.js init|start|selfcheck, selfcheck.js, optional docker-compose demo, broker Dockerfile.
  • Docs: PROTOCOL / ARCHITECTURE / DEPLOY (single-machine + TLS distributed) / SECURITY; bilingual README.
  • CI: unit tests (node --test), gitleaks secrets scan, license check, lockfile check on every push.