Documentation menu
Concepts

Security & trust model.

ProgressPals is built for small teams that trust each other. We’re explicit about what we protect and what we don’t. If the threat model below doesn’t fit yours, this is the right time to find out.

What is protected

Membership

Swarms are invite-only. There is no public discovery. The only people who can join your swarm are people you handed an invite token to. The backend enforces a per-swarm allow-list of peer IDs; servers refresh the list and reject RPCs from anyone not on it.

Identity

Every machine has a libp2p identity key that’s generated on the first server start (pals create / pals join / pals serve). The cryptographic peer ID derived from that key is verified during the libp2p handshake — you can’t spoof a peer ID without the matching private key.

Activations in transit

Activation tensors travel between peers under AES-256-GCM. The encryption key is derived from your swarm’s shared secret using HKDF-SHA256. The key never leaves member machines — the backend only stores material it needs to verify invites.

Auth-tag integrity

Because activations travel inside AES-GCM, a misbehaving peer can’t silently corrupt the chain — they’d need to forge a valid 128-bit authentication tag without the key. Tampering is detected before the next layer runs.

What is not protected

Read this section carefully. These aren’t bugs — they’re properties of P2P inference that no client-side cryptography can fix.

The first peer sees your input

Whoever holds layer 0 must decrypt your prompt to run their layers. That’s how transformer inference works. The only mitigations are: only invite people you would trust to read your prompts, or host layer 0 yourself.

Peers can see each other’s IPs

libp2p connections are direct. Any swarm member can observe the IP addresses of the peers they talk to. If your threat model requires hiding IPs, route the swarm over a VPN or a private mesh (Tailscale, Wireguard).

This is not a hardware enclave

Peers run regular user-space Python. There’s no SGX, no SEV, no Nitro. A peer with admin access to their own machine can inspect the activations passing through it.

Practical guidance

For operators

  • Choose your pals carefully. Treat “can join my swarm” as “can see my prompts” — because functionally it is.
  • Use short-lived invites. pals invite create --max-uses 1 --expires-hours 24 is the right default. Long-lived multi-use tokens are an unnecessary attack surface.
  • Pass invite tokens via secure channels. Signal, encrypted email, a 1Password share. Not SMS, not Slack DM in plaintext.
  • Revoke aggressively. When someone leaves the team, pals peers kick immediately; allow-list refreshes propagate within ~30 seconds.
  • Never expose pals serve publicly without an API key. The CLI refuses to start a non-loopback endpoint without --api-key for this reason.

For joiners

  • Pass tokens via env. export PROGRESSPALS_INVITE_TOKEN=... then pals login. Putting the token on the command line leaks it into /proc/<pid>/cmdline and your shell history.
  • Your identity.key is sensitive. It identifies your machine to the swarm. Mode 0600 on a single-user system is sufficient. Don’t commit it to git, don’t copy it across machines (run pals init fresh on each).
  • Validate the operator. The invite token doesn’t prove who the operator is. Confirm the multiaddr through a trusted channel before joining unknown ones.

What lives where, at rest

Your machine

config.json (mode 0600) and identity.key. Your swarm secret, peer credential, and identity key are all here.

ProgressPals backend

Account records, swarm metadata, the list of redeemed peer IDs, and the per-swarm shared secret (base64-encoded) so the redeem_invite RPC can hand it to peers who present a valid invite token. Not prompts, not weights, not activations, not the AES key itself — the AES-256-GCM key is derived from the shared secret via HKDF-SHA256 on each peer’s machine and never transmitted anywhere.

In transit

Activations are AES-256-GCM ciphertext. Control-plane RPCs run over libp2p’s Noise-encrypted channels.

Next steps