Security Model
The complete authentication and credential architecture — at docs depth. For the questionnaire-ready summary, see the Security page.
Identity: Ed25519 + RFC 7523
On first spineforge.init() with a registry URL:
- SDK generates an Ed25519 keypair using a CSPRNG
- Private key written to
.spineforge/agent_key.pem— never transmitted - Public key sent to
POST /agents/registerover HTTPS - Registry assigns a server-scoped Spine ID and returns it
When the agent needs an access token (e.g. before a credential lease):
- SDK constructs a JWT:
{ sub: spine_id, aud: "registry", scope, iat, exp } - JWT signed with Ed25519 private key
- JWT submitted to
POST /auth/token - Registry verifies signature using stored public key
- Registry checks scope subset membership against
allowed_scopes - Short-lived access token returned
Credential brokering: /credentials/lease
Flow after a valid access token is obtained:
POST /credentials/lease { secret_name: "openai-api-key" }with Bearer token- Registry validates Bearer token — checks expiry, scope (
credential:lease), and agent status (not revoked) - Registry retrieves raw secret from encrypted vault
- Returns
{ value: "sk-...", expires_at: "..." } - SDK returns raw value to calling code — value is not persisted by the SDK
Revocation — precise semantics
When an agent is revoked:
- Immediate: Status field on the agent record is set to
revoked - Immediate: Future token requests rejected (step 4 above fails)
- Immediate: Future lease requests rejected
- NOT immediate: Lease copies already in the agent's memory are not invalidated — providers don't support short-lived scoped keys
- Lag: Full access loss = remaining TTL on the current lease
Shadow agent detection
The primary defense is credential custody. If raw keys exist only in Spineforge, unregistered agents have no credential path. This requires the onboarding migration — removing keys from env files, shared vaults, and CI.
Secondary signal today: billing deltas across provider billing portals vs. Spineforge-attributed usage. Significant divergence may indicate out-of-band usage.
Phase 2 (not shipped): per-key reconciliation against provider Admin APIs. Confirmed for OpenAI and Anthropic. Groq has no confirmed Admin API equivalent — unresolved.
JWKS endpoint for agent-to-agent verification
The registry exposes a JWKS endpoint at GET /well-known/jwks.json. Receiving agents fetch and cache this. When a token arrives with aud: spine_worker_xyz, the receiving agent verifies the signature locally against the cached JWKS — no registry roundtrip needed.
Data path commitment
Spineforge is never in the data path. Agents call providers directly. The OTel span pipeline captures events after the fact, asynchronously. If Spineforge is unreachable, agents keep running. The FileSink absorbs events locally. APISink retries on recovery.
Next steps
- Credential Leasing — the lease flow from the SDK perspective
- Scopes — how scope enforcement works at the JWT level
- Security page — questionnaire-ready summary