Skip to content

feat(swarm): signature service — Ed25519 sign/verify over JCS (#77)#82

Merged
Dewinator merged 1 commit into
mainfrom
agent/issue-77-2026-04-27T20-01-26-605Z
Apr 27, 2026
Merged

feat(swarm): signature service — Ed25519 sign/verify over JCS (#77)#82
Dewinator merged 1 commit into
mainfrom
agent/issue-77-2026-04-27T20-01-26-605Z

Conversation

@Dewinator
Copy link
Copy Markdown
Owner

Summary

Research summary

  • mcp-server/src/services/ is the canonical home for new services (matches node-identity.ts from Swarm Phase 1b: scripts/init-node-identity.mjs + node_identity_get MCP tool #76); tests live under src/__tests__/ and run via node --test on the compiled output.
  • The existing crypto.ts exposes a non-JCS canonicalJson and Ed25519 helpers used by the legacy genome-lineage code. SWARM_SPEC §2 explicitly mandates JCS (RFC 8785), so reusing the legacy helper would silently drift the wire-format. New file added; legacy file untouched.
  • Node's crypto.sign(null, data, key) is the correct Ed25519 path (Node 14+); createSign('sha256') does NOT work for Ed25519 because Ed25519 prehashes internally.
  • For JCS conformance we used pure JSON.stringify-based string/number serialization: V8's JSON.stringify follows the same minimal-escape rules and the same ECMAScript Number-to-String algorithm RFC 8785 §3.2.2 references. Object key sorting uses Array.prototype.sort (default UTF-16 code-unit order, exactly what RFC 8785 §3.2.3 requires).
  • Issue Swarm Phase 1b: scripts/init-node-identity.mjs + node_identity_get MCP tool #76's node-identity.ts pattern was followed for testability — no I/O coupling in the pure functions; signWithSelfKey accepts a loadPem injection point so tests don't touch disk.

What this does NOT do

  • No networking, HTTP, or libp2p wiring (issue Hard constraint).
  • No integration into existing record-creation paths (lesson synthesizer, hub anchors, advertisements). That is the explicitly-deferred Phase 2.5 follow-up.
  • No migration files touched, no node-identity script touched (read-only dependency on the privkey at ~/.mycelium/node.key).
  • No key rotation, no revocation lists, no multi-signature schemes (v2 scope).

Constitution affirmation

  • Touches Pillar 6 — Cyber security: every record that ever leaves a node will be signed via these primitives. JCS bytes-stability + Ed25519 verification are what make the swarm trust premise work — no agent can speak for another node, signatures are computed over canonical bytes (not the producer's serialization), and the verifier collapses every malformed-input path to false rather than throwing on the network edge.
  • Adjacent Pillar 1 — Decentralized, networked AI and Pillar 5 — Experts in the swarm rely on signatures to attribute records to a node_id; this PR enables those without yet asserting them.
  • No pillar is weakened. The privkey continues to live only in the chmod-0600 file written by scripts/init-node-identity.mjs; this service reads it through an injectable loadPem hook so tests never need a real key on disk.

Test plan

cd mcp-server && npm test

Expect 22 new passing tests under signature (canonicalize conformance, sign/verify round-trip, tamper detection, wrong-key rejection, signature-field exclusion, signWithSelfKey wrapper). The pre-existing migration-070-node-identity.test.js failure is unrelated — it fails because supabase/migrations/070_node_identity.sql is still pending in PR #79.

Spot-check the wire-format anchor test (sign: wire-format anchor — independent re-derivation matches): it builds the canonical bytes by hand ({"a":1,"m":2,"z":3}) and signs via raw node:crypto, then asserts equality with the service's output. If this ever fails, the service has drifted from the JCS contract.

🤖 Generated with Claude Code

Phase 2 of the Swarm Foundation Plan v1. Adds the reusable crypto
primitives every later swarm record (Lesson, HubAnchor, NodeAdvertisement)
will sign with: a pure RFC 8785 (JCS) canonicalizer plus Ed25519
sign/verify wrappers around node:crypto. The contract — strip the
`signature` field, JCS the remainder, sign the UTF-8 bytes, base64 the
64-byte signature — matches docs/SWARM_SPEC.md §2.

22 new tests pin: JCS key sorting (UTF-16 code units), I-JSON number
constraint (NaN/Inf rejected), independent-derivation wire-format
anchor, round-trip, single-byte tamper detection, wrong-pubkey
rejection, defensive `false` returns on garbage input, signature-field
exclusion from signed bytes, signWithSelfKey signed_at attached to the
signed payload.

No networking. No integration with existing record-creation paths
(follow-up issue). Read-only on the privkey written by issue #76.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Dewinator Dewinator added the agent-opened Opened by the autonomy loop label Apr 27, 2026
@Dewinator Dewinator merged commit 39d3fde into main Apr 27, 2026
@Dewinator Dewinator deleted the agent/issue-77-2026-04-27T20-01-26-605Z branch April 27, 2026 20:19
Dewinator added a commit that referenced this pull request Apr 29, 2026
Updates the stale "spec-only" header (phases 0–3 have all merged via
PRs #79/#81/#82/#85/#89/#91/#92) and pins each phase to its issue +
merged commit so a reader can tell at a glance which sections are wired
on `main` vs. still paper.

Phases 4–9 are deliberately listed as "_not yet issued_" — the project's
current priority is *Gehirn perfektionieren* per CLAUDE.md § Roadmap
(Reed 2026-04-26), and the wire contract is frozen at v1.0 so an
independent implementer can build a phase-3-equivalent peer today.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dewinator added a commit that referenced this pull request Apr 29, 2026
The cryptographic foundation of the swarm (SWARM_SPEC v1, Ed25519
signing, JCS canonicalization, wire-validator, .well-known discovery,
peer/signed-record storage — PRs #78,#79,#81,#82,#85,#89,#91,#92) was
landing on main while the README/MANIFESTO still claimed
"pairing/swarm/federation deferred". This commit fixes that mismatch.

README (EN+DE):
- new "Swarm — federation in flight" section with merged-PR table
  and a "what is next" subsection pointing to the swarm label
- Roadmap rewritten: phase 4-5 from "deferred" to "Phase 1 shipped"
- existing /.well-known/mycelium-node block folded into the new section
- promo video as a clickable poster near the top, served from a
  v0.4-swarm-phase-1 GitHub release asset (14 MB H.264 1080p)

MANIFESTO (EN+DE):
- "What is built today" split into brain core + Swarm Phase 1
- aspirational Tailscale+mTLS / mutual-pairing claims removed; those
  pieces remain on archive/swarm-deferred as historical reference
- "What is not built yet" sharpened to the social layer (verification,
  reputation, banishment-by-consensus, Sybil resistance) plus
  micro-transactions

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-opened Opened by the autonomy loop

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant