Skip to content

Swarm Phase 3c: GET /.well-known/mycelium-node — serve self-signed NodeAdvertisement #87

Description

@Dewinator

Why

First end-to-end wire-path. SWARM_SPEC §4.1 requires every node to expose its self-description at a well-known URL, unauthenticated and idempotent. Discovery starts here — once this lands, an external curl can verify our node is reachable and the multihash invariant holds.

This PR also exists to PROVE that Phase 1a (nodes table) + Phase 1b (identity bootstrap) + Phase 2 (signature service) + Phase 3a (wire types) compose without modification. If they don't, that's the bug we want to find now.

Background — read this BEFORE starting

  • mcp__vector-memory__prime_context with task_description "implement /.well-known/mycelium-node endpoint for swarm discovery"
  • Read docs/SWARM_SPEC.md §3.3 (NodeAdvertisement fields) and §4.1 (endpoint contract) and §4.5 (common HTTP behavior)
  • Look at how the existing dashboard/HTTP server is wired up (likely src/services/http-*.ts or similar) — match the existing route-registration style
  • Phase 1b's node_identity_get MCP tool already knows how to read the local node's node_id + pubkey — REUSE its internal helper, do not re-read the keyfile twice in the codebase
  • Phase 2's signWireRecord (or whatever the signature.ts entrypoint is named) does the JCS+Ed25519 signing

What this issue delivers

A new module src/swarm/endpoints/node-advertisement.ts plus its registration in the existing HTTP entrypoint, that handles GET /.well-known/mycelium-node:

  • Loads node_id, pubkey from the row in nodes where is_self = true (single row, enforced by the partial unique index from migration 070)
  • Reads endpoint_url from env MYCELIUM_PUBLIC_URL (required; if missing, return 503 with body {"error":"MYCELIUM_PUBLIC_URL not configured"})
  • Reads optional display_name from env MYCELIUM_DISPLAY_NAME (≤ 64 chars per §3.3)
  • Constructs a NodeAdvertisement with spec_version = WIRE_SPEC_VERSION from Phase 3a
  • Sets signed_at = new Date().toISOString() with millisecond precision (UTC, Z suffix per the spec table)
  • Signs via Phase 2's signer
  • Responds 200 with Content-Type: application/json; charset=utf-8 and Cache-Control: no-store

Acceptance criteria

  • New file src/swarm/endpoints/node-advertisement.ts
  • Route GET /.well-known/mycelium-node is reachable via the existing HTTP server (no new server, no new port)
  • Integration test that:
    • Boots the server (or uses the existing test harness)
    • Hits the endpoint
    • Asserts: status 200, correct content-type, correct cache-control, body parses as JSON, all required NodeAdvertisement fields present, multihash(pubkey) === node_id (use the same multihash helper Phase 1b introduced)
    • Asserts: signature verifies via Phase 2's verifier against the returned pubkey
  • README or CLAUDE.md note about the new env vars MYCELIUM_PUBLIC_URL and MYCELIUM_DISPLAY_NAME

Hard constraints

  • DO NOT add authentication. Per §4.1, this endpoint is unauthenticated.
  • DO NOT introduce a new web framework. Use whatever already serves the dashboard.
  • DO NOT generate keys here. If nodes.is_self is missing, return 503 with a clear error — do NOT silently create a key.
  • DO NOT change the response shape. The body MUST be exactly a single NodeAdvertisement object, no envelope.

Out of scope

  • /swarm/peers, /swarm/lessons, /swarm/hubs → later Phase 3 / Phase 4 issues
  • Validator integration → Phase 3b is the validator; this endpoint produces records, doesn't consume them
  • TLS termination — assumed to be handled at the reverse proxy / dashboard layer; this endpoint serves plain HTTP and trusts the proxy for https://

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-eligibleAutonomous agent loop is allowed to pick thisfoundationPhase-0/1 Fundament für ein größeres FeatureswarmSchwarm-Foundation: dezentrale P2P-Architektur

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions