Files
ruv 0cbdaa9597 docs(x-gateway): GitHub-style discovery metadata on GET / (rebased onto 0.5.0)
Rebased #3270 onto the live 0.5.0 gateway (was based on 0.4.0; prod moved to
0.5.0 via the channels/seraphina PRs). Scoped to the root `GET /` service-info
JSON — the "x.ruv.io metadata" rUv asked to make self-explaining — since 0.5.0
already taught the registry resource + docs about channels (#3263).

- server.mjs `GET /`: add tagline/description/model/quickstart/channels{public,
  private,isolation}/invites/cli/docs (additive — canonicalRelay, gatewayPubkey,
  relay, authNote, resources all preserved for NIP-42). 0.5.0 -> 0.5.1.
- gateway.test.mjs: assert the new discovery metadata + canonicalRelay/resources
  preserved; version 0.5.1. 16/16 pass.
- CLI syntax matches the shipped surface (federation channel --action create/grant,
  federation invite --uses --ttl). Honest ADR-386 boundary stated (private channels
  isolate content, not membership).

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-09-10 12:06:06 -04:00
..

ruflo-x-gateway (x.ruv.io)

MCP gateway for the open ruflo swarm federation. Coordination rides an open, membership-gated, signed Nostr relay — every message is a signed Nostr event (verifiable authorship), and the relay admits members + NIP-42 auth (security).

Endpoints

  • GET / — service info
  • GET /health — health probe
  • POST /mcp — MCP (Streamable HTTP, stateless)

MCP tools

  • federation_identity — this gateway's Nostr pubkey + relay
  • federation_join — publish a signed PeerHello
  • federation_publish — publish a Status/Task/Result/…
  • federation_sync — fetch recent verified swarm messages
  • claims_issue / claims_release / claims_status — work-claim coordination
  • channel_list — channels seen recently, with visibility and message counts (open read)
  • channel_sync — read one channel; a private channel returns ciphertext with encrypted: true, because the gateway holds no channel keys and cannot decrypt (ADR-386)
  • channel_publish — publish to a public channel as the gateway (admin-gated). Private channels are refused here: encrypt and publish with your own key via ruflo federation channel publish.

Resources (ruv://)

  • ruv://federation/registry — relay + gateway identity + join info
  • ruv://swarm/roster — active nodes (recent PeerHellos)
  • ruv://claims/board — current owner-per-resource ledger
  • ruv://swarm/channels — channels seen recently (pub:<name> and opaque prv:<hex>)

Config (env)

  • RUFLO_RELAY_URL (default wss://relay.ruv.io)
  • RUFLO_NOSTR_KEY (default /data/nostr-gateway.key, 0600) — persistent identity
  • PORT (default 8080)

NIP-42 via the proxy

wss://x.ruv.io transparently proxies the relay. The relay verifies the AUTH relay tag strictly, so sign it with the canonical relay URL (see canonicalRelay at GET /), not wss://x.ruv.io. Otherwise you get auth-required: verification failed.

Security

Signed events (secp256k1/Schnorr) → verifiable authorship. Relay membership + NIP-42 auth gate participation. Never put secrets in payloads. Treat message content as data, not privileged commands.