feat(swarm): node identity bootstrap + node_identity_get tool (#76)#81
Merged
Conversation
Spec-only first phase of the Mycelium Swarm Foundation Plan v1. Defines spec versioning, JCS (RFC 8785) over Ed25519 for signatures, the four wire types (Lesson, HubAnchor, NodeAdvertisement, TrustEdge), four HTTP/JSON endpoints, and uniform rejection rules. No code, no migrations. Restates the three unverletzlichen Designprinzipien (Souveränität, Generalisierung-vor-Sharing, Diversität) at the top so all later phases implement against the same contract and the same constraints. Closes the Phase-0 deliverable of issue #74.
) Swarm Phase 1a: schema-only migration that creates the `nodes` table holding this mycelium node's public key and node_id (multihash of the pubkey), plus any peers we will later learn about. The PRIVATE key is deliberately NOT a column — it lives outside the database in a chmod-600 file at ~/.mycelium/node.key (Verfassung pillar 1, Souveränität). Includes a partial UNIQUE index `nodes_only_one_self ON nodes ((1)) WHERE is_self` that enforces "at most one row may carry is_self=true", and a sibling TS contract test (`migration-070-node-identity.test.ts`) that pins the canonical SQL: column types, defaults, and the partial predicate. The test reads the raw SQL — it does not run the migration. Out of scope: keypair-generation script and the `node_identity_get` MCP tool (both phase 1b, separate issue); signature service (phase 2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swarm Phase 1b. Builds on migration 070 (#75 / nodes table) by giving the node a way to (a) generate its Ed25519 keypair on first run and (b) expose the resulting identity over MCP. Wire format follows docs/SWARM_SPEC.md §3.5 exactly: node_id = base58btc(multihash(sha2-256, pubkey_raw)) The privkey lives in ~/.mycelium/node.key with mode 0600 inside a 0700 directory; it never enters the database. Bootstrap is idempotent and refuses to act when the DB has a self row but the privkey file is missing — that combination is unrecoverable signing-state. 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.
Closes #76 — Swarm Phase 1b.
Summary
scripts/init-node-identity.mjs: idempotent Ed25519 keypair bootstrap. Privkey lands in~/.mycelium/node.key(mode 0600, 0700 directory); pubkey + derivednode_idgo into thenodesself-row.node_identity_get: read-only, returns{ node_id, pubkey_b64, display_name, created_at }.node_idfollowsdocs/SWARM_SPEC.md§3.5 exactly:base58btc(multihash(sha2-256, pubkey_raw))→ 46-charQm…string.Research summary
tools/identity.ts,tools/soul.ts) and copied the read-onlygetSelfModelshape for the new tool.node:cryptoalready supports Ed25519 (generateKeyPairSync('ed25519')); existingservices/crypto.tsuses the same SPKI-tail pattern to extract the raw 32-byte pubkey, so I reused it.docs/SWARM_SPEC.md(merged ina50444a); the migration spec from Swarm Phase 1a: migration 070 — node_identity table (file only, do NOT run) #75 is insupabase/migrations/070_node_identity.sql(merged in3cce198). PR feat(swarm): migration 070 — nodes table for cryptographic identity (#75) #79 (which includes the contract test) is still open but the schema needed by this PR is already onmain.2NEpo7TZRRrLZSi2U'Hello World!' vector.What this does NOT do
nodestable is missing.display_nameheuristic — the bootstrap optionally honoursMYCELIUM_NODE_DISPLAY_NAME, otherwise leaves the field NULL.Constitution affirmation
Touches Pillar 1 (Decentralized) and Pillar 6 (Cyber security). Reinforced, not weakened:
Test plan
cd mcp-server && npm test— 271 tests pass, including 12 new ones innode-identity.test.ts:computeNodeIdrejects non-32-byte input, is deterministic, distinguishes inputs, produces a 46-charQm…, matches the spec formulacd mcp-server && npm run build && node scripts/init-node-identity.mjs— verify (a)~/.mycelium/node.keyis created with 0600, (b)nodestable has exactly oneis_self=truerow, (c) running again printsnode_id already initialized: …and inserts nothing, (d) callingnode_identity_getfrom any MCP client returns the samenode_id.