feat(swarm): signature service — Ed25519 sign/verify over JCS (#77)#82
Merged
Merged
Conversation
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>
This was referenced Apr 28, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mcp-server/src/services/signature.tsimplements the reusable Ed25519 sign/verify primitives for Swarm Phase 2 (issue Swarm Phase 2: src/services/signature.ts — Ed25519 sign/verify with JSON canonical form #77).node:cryptoEd25519 wrappers; no external dependencies.docs/SWARM_SPEC.md§2.Research summary
mcp-server/src/services/is the canonical home for new services (matchesnode-identity.tsfrom Swarm Phase 1b: scripts/init-node-identity.mjs + node_identity_get MCP tool #76); tests live undersrc/__tests__/and run vianode --teston the compiled output.crypto.tsexposes a non-JCScanonicalJsonand 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.crypto.sign(null, data, key)is the correct Ed25519 path (Node 14+);createSign('sha256')does NOT work for Ed25519 because Ed25519 prehashes internally.JSON.stringify-based string/number serialization: V8'sJSON.stringifyfollows the same minimal-escape rules and the same ECMAScript Number-to-String algorithm RFC 8785 §3.2.2 references. Object key sorting usesArray.prototype.sort(default UTF-16 code-unit order, exactly what RFC 8785 §3.2.3 requires).node-identity.tspattern was followed for testability — no I/O coupling in the pure functions;signWithSelfKeyaccepts aloadPeminjection point so tests don't touch disk.What this does NOT do
~/.mycelium/node.key).Constitution affirmation
falserather than throwing on the network edge.node_id; this PR enables those without yet asserting them.scripts/init-node-identity.mjs; this service reads it through an injectableloadPemhook so tests never need a real key on disk.Test plan
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-existingmigration-070-node-identity.test.jsfailure is unrelated — it fails becausesupabase/migrations/070_node_identity.sqlis 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 rawnode: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