Federation Peer Setup
What this runbook covers
Generate keypairs, register peers, pin public keys, and tune source-trust scores for Stigmem federation.
Audience: operators setting up cross-node federation for the first time; operators adding or removing peers.
Spec reference: Spec-03-HTTP-API for route shape, Spec-05-Federation-Trust for peer registration and pull replication, and Spec-04-Manifests for signed peer declarations.
See also: Federation guide, Federation trust.
Conceptsโ
Federation lets Stigmem nodes replicate facts from peers. Each peer must:
- Expose a
/.well-known/stigmemdiscovery endpoint. - Present a valid Ed25519 public key in its
PeerDeclaration. - Be registered (pinned) by the receiving node before replication starts.
Source-trust scoring (Spec-05-Federation-Trust) lets you weight incoming facts by source. Untrusted sources land in the quarantine garden until you promote them.
Step 1 โ Generate your federation keypairโ
python3 -c "
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
import base64
priv = Ed25519PrivateKey.generate()
priv_bytes = priv.private_bytes_raw()
pub_bytes = priv.public_key().public_bytes_raw()
print('STIGMEM_FEDERATION_PRIVKEY=' + base64.urlsafe_b64encode(priv_bytes).decode())
print('STIGMEM_FEDERATION_PUBKEY=' + base64.urlsafe_b64encode(pub_bytes).decode())
"
Store both values in your secrets manager. Never commit them to version control.
Set them on your node before starting:
# Docker Compose โ add to deploy/compose/.env
STIGMEM_FEDERATION_PUBKEY=...
STIGMEM_FEDERATION_PRIVKEY=...
STIGMEM_FEDERATION_ENABLED=true
Step 2 โ Verify your well-known endpointโ
curl -s https://your-node.example.com/.well-known/stigmem | jq .
Expected PeerDeclaration response:
{
"node_id": "stigmem:node:abc123...",
"node_url": "https://your-node.example.com",
"public_key": "<base64url-ed25519-pubkey>",
"pull_interval_s": 30,
"spec_version": "1.1"
}
If public_key is missing or node_id changes across restarts, your keypair is not being persisted โ check that STIGMEM_FEDERATION_PUBKEY and STIGMEM_FEDERATION_PRIVKEY are set.
Step 3 โ Register a peerโ
curl -X POST https://your-node.example.com/v1/federation/peers \
-H "Authorization: Bearer $STIGMEM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"peer_url": "https://peer-node.example.com",
"trusted_public_key": "<base64url-ed25519-pubkey-of-peer>"
}'
Pinning the trusted_public_key means your node will reject any PeerDeclaration signed with a different key.
This prevents impersonation after a key rotation on the peer side.
Verify the peer was registered:
curl -s https://your-node.example.com/v1/federation/peers | jq .
Step 4 โ Confirm replication is runningโ
# Check peer status
curl -s https://your-node.example.com/v1/federation/peers/<peer-id> | jq '{last_pull, pull_lag_ms, error}'
# Check audit log for pull events
curl -s "https://your-node.example.com/v1/federation/audit?limit=10" | jq .
Step 5 โ Pin public keysโ
To update a pinned key after a legitimate peer key rotation:
# Fetch the peer's new public key
NEW_KEY=$(curl -s https://peer-node.example.com/.well-known/stigmem | jq -r .public_key)
# Update the pin
curl -X PATCH https://your-node.example.com/v1/federation/peers/<peer-id> \
-H "Authorization: Bearer $STIGMEM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d "{\"trusted_public_key\": \"$NEW_KEY\"}"
Step 6 โ Tune source-trust scoresโ
Each source gets a scalar trust score t โ [0, 1]. At recall time, effective confidence is weighted by the trust score. Facts from sources below the quarantine threshold land in the quarantine garden.
View current scoresโ
curl -s https://your-node.example.com/v1/federation/trust-scores | jq .
Set a scoreโ
curl -X PUT https://your-node.example.com/v1/federation/trust-scores/<source-id> \
-H "Authorization: Bearer $STIGMEM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"score": 0.8}'
Quarantine thresholdโ
The default quarantine threshold is 0.3. Facts from sources with t < 0.3 are routed to the quarantine garden and excluded from standard recall.
STIGMEM_TRUST_QUARANTINE_THRESHOLD=0.3
Promote facts from quarantineโ
# List quarantined facts
curl -s "https://your-node.example.com/v1/facts?garden=quarantine&limit=50" | jq .
# Promote a batch to the default garden
curl -X POST https://your-node.example.com/v1/federation/quarantine/promote \
-H "Authorization: Bearer $STIGMEM_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"fact_ids": ["<id1>", "<id2>"]}'
Removing a peerโ
curl -X DELETE https://your-node.example.com/v1/federation/peers/<peer-id> \
-H "Authorization: Bearer $STIGMEM_ADMIN_KEY"
Removing a peer stops the pull loop immediately. Facts already replicated are retained.
Federation env-var referenceโ
STIGMEM_FEDERATION_ENABLEDSTIGMEM_FEDERATION_PUBKEYSTIGMEM_FEDERATION_PRIVKEYSTIGMEM_FEDERATION_PULL_INTERVAL_SSTIGMEM_FEDERATION_NONCE_WINDOW_SSpec-11-Replay-Protection).STIGMEM_FEDERATION_ALLOW_TEAMteam-scoped facts across federation boundaries.STIGMEM_TRUST_QUARANTINE_THRESHOLDTroubleshootingโ
STIGMEM_FEDERATION_ENABLED=false. Set to true and restart.signature_mismatch in audit lognode_id changes across restartsSTIGMEM_FEDERATION_PUBKEY/PRIVKEY env vars.STIGMEM_NODE_URL is reachable from the peer.