Revocation
DRS supports two revocation mechanisms that work together:
- Remote Bitstring Status List — W3C standard; fetched from
STATUS_LIST_BASE_URLwith a configurable TTL cache (default 5 minutes). Revocations take effect within the cache window. - Local revocation store — in-memory; updated immediately via
POST /admin/revoke. Takes effect on the next request. Does not survive process restart.
Both are checked in Block F of verify_chain. A DR is revoked if its drs_status_list_index is marked in either source.
Revoking a delegation (immediate effect)
The local revocation store takes effect on the next verification request — no cache window:
curl -X POST http://localhost:8080/admin/revoke \
-H "Authorization: Bearer $DRS_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status_list_index": 42}'
# Response: {"revoked":true,"status_list_index":42}
DRS_ADMIN_TOKEN must be set as an environment variable. If not set, the endpoint responds 503:
{"error": "admin endpoint not configured — set DRS_ADMIN_TOKEN"}
Note: The local revocation store is in-memory. Revocations are lost on process restart. For durable revocation that survives restarts, update the W3C Bitstring Status List served at
STATUS_LIST_BASE_URL.
Revoking via the remote Bitstring Status List
To revoke durably (surviving restarts and across multiple drs-verify instances), update the W3C Bitstring Status List at the URL configured in STATUS_LIST_BASE_URL. drs-verify fetches and caches this list; the TTL is STATUS_CACHE_TTL_SECS (default 300 seconds / 5 minutes).
Reducing the cache window
For deployments where faster remote revocation propagation is needed:
STATUS_CACHE_TTL_SECS=30 ./drs-verify
Setting this too low increases load on the status list endpoint. 300 seconds is appropriate for most deployments. For emergency revocations, use POST /admin/revoke for immediate effect alongside updating the remote list.
How Block F works
for each DR in bundle:
if DR.drs_status_list_index is set:
if remote_status_list.is_revoked(DR.drs_status_list_index):
return RECEIPT_REVOKED
if local_revocation_store.is_revoked(DR.drs_status_list_index):
return RECEIPT_REVOKED
Status list cache concurrency
The status list cache uses sync.Once internally to prevent double-fetch race conditions under concurrent load. When the cache expires and multiple goroutines arrive simultaneously, only one HTTP request is made — all others wait and reuse the result.