From 53b10eab74d83522dd90af697773e32279469b30 Mon Sep 17 00:00:00 2001 From: bndw Date: Sun, 8 Mar 2026 21:59:24 -0700 Subject: add implementation plan --- PLAN.md | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 PLAN.md (limited to 'PLAN.md') diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..ab277d9 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,99 @@ +# Axon — Implementation Plan + +## Dependency Philosophy + +Minimize external dependencies at every layer. The protocol is designed so that the Go implementation requires nothing beyond the standard library and `golang.org/x/crypto`. The JS implementation requires only `@noble/curves` and `@msgpack/msgpack` — both small, audited, zero-dependency libraries. No frameworks, no ORMs, no generated code. + +--- + +## Phase 1: Core Package + +**Everything depends on this. Do not move to Phase 2 until the signing spec is fully verified.** + +- `Event` struct, `Tag`, kind constants matching the registry in PROTOCOL.md +- Canonical signing payload construction — byte-exact per the spec +- Tag sorting (`canonical_tags` hash) +- Ed25519 sign and verify (`crypto/ed25519`) +- X25519 key conversion from Ed25519 keypair (`golang.org/x/crypto/curve25519`) +- ChaCha20-Poly1305 encrypt/decrypt for DMs (`golang.org/x/crypto/chacha20poly1305`) +- MessagePack encode/decode for events + +**Test vectors — write these before any implementation:** + +Publish a set of known-input → known-output pairs for: +- `canonical_tags` hash given a specific tag list +- `canonical_payload` bytes given a specific event +- Event `id` (SHA256 of payload) +- Signature verification + +These vectors must be committed to the repo and validated by the JS client in Phase 4. They are the ground truth for cross-implementation correctness. A disagreement on a test vector means the spec is ambiguous — fix the spec before fixing the code. + +**Go dependencies:** `golang.org/x/crypto` only. + +--- + +## Phase 2: Relay + +- WebSocket server (stdlib `net/http` + `golang.org/x/net/websocket` or `nhooyr.io/websocket`) +- Challenge/Auth handshake on connect +- Allowlist: authorized pubkeys in a flat config file or SQLite table +- Ingest pipeline: + 1. Unmarshal msgpack envelope + 2. Verify signature using Phase 1 core + 3. Reject duplicates (id PRIMARY KEY) + 4. Reject expired job requests (check `expires_at` tag) + 5. Reject events exceeding 64KB content limit + 6. Write to index + store + 7. Fanout to matching subscribers +- SQLite storage via `database/sql` + `mattn/go-sqlite3` or `modernc.org/sqlite` (pure Go, no CGo) +- Subscription management: filter matching, per-connection subscription map +- Ephemeral events (kind 3000–3999): fanout only, skip storage +- Error responses with HTTP-borrowed codes +- WebSocket keepalive: ping every 30s, close after two missed + +**Go dependencies:** sqlite driver, websocket library. Both should be pure Go where possible. + +--- + +## Phase 3: Go Client + +- Connect to relay + complete auth handshake +- Publish events +- Subscribe with filter, receive event stream +- Unsubscribe +- Reconnect with backoff + +The Go client is the primary tool for integration testing the relay. All relay behavior should be exercised via the client before moving to Phase 4. + +**Go dependencies:** none beyond what Phase 1 and Phase 2 already use. + +--- + +## Phase 4: JS Client + +- Connect + auth (Ed25519 sign the challenge) +- Publish events (msgpack encode, Ed25519 sign) +- Subscribe / unsubscribe +- DM encrypt/decrypt (X25519 ECDH + ChaCha20-Poly1305) +- Validate Phase 1 test vectors — JS and Go must agree on every vector before this phase is considered complete + +**JS dependencies:** `@noble/curves` (Ed25519, X25519), `@msgpack/msgpack`. No others. + +--- + +## Phase 5: Integration + +- End-to-end: publish from JS client, receive in Go client (and vice versa) +- Cross-language signature verification: Go signs, JS verifies; JS signs, Go verifies +- DM round-trip: encrypt in JS, decrypt in Go +- Job protocol flow: request → feedback → result across two separate processes + +At the end of Phase 5 you have a working protocol implementation ready to back an agent system. + +--- + +## What Comes After + +- Agent discovery via `KindProfile` (kind 0) — capability advertisement +- Relay clustering / replication (out of scope for v1) +- Retention and event expiry policies -- cgit v1.2.3