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

Reading guide

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

  1. Instances exchange a signed invitation and acceptance, adding each other to their rosters.
  2. /fips ping <id> explicitly connects using the peer's FIPS key.
  3. The UDP transport binds a fresh socket and queries configured STUN servers.
  4. It sends an encrypted traversal offer through the current signaling relay list. The receiver authenticates the inner seal and checks its peer roster.
  5. The receiver creates its own socket/candidates, sends an answer, and starts probing. The initiator probes after receiving the answer.
  6. 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.
  7. Ping/pong uses FSP service port 4201; app envelopes use 4200. 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