Security

Ed25519 Identity

Every peer has an Ed25519 keypair. The PeerID is derived from the public key using the Base58btc identity-multihash encoding (identity-multihash(libp2p-protobuf(pubkey))), producing a string in 12D3KooW… format.

Key operations:

  • ip.peer.action_generate_keys() — creates the keypair and derives the PeerID. If a valid PeerID is already present, the existing key is extracted rather than overwritten.

  • ip.peer._sign_payload() — signs outbound event payloads with the private key.

  • ip.peer._verify_signature() — verifies a signature against a payload and public key on receipt. Events that fail verification are rejected before any database write occurs.

The private key is stored encrypted and is visible only to users in the sync_manager group.

Danger

Never expose private_key via a public controller, store it in logs, or include it in database dumps shared outside your organisation. A leaked private key allows an attacker to forge events that pass signature verification.

See also

Technical reference — sync_base.ip.peer.

Peer Trust Levels

Every peer carries a ip.peer.trust_level that controls gateway behaviour for content from that peer:

Level

Behaviour

unknown

Events are admitted and stored. CID content is fetched from this peer only when the node actually serves it. Use this for peers you have not yet verified.

trusted

Events are admitted and stored. CID content is fetched and an ip.cid record is created regardless of node response. Use this only for peers you control or have verified out-of-band.

blocked

All payloads from this peer are rejected at the gateway before any ip.event record is created. No ORM call is made.

Note

Whether admitted events are auto-imported depends on the topic’s auto_import flag, not on trust_level. To prevent records from being created automatically, archive the topic rather than demoting a peer.

Promote a new peer from unknown to trusted only after confirming its PeerID matches the public key you expect — for example by comparing the ip.peer.peer_char value over a secure side-channel. Use ip.peer.action_validate_keys() to verify that the stored keypair is internally consistent before trusting a peer.

Bearer Tokens (HTTP Transport)

Each ip.node stores its own odoo_api_key — the API key of a user on the remote Odoo instance, not the gateway’s own credentials. When the gateway POSTs an event to a peer, it presents that peer’s key as the Bearer token. The receiving Odoo maps the token to a local res.users and applies that user’s access rights.

This design means:

  • The gateway never shares its own credentials with peers.

  • Revoking a compromised key on the remote Odoo is sufficient; no gateway restart is needed. Update odoo_api_key on the node record to the new key.

  • Each peer relationship has an independent key, so compromising one peer’s key does not affect other peers.

Keys are stored encrypted in Odoo and are visible only to users in the sync_manager group.

See also

ip.node.api_user_id, sync_base.ip.node — node field reference. api_node_id, users — the inverse relation: which node a user’s API key authenticates.

Swarm Keys (Kubo Transport)

A private IPFS network uses a swarm.key pre-shared key to prevent unauthorised nodes from joining at the TCP layer. Any Kubo daemon that does not hold the correct key is mathematically rejected before it can exchange messages.

The key is generated by 001-setup-swarm.sh on first boot. Share the swarm.key file out-of-band with every trusted peer — for example via an encrypted channel or a secrets manager.

Warning

Never commit swarm.key to version control. Regenerate and redistribute the key if exposure is suspected.

See also

Deployment — swarm key generation on first boot and distribution procedure.

Defense in Depth

Odoo Sync uses a three-layer security model. Each layer catches a different class of threat, so a failure at one layer does not mean an attacker reaches the application.

Network layer  → swarm.key rejects unknown TCP peers (Kubo only)
Gateway layer  → rate limits, payload size cap, blocked-peer cache
Application    → Ed25519 signature verification + trust_level check

Layer 1 — Network: The Kubo swarm key ensures only nodes with the correct pre-shared key can establish a TCP connection. External attackers or misconfigured nodes are stopped here before any data is exchanged.

Layer 2 — Gateway: The gateway enforces rate limits and a maximum payload size. Blocked peers are cached in memory so repeated requests from a blocked PeerID are rejected immediately without a database lookup.

Layer 3 — Application: Every inbound event payload is verified against the sender’s Ed25519 public key. Even if a peer passes layers 1 and 2, a forged or tampered payload is rejected here. The trust_level check then determines whether a verified event is auto-imported or held for manual review.