Skip to main content
Palyra implements a decentralized identity system based on Mutual TLS (mTLS) and a Trust-on-First-Use (TOFU) pairing handshake. Every entity in the system—the core daemon (palyrad) and various nodes (CLI, Desktop, Browser, or remote connectors)—possesses a unique cryptographic identity rooted in X.509 certificates issued by a transient, internal Certificate Authority (CA).

Identity Architecture

The identity system is managed by the IdentityManager in palyra-identity. It handles the lifecycle of the Gateway CA, device identities, and the secure storage of these credentials.

Certificate Authority (CA)

The CertificateAuthority struct in palyra-identity is responsible for generating the root of trust.

Device Identity

A DeviceIdentity represents a unique installation or actor.

Code Entity Mapping: Identity Management

The following diagram illustrates the relationship between the management logic and the underlying storage entities. Sources: crates/palyra-identity/src/pairing/manager.rs#45-75, crates/palyra-identity/src/ca.rs#34-39, crates/palyra-identity/src/pairing/persistence.rs#16-20

The Pairing Handshake (TOFU)

Pairing is the process by which an untrusted device establishes a permanent, mTLS-secured relationship with the Gateway. Palyra uses a multi-step handshake involving a shared secret (PIN or QR token).

Handshake Sequence

  1. Initiation: The Gateway creates a PairingSession containing a challenge and an ephemeral public key crates/palyra-identity/src/pairing/handshake.rs#27-52.
  2. Hello: The device responds with a DevicePairingHello. This includes its device_id, its own ephemeral public key, and a signature over the transcript crates/palyra-identity/src/pairing/models.rs#45-55.
  3. Verification: The Gateway verifies the signature and the proof (PIN/QR). If valid, it generates a VerifiedPairing crates/palyra-identity/src/pairing/handshake.rs#129-137.
  4. Approval: By default, pairing requires explicit administrative approval via the ApprovalsService crates/palyra-daemon/src/node_rpc.rs#187-210.
  5. Finalization: Once approved, the Gateway issues a client certificate to the device, which is then used for all subsequent mTLS connections crates/palyra-identity/src/pairing/handshake.rs#139-148.

Handshake Data Flow

Sources: crates/palyra-identity/src/pairing/handshake.rs#83-127, crates/palyra-daemon/src/node_rpc.rs#187-210, crates/palyra-cli/src/commands/pairing.rs#159-180

mTLS Enforcement

Once paired, the communication between nodes and the daemon is secured via mTLS.

Transport Layer Security

The system supports two primary secure transports:
  1. gRPC (Tonic): Used for high-level service calls. The NodeRpcServiceImpl enforces mTLS by inspecting TlsConnectInfo and validating the peer certificate fingerprint against the IdentityManager crates/palyra-daemon/src/node_rpc.rs#56-97.
  2. QUIC (Quinn): Used for low-latency event streaming. The quic_runtime uses rustls with a custom ClientCertVerifier to ensure only paired devices can connect crates/palyra-daemon/src/quic_runtime.rs#19-25.

Revocation

Certificates are not revoked via standard CRLs or OCSP. Instead, the IdentityManager maintains a list of revoked_devices. During the TLS handshake or at the application layer, the gateway checks if the certificate’s fingerprint belongs to a revoked device crates/palyra-daemon/src/node_rpc.rs#91-95.
ComponentLogic LocationEnforcement Mechanism
gRPC Servernode_rpc.rspeer_certificate_fingerprint check in every RPC crates/palyra-daemon/src/node_rpc.rs#56-97
QUIC Serverquic_runtime.rsQuicServerTlsConfig with require_client_auth crates/palyra-daemon/src/quic_runtime.rs#67-80
Identity Storemanager.rsFingerprint-to-Device mapping crates/palyra-identity/src/pairing/manager.rs#130-145

Pairing Manager & Node Runtime

The NodeRuntimeState in palyra-daemon tracks the state of active pairing requests and registered nodes.

Persisted State

The runtime persists state to node-runtime.v1.json, including:

Capability Dispatch

Paired nodes can register “Capabilities” (e.g., a local shell or browser automation). The NodeRuntimeState manages a queue of CapabilityDispatchRecord objects, allowing the gateway to route tasks to specific paired devices crates/palyra-daemon/src/node_runtime.rs#151-170. Sources: crates/palyra-daemon/src/node_runtime.rs#177-203, crates/palyra-daemon/src/node_rpc.rs#38-54, crates/palyra-identity/src/lib.rs#1-15