# Architecture

A deep dive into how Keychains.dev works under the hood — identity, permissions, proxy validation, and the security model.

## Four layers of trust

Access flows through four layers. Each builds on the previous — compromise at one layer doesn't break the others.

1. **Machine Identity**  
   Ed25519 SSH keypairs + rolling challenge-response + hardware fingerprinting. Proves which machine is acting. Challenge nonces are single-use — replayed signatures fail.

2. **Permission Request**  
   Stateful, user-approved authorization stored in Redis. Scoped or wildcard mode. Carries version tracking — any mutation bumps the version, invalidating in-flight tokens.

3. **Delegate Identity**  
   Immutable bootstrap identity with its own Ed25519 keypair and proof-of-possession. Allows remote systems to act with a reduced scope ceiling derived from the parent.

4. **Permission Token**  
   Short-lived JWT (5-15 min) for execution. Contains request ID and version — no scopes. Scopes are resolved from Redis at proxy time, ensuring revocations take effect instantly.

## Proxy validation algorithm

Every proxied request goes through this pipeline. All checks are stateful — the proxy is the final authority.

1. Verify JWT signature
2. Fetch Permission Request from Redis by requestId
3. Validate state: status === active, version matches, not expired
4. If delegateId: validate delegate chain + parent status
5. Validate machine challenge state
6. Resolve approvedScopes from Redis (not from token)
7. Check required scopes vs approved:
   - All present: proceed
   - Wildcard + missing: 403 + approval_url
   - Scoped + missing: 403 no recourse
   - Delegate ceiling exceeded: 403 scope_refused
8. Inject credentials server-side (OAuth tokens / API keys / basic auth)
9. Execute upstream call
10. Write audit log (non-blocking via after())

## Wildcard permissions

Wildcard permissions start with zero scopes and grow as the user approves each one. Every scope still requires explicit consent.

1. Agent calls proxy requiring github::repo
2. Proxy returns 403 with approval URL
3. User visits URL, approves github::repo
4. Scope added to approvedScopes, version bumps
5. Agent retries — proxy re-reads Redis — success

## Core data model

| Entity              | Storage  | Key fields                                                |
|---------------------|----------|----------------------------------------------------------|
| Machine             | Redis    | id, userId, publicKey, fingerprint, challengeNonce      |
| PermissionRequest    | Redis    | id, machineId, mode, status, requestedScopes, approvedScopes, version |
| Delegate            | Redis    | id, parentPermissionId, mode, publicKey, approvedScopes, ttl |
| PermissionToken     | JWT (stateless) | requestId, machineId, delegateId, version, exp  |
| AuditLog           | MongoDB  | userId, machineId, permissionId, provider, method, endpoint, status |

## Security properties

- **No secrets in tokens**  
  Permission tokens contain IDs and versions — never scopes, never credentials. Scopes are resolved server-side.

- **Version pinning**  
  Every mutation bumps the permission version. Tokens with stale versions are rejected. Revocation takes effect in under 1 second.

- **Cascade revocation**  
  Revoking a parent automatically revokes all delegates. No orphaned access, no cleanup needed.

- **Rolling challenges**  
  Each machine auth uses a single-use nonce. Concurrent auth from two locations triggers automatic revalidation.

- **Scope immutability (scoped)**  
  Once approved, scoped permissions can never expand. The set is frozen — auditable and predictable.

- **Audit everything**  
  Every proxied call is logged in MongoDB with full context. Dashboard provides real-time visibility.

## Credential injection

The proxy resolves and injects credentials based on the target API's requirements. Supported methods:

- **OAuth 2.0 / 2.1**  
  Access tokens refreshed automatically. Token rotation handled server-side.

- **API Keys**  
  Injected as headers or query params per provider spec.

- **Basic Auth**  
  Username/password pairs injected as Authorization headers.

[Key & Token Security](/content/docs/security/index.html)  
[API Reference](/content/docs/api/index.html)
