Identity and keys
Every Covenant install holds a single ed25519 keypair. The same key signs capability grants, signs Solana settlement transactions, and appears as the issuer on audit events and memory records. Covenant does not maintain a secondary key system.
Persistence
The keypair is stored as the raw 32-byte seed at $COVENANT_HOME/identity/local.key with mode 0600 (owner read/write only). The daemon refuses to start if the key file has broader permissions; restrict the file with chmod 0600 to recover.
The corresponding public key is derived from the seed and attached to every AgentId the daemon emits as issuer.
The AgentId shape
AgentId {
display: "user@local", // human-readable label
pubkey: [u8; 32] // raw ed25519 pubkey
}The display half is set on first daemon start (default user@<hostname>). The public key is derived from the seed and is the cryptographically meaningful identifier; display strings may collide, public keys cannot.
Signing helpers
The covenant-identity crate exposes:
LocalIdentity::generate(display)— fresh ed25519 keypair plus display string.LocalIdentity::load_or_create(path, display)— loads from disk if present, else generates and persists.LocalIdentity::sign(&self, message)— signs arbitrary bytes.verify_with_pubkey(pubkey, message, signature)— read-side verification; returnsResult<(), SignatureError>.verifying_key_from_bytes(pubkey)— converts a 32-byte pubkey to aned25519_dalek::VerifyingKey.
The signing helpers are deliberately minimal and do not prescribe a canonical message encoding. The capability layer (covenant-permissions) supplies its own encoder and passes the resulting bytes to the signing helpers.
Roles
The same ed25519 keypair is used to:
- sign capability tokens (
SignedCapability); - sign Solana settlement transactions when the daemon flushes receipts on-chain;
- appear as the
issueron audit events and as theowneron memory records.
A single key across all three roles reduces the operator's key-management surface to one artifact. The trade-off is that compromise of the key affects all three roles; the deployment benefit is one artifact to back up, rotate, and protect.
Rotation
Rotation is deliberate and disruptive. Re-issuing the keypair invalidates every capability signed under the prior key: verification fails because the expected granter public key no longer matches the daemon's active key. Plan the corresponding re-grant in advance of rotation.
Procedure:
- Stop the daemon.
- Move the existing key file aside, or delete it once no other state references the corresponding public key.
- Start the daemon. A new keypair is generated on first run.
- Re-grant the capabilities required by registered agents. The audit log records the rotation implicitly through the change of issuer on subsequent events, and explicitly through the new grant events.
- Update any external systems bound to the prior public key (Solana program authority records, third-party integrations).
Subordinate keys
The current implementation provisions one keypair per host. A later milestone introduces subordinate keys for delegated agents, each signed by the root key, so that compromise of an individual subordinate does not require a full root rotation. Until that capability ships, the single keypair carries the same protection requirements as a host SSH key.
Related
- Capability tokens — everything that depends on the signing helpers.
- Settlement — the on-chain side that signs with the same key.
- Security model — the file-permissions, threat-model context.