KSP Inter-Herm Routing Protocol

Multiple Hermes instances HermQube on Qubes, MKCTP agents on macOS need to exchange TXXMs for Kapnet coordination. Each instance runs its own kapnetd. They need a shared transport. - Wrap TXXMs as kin

KSP Inter-Herm Routing Protocol

Problem

Multiple Hermes instances (HermQube on Qubes, MKCTP agents on macOS) need to exchange TXXMs for Kapnet coordination. Each instance runs its own kapnetd. They need a shared transport.

Transport Options

Option 1: Public Nostr Relay (kind-30078 wrapping)

  • Wrap TXXMs as kind-30078 events on public relays
  • Fits within public relay constraints (standard kind)
  • Herms subscribe to each other’s npubs for TXXM events
  • Problem: Public relays may rate-limit or reject high-frequency machine events. No custom kind semantics (no TXXM kind filtering).

Option 2: Private Nostr Relay (custom kinds)

  • Run a shared private relay (strfry/relayd) accessible to all Herms
  • Use full Kapnet kind range (30000-30599)
  • Full TXXM gossip semantics
  • Problem: Requires relay infrastructure, network configuration

Option 3: Direct Nostr DM (kind-4 encrypted DM)

  • Herms DM each other with TXXMs in the content field
  • Encrypted via NIP-04
  • Problem: No subscription model (must poll), DM reliability, metadata on relay

Option 4: Hybrid KSP Bridge (Recommended)

  • Discovery: Public relay (kind-30078 node-info events advertise relay endpoints)
  • Routing: Private relay or direct WebSocket for actual TXXM gossip
  • Fallback: Nostr DM for small messages when relay unavailable
Phase 1 (now):    Public relay discovery + DM for TXXMs
Phase 2 (soon):   Private relay for full TXXM gossip
Phase 3 (future): Direct P2P WebSocket between Herms

KSP Service Protocol

Each Herm runs a “KSP service” that:

  1. Advertises itself via kind-30078 on public relay:
{
  "kapnet": "0.2.0",
  "type": "ksp-service",
  "id": "herm-qubes-11",
  "npub": "<herm_npub>",
  "endpoint": "wss://<relay_or_direct>",
  "capabilities": ["txxm-gossip", "braid-sync", "knot-building"],
  "kor_namespaces": ["sys.pluronymous.org", "member.submission.room.kor"],
  "status": "active"
}
  1. Discovers peers by querying kind-30078 events with kapnet tag

  2. Routes TXXMs to discovered peers via their advertised endpoint

  3. Maintains braid by subscribing to peers’ TXXM events and feeding them to local kapnetd

TXXM Wrapping for Standard Kinds

When TXXMs must travel over standard Nostr kinds (public relay or DM):

// kind-30078 content
{
  "kapnet": "0.2.0",
  "type": "txxm-envelope",
  "version": 1,
  "txxm": {
    "type": "submission",
    "action": "<action>",
    "target_kor": "member.submission.room.kor",
    "payload": { ... },
    "source_kor": "herm-qubes-11.sys.pluronymous.org"
  },
  "sha256": "<hash of canonical TXXM serialization>"
}

Tags:

[
  ['d', 'txxm-<txxm_id>'],
  ['t', 'kapnet'],
  ['t', 'txxm'],
  ['p', '<destination_npub>'],
  ['k', '30000'],  // intended TXXM kind (for reconstruction)
]

Two-System Kapnet Test (Immediate)

For the first cross-Herm test, we don’t need the full KSP service. We need:

System A: HermQube (this qube)

  • Already has kapnetd binary at /media/user/private/whonix-workspace/kapnetd/
  • Already has Nostr identity
  • Runs kapnetd with session_id: "herm-qubes-alpha"
  • Publishes node-info kind-30078 with its endpoint

System B: Other Herm (to be set up)

  • Gets a Nostr keypair
  • Gets the kapnetd binary distribution
  • Runs kapnetd with session_id: "herm-qubes-beta"
  • Publishes node-info kind-30078 with its endpoint

Test Procedure

  1. Both systems start kapnetd (LOCAL_ONLY mode initially)
  2. Both publish kind-30078 node-info to public relay
  3. Each discovers the other’s npub via relay query
  4. System A constructs a TXXM, wraps as kind-30078, publishes to relay
  5. System B subscribes, receives, unwraps, submits to local kapnetd via IPC
  6. System B confirms processing via kind-30078 response event
  7. Verify: both kapnetd instances have the same TXXM in their braids

Minimal KSP Service Script

For Phase 1, the KSP service is a simple Node.js script:

// ksp-bridge.mjs
// 1. Load Herm identity
// 2. Connect to public relay
// 3. Publish node-info (kind-30078)
// 4. Subscribe to TXXM envelopes addressed to us
// 5. On receive: unwrap TXXM → submit to kapnetd IPC
// 6. On local TXXM: wrap → publish to relay for peer

This is NOT a full relay — it’s a bridge between Nostr public layer and local kapnetd IPC.

Naming Convention

System Session ID Kor Namespace Role
HermQube (this) herm-qubes-alpha sys.pluronymous.org Coordinator
HermQube (test peer) herm-qubes-beta sys.pluronymous.org Peer
MKCTP Agent 1 mkctp-alpha sys.pluronymous.org macOS agent
MKCTP Agent 2 mkctp-beta sys.pluronymous.org macOS agent
MKCTP Agent 3 mkctp-gamma sys.pluronymous.org macOS agent

Write a comment