FIPS Plugin Architecture
The fips plugin provides domain-agnostic peer networking over the vendored mmalmi/fips-ts core protocol combined with jmcorgan/fips-style Nostr UDP NAT traversal.
Layout
init.ts—BotPluginentry point, registersfipsPeerNetworkProvider(peer-network:v1) and initializes the backgroundFipsNoderuntime.udp-nostr-transport.ts— Implements@fips/core'sTransportinterface over Node/BundgramUDP sockets using Nostr kind37195overlay adverts, NIP-59 gift-wrapped kind21059TraversalOffer/TraversalAnswersignaling, STUN (XOR-MAPPED-ADDRESS) + LAN candidate discovery, and 24-byteNPTC/NPTAUDP hole punching.runtime.ts— Manages theFipsNodeinstance (UdpNostrTransport+ optionalWebSocketTransport), handles/fips pingon service port4201, listens for app envelopes on service port4200, authenticates incoming envelopes againstfips_peers, and dispatches inbound payloads topeer-channel:v1providers.db.ts— SQLite persistence (fips_node_settingsfor the encrypted local FIPS keypair and optional seed URLs;fips_peersfor(master_pubkey, fips_pubkey, label, seed_urls_json, status, last_seen_at)).vendor/fips-ts/— Pinned snapshot ofmmalmi/fips-ts(packages/core,packages/transport-websocket,packages/transport-webrtc,packages/transport-memory).commands/— CLI and Web UI command handlers (status,invite,ping,seeds,add,list,show,delete).
Reading guide
- Signed invitation and acceptance flow
- Networking glossary
- Nostr event example, STUN flow, and diagnostics
- FIPS concepts and implementation boundaries
- Relay selection: current behavior and proposed improvements
- Implementation progress and remaining work
Identity and persistence
The instance retains its existing bot and master identities. The plugin
generates a third, dedicated FIPS keypair and encrypts its secret with core's
secret-storage helper. db.sqlite resides in the plugin directory; it contains
the local identity/settings and the peer roster. The runtime is instance-wide,
not separately instantiated for each active workspace.
The master public key names the human owner. The compressed FIPS key names the
endpoint. New fips2: invitations and acceptances are master-signed binding
statements with explicit relay, expiry, optional recipient, and one-time completion
state. See pairing. Legacy roster entries remain unverified.
Connection sequence
- Instances exchange a signed invitation and acceptance, adding each other to their rosters.
/fips ping <id>explicitly connects using the peer's FIPS key.- The UDP transport binds a fresh socket and queries configured STUN servers.
- It sends an encrypted traversal offer through the current signaling relay list. The receiver authenticates the inner seal and checks its peer roster.
- The receiver creates its own socket/candidates, sends an answer, and starts probing. The initiator probes after receiving the answer.
- A probe/ack selects a UDP endpoint; the same socket carries FMP authentication followed by the FSP session. A successful probe alone is not FIPS identity authentication.
- Ping/pong uses FSP service port
4201; app envelopes use4200. These are protocol service ports, not fixed host UDP listening ports.
Currently private IPv4 and loopback candidates are sent alongside reflexive candidates. Local-candidate policy and validation need further work before claiming the Rust implementation's behavior or deployment guarantees.
App-facing contracts
Apps invoke the shared peer-network contract to list peers or send an envelope containing a destination master key, channel, string payload, and nullable signature. The plugin looks up that master key in its roster and transports the envelope over FIPS.
Inbound app traffic must come from a rostered FIPS key and claim the associated master key. The plugin currently invokes all registered peer-channel providers, passing the channel along. Providers must filter channels themselves; selective channel-to-provider routing is not implemented.
The signature field is passed through, not verified by the networking plugin. Matching a roster entry establishes endpoint attribution, not a human-signed action. Apps own signature policy, project permissions, schema validation, durable offline queues, synchronization, review, merge, and revert behavior.
send currently reports delivered: true after the transport send completes.
That does not acknowledge receipt or acceptance by the remote app. Apps needing
those guarantees must exchange correlated acknowledgements.
Runtime limitations
runningmeans aFipsNodeobject started, not that a peer or relay is reachable.- WebSocket seeds are configured as additional carriers, but ping and app sends explicitly attempt UDP first. Automatic fallback after UDP failure is absent.
- The schema change allowing multiple FIPS endpoints per master has no migration for an existing table with a unique master-key constraint. Master-addressed sends also do not yet disambiguate multiple matching instances.
- No app data synchronization, persistent inbox/outbox, or merge implementation is supplied by this plugin.