Admin XRPC endpoints
This page documents all XRPC endpoints in the pub.chive.admin.* namespace, plus the related pub.chive.actor.getMyRoles endpoint. All admin endpoints require authentication and the admin role.
Every admin handler follows the same authorization pattern: the middleware resolves the user's DID from the service auth JWT, then the handler checks user.isAdmin. Non-admin requests receive a 403 AuthorizationError. If a required backend service is not configured, the handler returns a 503 ServiceUnavailableError.
System
pub.chive.admin.getOverview
Returns aggregate counts from all index tables.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"eprints": 1234,
"authors": 567,
"reviews": 89,
"endorsements": 42,
"collections": 15,
"tags": 203
}
pub.chive.admin.getSystemHealth
Returns health status for each database connection and overall system status.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"status": "healthy",
"databases": [
{ "name": "PostgreSQL", "healthy": true, "latencyMs": 3 },
{ "name": "Elasticsearch", "healthy": true, "latencyMs": 12 },
{ "name": "Neo4j", "healthy": true, "latencyMs": 8 },
{ "name": "Redis", "healthy": true, "latencyMs": 1 }
],
"uptime": 86400,
"timestamp": "2026-03-04T12:00:00.000Z"
}
The status field is one of: healthy (all databases healthy), degraded (some databases unhealthy), unhealthy (no databases healthy).
pub.chive.admin.getPrometheusMetrics
Returns all registered Prometheus metrics as JSON.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"metrics": [
{ "name": "chive_http_requests_total", "type": "counter", "values": [...] }
],
"timestamp": "2026-03-04T12:00:00.000Z"
}
The metrics array contains the raw output of prom-client's getMetricsAsJSON(). If prom-client is not configured, returns an empty array.
pub.chive.admin.getEndpointMetrics
Returns structured per-endpoint performance data parsed from Prometheus histograms and counters.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"metrics": [
{
"method": "GET",
"path": "/xrpc/pub.chive.eprint.getSubmission",
"requestCount": 15234,
"errorCount": 12,
"errorRate": 79,
"p50": 23400,
"p95": 89200,
"p99": 234000
}
]
}
| Field | Description |
|---|---|
errorRate | Error rate in basis points (100 = 1%) |
p50, p95, p99 | Latency percentiles in microseconds |
Metrics are sorted by requestCount descending. Percentiles are computed via linear interpolation within histogram buckets.
pub.chive.admin.getNodeMetrics
Returns Node.js runtime metrics and structured process information.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"metrics": [
{
"name": "nodejs_heap_size_total_bytes",
"value": "52428800",
"type": "gauge",
"unit": "bytes"
}
],
"processInfo": {
"pid": 12345,
"uptime": 3600,
"heapUsed": 41943040,
"heapTotal": 52428800,
"rss": 104857600,
"external": 2097152,
"cpuUser": 1500000,
"cpuSystem": 300000,
"eventLoopLag": 1200
}
}
The eventLoopLag is in microseconds. The metrics array includes all nodejs_*, process_*, and chive_* Prometheus metrics (excluding histogram sub-metrics).
Alpha applications
pub.chive.admin.listAlphaApplications
Lists alpha applications with optional status filter and cursor-based pagination.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status (e.g., pending, approved, rejected) |
limit | number | No | Maximum results to return (default: 50) |
cursor | string | No | Pagination cursor |
Response
{
"items": [
{
"id": "uuid",
"did": "did:plc:abc123",
"handle": "researcher.bsky.social",
"email": "researcher@example.com",
"status": "pending",
"sector": "academia",
"careerStage": "postdoc",
"affiliations": [],
"researchKeywords": [],
"motivation": "Interested in open science",
"createdAt": "2026-03-01T10:00:00Z",
"updatedAt": "2026-03-01T10:00:00Z"
}
],
"total": 42,
"cursor": "next-page-cursor"
}
Handles are resolved via DID document lookup for applications that have no stored handle.
pub.chive.admin.getAlphaApplication
Returns a single alpha application by DID.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
did | string | Yes | DID of the applicant |
Response
Returns the full AlphaApplication object. Throws NotFoundError if no application exists for the given DID.
pub.chive.admin.updateAlphaApplication
Updates an alpha application status. On approval, assigns the alpha-tester role in Redis and sends an email notification (best-effort).
| Property | Value |
|---|---|
| Type | Procedure (POST) |
| Auth | Required (admin) |
Input
| Name | Type | Required | Description |
|---|---|---|---|
did | string | Yes | DID of the applicant |
action | string | Yes | One of: approve, reject, revoke |
Response
Returns the updated AlphaApplication object. On approve, adds alpha-tester role. On reject or revoke, removes alpha-tester role.
Increments the chive_admin_actions_total counter with labels action={action} and target=alpha_application.
pub.chive.admin.getAlphaStats
Returns aggregate statistics for alpha applications.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
None.
Response
{
"byStatus": { "pending": 12, "approved": 28, "rejected": 2 },
"bySector": { "academia": 30, "industry": 10, "government": 2 },
"byCareerStage": { "postdoc": 15, "faculty": 10, "student": 12, "other": 5 },
"recentByDay": [
{ "date": "2026-03-04", "count": 3 },
{ "date": "2026-03-03", "count": 5 }
],
"total": 42
}
Users
pub.chive.admin.searchUsers
Searches users by handle or DID.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search term (handle or DID prefix) |
limit | number | No | Maximum results (default: 20) |
Response
{
"users": [
{
"did": "did:plc:abc123",
"handle": "researcher.bsky.social",
"displayName": "Dr. Smith",
"eprintCount": 5,
"reviewCount": 3,
"endorsementCount": 1,
"roles": ["alpha-tester"],
"createdAt": "2026-01-15T08:00:00Z"
}
]
}
pub.chive.admin.getUserDetail
Returns detailed information for a single user.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
did | string | Yes | DID of the user |
Response
Returns a UserDetail object with eprint count, review count, endorsement count, roles, and timestamps. Throws NotFoundError if the user is not in the index.
pub.chive.admin.assignRole
Assigns a role to a user. Stores the assignment in Redis with metadata (timestamp, assigning admin DID).
| Property | Value |
|---|---|
| Type | Procedure (POST) |
| Auth | Required (admin) |
Input
| Name | Type | Required | Description |
|---|---|---|---|
did | string | Yes | DID of the target user |
role | string | Yes | Role to assign |
Valid roles: admin, moderator, graph-editor, author, reader, alpha-tester.
Response
{
"success": true,
"did": "did:plc:abc123",
"role": "moderator"
}
Increments chive_admin_actions_total{action="assign_role", target="user"}.
pub.chive.admin.revokeRole
Revokes a role from a user. Removes both the role set member and the assignment metadata from Redis.
| Property | Value |
|---|---|
| Type | Procedure (POST) |
| Auth | Required (admin) |
Input
| Name | Type | Required | Description |
|---|---|---|---|
did | string | Yes | DID of the target user |
role | string | Yes | Role to revoke |
Response
{
"success": true,
"did": "did:plc:abc123",
"role": "moderator"
}
Increments chive_admin_actions_total{action="revoke_role", target="user"}.
Content
pub.chive.admin.listEprints
Queries indexed eprints with optional text search and pagination.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
q | string | No | Text search query |
limit | number | No | Maximum results (default: 50) |
offset | number | No | Offset for pagination (default: 0) |
Response
{
"items": [
{
"uri": "at://did:plc:abc123/pub.chive.eprint.submission/rkey",
"title": "An Eprint Title",
"authorDid": "did:plc:abc123",
"createdAt": "2026-03-01T10:00:00Z"
}
],
"total": 1234
}
pub.chive.admin.listReviews
Queries indexed reviews with pagination.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | number | No | Maximum results (default: 50) |
cursor | string | No | Numeric offset as cursor string |
Response
{
"items": [
{
"uri": "at://did:plc:abc123/pub.chive.review.comment/rkey",
"eprintUri": "at://did:plc:def456/pub.chive.eprint.submission/rkey",
"reviewerDid": "did:plc:abc123",
"motivation": "minor-revision"
}
],
"total": 89
}
pub.chive.admin.listEndorsements
Queries indexed endorsements with pagination.
| Property | Value |
|---|---|
| Type | Query (GET) |
| Auth | Required (admin) |