Revocation & Key API¶
Robot identity revocation and public key management endpoints. Defined by GAP-02 (Robot Identity Revocation, §13) and GAP-09 (Key Lifecycle, §8.6) of the RCAN protocol.
| Spec | MessageType | Cache TTL |
|---|---|---|
| RCAN protocol §13 + §8.6 | 19 — ROBOT_REVOCATION broadcast | 1h (active), 5m (revoked) |
Protocol Safety Invariants
- ESTOP from a revoked robot is always accepted by peers — revocation never blocks safety halt.
- RESUME from a revoked robot is always rejected — the robot cannot clear its own emergency stop.
- Revocation check occurs after replay check but before command execution.
- Offline robots may continue operation for up to
max_revocation_staleness_s(default 3600s) before quarantine.
GET /api/v1/robots/{rrn}/revocation-status¶
Auth: None (public)
Get revocation status.
Returns the current revocation status of a robot. Robots MUST check this endpoint on startup and cache the result for up to 1 hour (configurable via max-age). If the registry is unreachable, robots may continue operation for up to max_revocation_staleness_s (default 3600s) before entering quarantine mode.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
rrn |
path | required | Robot Registration Number (e.g. RRN-000000000001) |
Example:
{
"rrn": "RRN-000000000001",
"status": "active",
"revoked_at": null,
"reason": null,
"authority": "RRF Registry",
"checked_at": "2026-03-16T20:00:00Z",
"cache_max_age_s": 3600
}
Status values / Notes:
// Revoked robot:
{
"rrn": "RRN-000000000099",
"status": "revoked",
"revoked_at": "2026-03-15T08:30:00Z",
"reason": "Stolen — private key compromised",
"authority": "RRF Registry (owner request)",
"checked_at": "2026-03-16T20:00:00Z",
"cache_max_age_s": 300
}
// Possible status values: "active" | "revoked" | "suspended"
// suspended = temporarily restricted; ESTOP still accepted, commands blocked
// revoked = permanent; all commands blocked; ESTOP still accepted
// active = normal operation
POST /api/v1/robots/{rrn}/revoke¶
Auth: Bearer JWT — role: creator or registry admin
Revoke a robot (registry admin only).
Marks a robot as revoked or suspended. Requires registry admin or verified owner JWT (role: creator). On success, the registry broadcasts a ROBOT_REVOCATION (MessageType 19) message to all connected peers so they can invalidate cached consent and public key material. ESTOP commands from revoked robots are still accepted by peers; RESUME commands are rejected.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
rrn |
path | required | Robot Registration Number to revoke |
status |
string | required | "revoked" or "suspended" |
reason |
string | required | Human-readable reason for revocation (max 500 chars) |
authority |
string | optional | Issuing authority identifier (defaults to authenticated JWT sub) |
Example:
// Request body:
{
"status": "revoked",
"reason": "Stolen — private key believed compromised after device loss on 2026-03-15",
"authority": "craigm26 (owner)"
}
// Response:
{
"rrn": "RRN-000000000001",
"status": "revoked",
"revoked_at": "2026-03-16T20:05:00Z",
"reason": "Stolen — private key believed compromised after device loss on 2026-03-15",
"authority": "craigm26 (owner)",
"broadcast_sent": true,
"broadcast_message_type": 19
}
GET /api/v1/robots/{rrn}/keys¶
Auth: None (public)
List public keys for a robot (JWKS).
Returns the JSON Web Key Set (JWKS, RFC 7517) for all signing keys associated with this robot — current and historical. Used for delegation chain verification (GAP-01), offline operation key caching (GAP-06), and audit trail signature verification (GAP-21). Keys include validity windows; expired keys are retained for replay_window_s × 2 to allow in-flight validation.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
rrn |
path | required | Robot Registration Number |
active_only |
boolean | optional | If true, returns only non-expired, non-revoked keys (default: false) |
Example:
{
"rrn": "RRN-000000000001",
"keys": [
{
"key_id": "kid-2026-03-001",
"kty": "OKP",
"crv": "ML-DSA-65",
"use": "sig",
"alg": "EdDSA",
"x": "base64url-encoded-public-key",
"valid_from": "2026-03-01T00:00:00Z",
"valid_until": "2027-03-01T00:00:00Z",
"revoked_at": null,
"is_current": true
},
{
"key_id": "kid-2026-01-001",
"kty": "OKP",
"crv": "ML-DSA-65",
"use": "sig",
"alg": "EdDSA",
"x": "base64url-encoded-old-key",
"valid_from": "2026-01-01T00:00:00Z",
"valid_until": "2026-03-01T00:00:00Z",
"revoked_at": null,
"is_current": false
}
],
"current_key_id": "kid-2026-03-001",
"jwks_uri": "https://api.robotregistryfoundation.org/api/v1/robots/RRN-000000000001/keys"
}
MessageType 19 — ROBOT_REVOCATION Broadcast¶
When a robot is revoked via POST /api/v1/robots/{rrn}/revoke, the registry broadcasts a ROBOT_REVOCATION message (MessageType 19, RCAN protocol §13.4) to all registered peers. Receiving robots MUST:
- Invalidate all cached consent grants from the revoked RRN
- Invalidate the revoked robot's cached public key material
- Reject all future commands originating from the revoked RRN (except ESTOP)
- Log a
ROBOT_REVOKEDaudit event with the revocation timestamp
ROBOT_REVOCATION Wire Format:
{
"msg_type": 19,
"msg_id": "uuid-v4",
"timestamp": "2026-03-16T20:05:00Z",
"sender_type": "service",
"service_id": "rrf-registry",
"payload": {
"revoked_rrn": "RRN-000000000001",
"status": "revoked",
"revoked_at": "2026-03-16T20:05:00Z",
"reason": "Stolen — private key believed compromised",
"authority": "craigm26 (owner)"
}
}
Related API Endpoints¶
| Path | Description |
|---|---|
/api/v1/robots/{rrn} |
Full robot record (includes revocation_status, key_id) |
/api/v1/robots/{rrn}/keys |
JWKS for delegation chain verification (this page) |
/api/v1/public-keys |
Registry-wide signing keys for offline caching (GAP-06) |