Skip to content

Server Administration

Administration is the one place in Cryptid where identity is the point. An operator is a known party acting on infrastructure they own, so there is nothing to anonymize and no reason to.

Admin sessions authenticate a person to their own server; PrivacyPass authenticates nobody to anybody.

AdminSession Structure
struct AdminSession {
token: String,
expires_at: u64,
permissions: Vec<AdminPermission>,
admin_level: AdminLevel, // Viewer | Moderator | Admin
}
enum AdminPermission {
ViewMetrics,
ViewAudit,
ManageConfig,
VerifyDevices,
ModifyBudgets,
BlockFederation,
}

Obtains a nonce for an administrator to sign.

  • Input: AdminChallengeRequest { device_id }
  • Output: AdminChallenge { challenge, expires_at }
  • Auth: None
  • Idempotent: No
  • Errors: MALFORMED_REQUEST
  • Servers MUST generate challenge with cryptographically secure randomness
  • Servers MUST expire a challenge within 5 minutes
  • Servers MUST NOT reveal whether device_id is an administrator
  • Servers MUST rate limit challenge issuance per source address

The third rule is especially important: a challenge endpoint that answers differently for administrators and everyone else enumerates the admin list.

GET /admin/v1/auth/challenge?device_id={device_id}

Exchanges a signed challenge for a session.

  • Input: AdminAuthRequest { device_id, challenge, signature, timestamp }
  • Output: AdminSession
  • Auth: Device signature over the challenge
  • Idempotent: No
  • Errors: ADMIN_UNAUTHORIZED, CHALLENGE_EXPIRED, CHALLENGE_INVALID, DEVICE_ID_MISMATCH
  • Servers MUST verify device_id == Blake3(public_key) before anything else
  • Servers MUST verify signature against the issued challenge
  • Servers MUST reject a challenge already spent
  • Servers MUST reject a timestamp outside an acceptable window
  • Servers MUST return ADMIN_UNAUTHORIZED for a valid signature from a non-administrator
  • Sessions MUST expire; one hour is the default
  • Servers MUST grant only the permissions configured for that administrator
POST /admin/v1/auth
Content-Type: application/json
  • Input: None - the current session authorizes
  • Output: AdminSession
  • Auth: Admin session
  • Idempotent: No
  • Errors: ADMIN_UNAUTHORIZED
  • Servers MUST reject a refresh presented after expiry; re-authentication is required
  • Servers MUST NOT extend permissions on refresh
  • Servers SHOULD bound total session lifetime independently of refresh count
POST /admin/v1/auth/refresh
Authorization: AdminSession <token>
  • Input: None
  • Output: None
  • Auth: Admin session
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED
  • Servers MUST invalidate the session immediately
  • Servers MUST succeed for an already-revoked session
POST /admin/v1/auth/logout
Authorization: AdminSession <token>
  • Input: None
  • Output: ServerConfig
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS
{
"server": {
"server_name": "chat.example.com",
"cryptid_version": "0.12",
"max_message_size": 262144,
"max_blob_size": 104857600,
"max_retention_days": 30
},
"announcement": {
"enabled": true,
"vdf_iterations": 5000000,
"max_challenges_per_ip_per_hour": 10,
"max_announcements_per_ip_per_hour": 5,
"accept_invites": true
},
"progressive_trust": {
"enabled": true,
"new_tier_duration_hours": 6,
"established_tier_duration_hours": 24,
"new_tier_rate": 50,
"new_tier_capacity": 200,
"established_tier_rate": 500,
"established_tier_capacity": 2000,
"trusted_tier_rate": 2000,
"trusted_tier_capacity": 10000
},
"issuance": {
"key_rotation_days": 30,
"key_overlap_days": 7
},
"federation": {
"enabled": true,
"allowlist_mode": false,
"auto_block_threshold": 0.2,
"publish_blocklist": true,
"certificate_validation": true
}
}
  • Servers MUST NOT return private key material of any kind
  • Values published at /.well-known/cryptid MUST match those returned here
GET /admin/v1/config
Authorization: AdminSession <token>
  • Input: ConfigPatch - a partial ServerConfig
  • Output: ServerConfig
  • Auth: Admin session + ManageConfig
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS, CONFIG_INVALID
  • Servers MUST validate every key and reject the whole patch if any is invalid
  • Servers MUST apply a patch atomically
  • Servers MUST return the resulting full config, so a caller can confirm what applied
  • Servers MUST record the change and the acting administrator in the audit log
  • A change to max_message_size or max_blob_size MUST be reflected at /.well-known/cryptid before taking effect
PATCH /admin/v1/config
Authorization: AdminSession <token>
  • Input: MetricsQuery { period }
  • Output: ServerMetrics
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS
{
"period": "24h",
"timestamp": 1789357668,
"server": {
"uptime_seconds": 2592000,
"cpu_usage_percent": 35.2,
"memory_usage_mb": 2048,
"storage_used_gb": 125.5
},
"devices": {
"announced_total": 1500,
"announced_last_24h": 25,
"verified": 120,
"blocked": 15,
"by_trust_tier": { "new": 45, "established": 320, "trusted": 1115, "verified": 120 }
},
"envelopes": {
"accepted_last_24h": 45000,
"queued": 120,
"expired_last_24h": 5,
"average_size_bytes": 8192
},
"tokens": {
"issued_last_24h": 98000,
"redeemed_last_24h": 94500
},
"federation": {
"peers_active": 25,
"peers_blocked": 3
}
}
  • Every figure MUST be a server-wide aggregate
  • Servers MUST NOT expose any metric attributable to an individual device beyond its DeviceRecord
  • Servers MUST NOT correlate issuance counts with redemption counts per device
GET /admin/v1/metrics?period={period}
Authorization: AdminSession <token>
  • Input: TimeseriesQuery { metric, period, interval }
  • Output: Timeseries { metric, points }
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS, CONFIG_INVALID
  • Servers MUST reject an unknown metric as CONFIG_INVALID
  • Servers MUST bound the number of points returned
  • Only aggregate metrics MUST be available as a series
GET /admin/v1/metrics/timeseries?metric={m}&period={p}&interval={i}
Authorization: AdminSession <token>
  • Input: ExportQuery { format }
  • Output: encoded metrics
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS, UNSUPPORTED_CONTENT_TYPE
  • Servers MUST expose the same aggregates as GetServerMetrics, in a different encoding
  • Servers MUST reject an unsupported format rather than silently substituting one
GET /admin/v1/metrics/export?format=prometheus
Authorization: AdminSession <token>

Export formats are a property of this binding, not of the operation. The HTTP binding supports prometheus and json.

  • Input: AuditQuery { since, action, limit }
  • Output: Vec<AuditEntry>
  • Auth: Admin session + ViewAudit
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS
AuditEntry Structure
struct AuditEntry {
entry_id: Uuid,
timestamp: u64,
// The administrator who acted. Admin actions are attributable by design
actor: DeviceId,
action: AuditAction,
// What was acted on: a device_id, a peer domain, a config key
subject: String,
reason: Option<String>,
}
  • Servers MUST log every administrative action that changes state
  • Entries MUST be append-only and MUST NOT be editable through the API
  • Servers MUST NOT log user traffic, mailbox addresses, or envelope contents
  • Servers MUST retain entries for at least the configured retention period
GET /admin/v1/audit?since={ts}&action={a}&limit={n}
Authorization: AdminSession <token>
  • Input: AuditExportQuery { since, format }
  • Output: encoded audit entries
  • Auth: Admin session + ViewAudit
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS, UNSUPPORTED_CONTENT_TYPE
  • Export MUST contain the same entries QueryAuditLog would return for the same range
  • Servers MUST record the export itself as an audit entry
GET /admin/v1/audit/export?since={ts}&format=csv
Authorization: AdminSession <token>

The HTTP binding supports csv and json.

Component-level health, for the operator.

  • Input: None
  • Output: AdminHealth { status, components, checked_at }
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS
  • Servers MUST report per-component status: storage, queue, federation, issuance
  • Servers MUST return degraded rather than healthy when any component is failing
  • this operation MUST NOT be used as the public liveness check
GET /admin/v1/health
Authorization: AdminSession <token>
  • Input: AlertQuery { severity, acknowledged }
  • Output: Vec<Alert>
  • Auth: Admin session + ViewMetrics
  • Idempotent: Yes
  • Errors: ADMIN_UNAUTHORIZED, ADMIN_INSUFFICIENT_PERMISSIONS
  • Alerts MUST derive from server-wide conditions: storage pressure, queue depth, federation failures, issuance-key expiry
  • Servers MUST NOT raise an alert naming a device or a mailbox
  • Servers SHOULD alert before an issuance key’s overlap window closes
GET /admin/v1/alerts?severity={s}&acknowledged={bool}
Authorization: AdminSession <token>