feat(swarm): wire-validator — rejection rules 1-13 (#86)#89
Merged
Conversation
…#86) Implements the pure runtime validator every receive path will compose: validateWireRecord(record, kind, opts) returns { ok: true } or { ok: false, rule, reason }. No DB, no HTTP, no I/O — all side-channel data (clock, pubkey-by-node lookup) injected via opts so the function is deterministic and trivially testable. Covers rules 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13. Skips 10 (caller's job — needs DB read), 14 (local trust), and 15 (transport-layer body cap), per the issue's explicit out-of-scope list. Reuses computeNodeId from services/node-identity.ts and verify from services/signature.ts rather than re-implementing — re-implementation would create a divergence surface against the producer side, which is exactly the regression the swarm trust premise cannot tolerate. Test coverage: 1 valid example per kind + 12 negative tests (one per implemented rule), each starting from a fully-valid record and mutating one invariant so the asserted rule cannot mask another. 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 28, 2026
Storage floor for /swarm/lessons and /swarm/hubs (Phase 3/4 endpoints land later). Schemas mirror docs/SWARM_SPEC.md §3.1 (Lesson) and §3.2 (HubAnchor); peer + local-trust columns extend `nodes` from migration 070. SWARM_SPEC §3.4 trust stays local — flat columns on `nodes`, no `trust_edges` table that could be JOINed into a wire response. Column-level CHECKs map to §5 rejection rules (defense in depth behind the wire-validator from PR #89): rule 9 signed_at >= created_at, rule 11 synthesized_from_cluster_size >= 2, rule 12 content/topic_label size caps, rule 4 embedding dim 768. HNSW vector_cosine_ops indexes match every other embedding index in the codebase (memories, experiences, lessons, soul_traits — migrations 002, 004, 015, 017). The issue body's ivfflat reference contradicted the established pattern; HNSW keeps query plans uniform. File only — Reed runs migrations manually after merge. Sibling SQL-text contract test pins every column, CHECK, FK, and index so a later edit cannot silently weaken the schema before the Phase 3/4 endpoints come online. Closes #88.
12 tasks
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
validateWireRecord(record, kind, opts)inmcp-server/src/services/wire-validator.tsreturning{ ok: true } | { ok: false, rule, reason }.mcp-server/src/__tests__/wire-validator.test.ts: one valid example per kind + 12 negative tests (one per implemented rule).Research summary
docs/SWARM_SPEC.md§3 (wire types) + §5 (rejection rules) end-to-end. Rules 14 (local trust) and 15 (transport body cap) are explicitly out-of-scope per the issue; rule 10 (duplicate detection) is also caller-side because it needs a DB read against ingested records.verify(record, sig, pubkey)fromservices/signature.ts(feat(swarm): signature service — Ed25519 sign/verify over JCS (#77) #82) for rule 5 — strips the on-wiresignaturefield internally before JCS-recomputing.computeNodeId(pubkeyRaw)fromservices/node-identity.ts(feat(swarm): node identity bootstrap + node_identity_get tool (#76) #81) for rule 6 — already exported, no re-export needed.wire-types.ts, Swarm Phase 3a: src/services/wire-types.ts — TypeScript types + JCS canonicalize helper #85) interface shapes verbatim so the validator's required-field tables track the spec table directly.Promise<ValidationResult>) per the issue contract even though the body is synchronous; matches the pattern other v1-locked-but-v2-extensible services in this repo took.What this does NOT do
Constitution affirmation
This change touches Pillar 6 — Cyber security: it is the single chokepoint that decides whether a received wire record influences local state, so every later ingest path becomes a one-line validate(...) call. It also reinforces Pillar 1 — Decentralized, networked AI by making the rejection contract identical for every node, and Pillar 3 — Swarm intelligence by enforcing the §3.1 generalization rule (rule 11) on the wire so raw episodes cannot leak as lessons. No pillar is weakened. Pillars 2 (Reproduction), 4 (Microtransactions), and 5 (Experts) are not touched.
Test plan
🤖 Generated with Claude Code