HTTP service for publishing and querying DCP agent revocations. Supports both V1 (agent-level) and V2 (kid-level, emergency revocation, short-lived cert tracking). Exposes a .well-known endpoint for standardized queries.
# Start the service
node index.js
# Or with Docker
docker compose up revocationThe service listens on http://localhost:3003 by default.
Service health check.
curl http://localhost:3003/health{
"ok": true,
"service": "dcp-revocation",
"supported_versions": ["1.0", "2.0"],
"total_revocations": 3,
"total_kid_revocations": 1
}Publish an agent-level revocation (V1).
curl -X POST http://localhost:3003/revoke \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent-001",
"human_id": "human-001",
"reason": "Compromised credentials",
"signature": "base64-signature..."
}'Request body:
| Field | Type | Required | Description |
|---|---|---|---|
agent_id |
string |
Yes | ID of the agent to revoke |
human_id |
string |
No | ID of the responsible human |
reason |
string |
Yes | Reason for revocation |
signature |
string |
Yes | Revocation signature |
dcp_version |
string |
No | DCP version (default: "1.0") |
timestamp |
string |
No | ISO 8601 (default: now) |
Response (201):
{
"ok": true,
"agent_id": "agent-001",
"revoked_at": "2026-03-01T00:00:00.000Z"
}Check if an agent is revoked.
curl http://localhost:3003/check/agent-001Revoked agent:
{
"revoked": true,
"record": {
"dcp_version": "1.0",
"agent_id": "agent-001",
"human_id": "human-001",
"timestamp": "2026-03-01T00:00:00.000Z",
"reason": "Compromised credentials",
"signature": "base64-signature..."
}
}Non-revoked agent:
{
"revoked": false,
"agent_id": "agent-001"
}List all agent-level revocations.
curl http://localhost:3003/list{
"revocations": [...],
"total": 3
}Kid-level revocation with composite signature.
curl -X POST http://localhost:3003/v2/revoke \
-H "Content-Type: application/json" \
-d '{
"dcp_version": "2.0",
"agent_id": "agent-001",
"human_id": "human-001",
"revoked_kid": "a1b2c3d4e5f6...",
"reason": "Key compromised",
"composite_sig": {
"classical": { "alg": "ed25519", "kid": "abc123", "sig_b64": "..." },
"pq": { "alg": "ml-dsa-65", "kid": "def456", "sig_b64": "..." },
"binding": "pq_over_classical"
}
}'Request body:
| Field | Type | Required | Description |
|---|---|---|---|
dcp_version |
string |
Yes | Must be "2.0" |
agent_id |
string |
Yes | ID of the agent |
human_id |
string |
No | ID of the responsible human |
revoked_kid |
string |
Yes | Key identifier to revoke |
reason |
string |
Yes | Reason for revocation |
composite_sig |
object |
Yes | Composite signature (classical + optional PQ) |
Response (201):
{
"ok": true,
"agent_id": "agent-001",
"revoked_kid": "a1b2c3d4e5f6...",
"revoked_at": "2026-03-01T00:00:00.000Z"
}Emergency revocation (panic button). Revokes ALL keys for an agent using a pre-registered revocation secret. Rate-limited to 5 attempts per minute per IP.
curl -X POST http://localhost:3003/v2/emergency-revoke \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent-001",
"revocation_secret": "a1b2c3d4e5f6..."
}'Request body:
| Field | Type | Required | Description |
|---|---|---|---|
agent_id |
string |
Yes | ID of the agent to revoke |
human_id |
string |
No | ID of the responsible human |
revocation_secret |
string |
Yes | Pre-image of the registered token (64 hex chars) |
reason |
string |
No | Reason (default: "key_compromise_emergency") |
timestamp |
string |
No | ISO 8601 (default: now) |
Response (200):
{
"ok": true,
"agent_id": "agent-001",
"revoked_at": "2026-03-01T00:00:00.000Z",
"keys_revoked": 3
}Error responses: 400 (bad format), 403 (invalid secret), 404 (no token registered), 409 (token already consumed), 429 (rate limit).
Register an emergency revocation token for an agent. Called during identity setup.
curl -X POST http://localhost:3003/v2/register-emergency-token \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent-001",
"emergency_revocation_token": "sha256:abc123..."
}'Response (201):
{ "ok": true, "agent_id": "agent-001" }Register key expiry for short-lived cert tracking.
curl -X POST http://localhost:3003/v2/register-key-expiry \
-H "Content-Type: application/json" \
-d '{
"kid": "a1b2c3d4...",
"expires_at": "2026-04-01T00:00:00Z"
}'Response (201):
{ "ok": true, "kid": "a1b2c3d4...", "expires_at": "2026-04-01T00:00:00Z" }Check if a specific key identifier is revoked (explicit revocation, emergency revocation, or expiry).
curl http://localhost:3003/v2/check/kid/a1b2c3d4e5f6Revoked key:
{
"revoked": true,
"kid": "a1b2c3d4e5f6",
"agent_id": "agent-001",
"reason": "Key compromised",
"revoked_at": "2026-03-01T00:00:00.000Z"
}Active key:
{ "revoked": false, "kid": "a1b2c3d4e5f6" }List all revocations including agent-level and kid-level.
curl http://localhost:3003/v2/list{
"dcp_version": "2.0",
"agent_revocations": [...],
"kid_revocations": [...],
"total_agents": 2,
"total_kids": 5
}Standardized endpoint for querying all revocations (V1 + V2). Follows RFC 8615.
curl http://localhost:3003/.well-known/dcp-revocations.json{
"dcp_version": "2.0",
"updated_at": "2026-03-01T00:00:00.000Z",
"revocations": [
{
"dcp_version": "2.0",
"agent_id": "agent-001",
"human_id": "human-001",
"timestamp": "2026-03-01T00:00:00.000Z",
"reason": "Compromised credentials",
"signature": "composite:a1b2c3d4"
}
],
"kid_revocations": [
{
"dcp_version": "2.0",
"agent_id": "agent-001",
"revoked_kid": "a1b2c3d4e5f6...",
"timestamp": "2026-03-01T00:00:00.000Z",
"reason": "Key compromised"
}
]
}This endpoint can be:
- Queried by any verifier
- Cached by CDNs
- Served as a static file in production
| Variable | Default | Description |
|---|---|---|
PORT |
3003 |
HTTP port |
The Express and FastAPI middlewares can use checkRevocation: true to automatically verify against this service before accepting a bundle.
- Register emergency token during agent setup (
POST /v2/register-emergency-token) - Register key expiry for short-lived certs (
POST /v2/register-key-expiry) - Revoke individual keys as needed (
POST /v2/revoke) - Use panic button in emergencies (
POST /v2/emergency-revoke) - Check key status before accepting bundles (
GET /v2/check/kid/:kid)
PORT=3003 node index.js
# Test V1
curl http://localhost:3003/health
curl -X POST http://localhost:3003/revoke \
-H "Content-Type: application/json" \
-d '{"agent_id":"test-001","reason":"test","signature":"sig"}'
curl http://localhost:3003/check/test-001
# Test V2
curl -X POST http://localhost:3003/v2/register-emergency-token \
-H "Content-Type: application/json" \
-d '{"agent_id":"test-002","emergency_revocation_token":"sha256:abc123"}'
curl http://localhost:3003/v2/list
curl http://localhost:3003/.well-known/dcp-revocations.jsonApache-2.0