Agent signing keypair
Proves which agent is calling. RS256 keypair, generated on the customer device. We never see the private half.
Three trust zones, three keys, one decryption moment. Below is the high-level shape: what is held where, what is encrypted with what, and which boundary an attacker would have to cross to do real harm.
A credential never sits in plaintext on two sides of any boundary at once. Each zone has a different operator, a different blast radius, and a different recovery story if it falls.
Each key has exactly one purpose and lives with exactly one party. No key can do another key’s job on its own. Compromise one and you lose one layer.
Proves which agent is calling. RS256 keypair, generated on the customer device. We never see the private half.
Wraps every per-credential DEK belonging to one customer. Stored exclusively in an HSM-backed vault. The key material never leaves the HSM.
Encrypts one credential. Born fresh per credential, wrapped immediately by the tenant KEK, then stored as ciphertext alongside the wrapped credential.
Plaintext exists for the seconds it takes to encrypt or use. Outside those moments, the credential is ciphertext. The proxy is stateless across calls.
The OAuth callback returns a token to AgentValet’s edge over TLS. The token exists in memory only. We immediately generate a fresh per-credential DEK, encrypt the token, wrap the DEK using the tenant’s KEK in the HSM, then forget both plaintexts.
Only the encrypted credential, the wrapped DEK, the IVs and tags, and a reference to the KEK version are stored. Postgres Row Level Security enforces that one tenant cannot see another’s rows even with a stolen connection string.
The agent signs a 60-second JWT with its private key, sends it with the call. The proxy verifies the signature against the public key on file, evaluates policy (scope, approval gate, rate limit) before touching any credential.
The HSM unwraps the DEK. The DEK decrypts the credential. The credential is attached to the outbound upstream call, the call fires, the response returns. The plaintext is dropped before the function returns. Nothing is logged that would let an operator reconstruct the token.
An immutable audit row captures who, what, when, scope, result, and the size of the call. It does not capture the credential or the response body. The audit log is the only thing that persists after the call.
Across five common actors, here is exactly what each can read about a credential. Cells are intentional. Where AgentValet engineers have access, it is metadata only.
Each layer can revoke independently. From the smallest scalpel to the global cut, here is what each pull actually shuts down. None of them require AgentValet to ship code.
Untick a scope on one agent’s permission row. Next call returns scope_not_granted. Upstream untouched.
Suspend or revoke the agent. Its JWTs stop validating. Any other agents owned by the same human keep working.
one agent · all scopesDisconnect a platform at the owner level. All agents lose access to that SaaS instantly. The upstream OAuth grant is also revoked.
one platform · all agentsRotate or delete the tenant KEK. Every wrapped credential for that tenant becomes unrecoverable. Tenant-wide kill switch.
one tenant · everythingThe boundaries we hold even when it would be convenient not to.
We send a detailed architecture document, our DPIA template, and a written breach-analysis Q&A to security reviewers under NDA. If your compliance team needs to dig into any layer above before you can buy, this is the next conversation.