1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
|