Skip to main content

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.

PropertyValue
TypeQuery (GET)
AuthRequired (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.

PropertyValue
TypeQuery (GET)
AuthRequired (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.

PropertyValue
TypeQuery (GET)
AuthRequired (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.

PropertyValue
TypeQuery (GET)
AuthRequired (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
}
]
}
FieldDescription
errorRateError rate in basis points (100 = 1%)
p50, p95, p99Latency 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.

PropertyValue
TypeQuery (GET)
AuthRequired (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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
statusstringNoFilter by status (e.g., pending, approved, rejected)
limitnumberNoMaximum results to return (default: 50)
cursorstringNoPagination 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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
didstringYesDID 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).

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
didstringYesDID of the applicant
actionstringYesOne 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.

PropertyValue
TypeQuery (GET)
AuthRequired (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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
querystringYesSearch term (handle or DID prefix)
limitnumberNoMaximum 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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
didstringYesDID 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).

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
didstringYesDID of the target user
rolestringYesRole 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.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
didstringYesDID of the target user
rolestringYesRole 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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
qstringNoText search query
limitnumberNoMaximum results (default: 50)
offsetnumberNoOffset 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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 50)
cursorstringNoNumeric 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.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 50)
cursorstringNoNumeric offset as cursor string

Response

{
"items": [
{
"uri": "at://did:plc:abc123/pub.chive.review.endorsement/rkey",
"eprintUri": "at://did:plc:def456/pub.chive.eprint.submission/rkey",
"endorserDid": "did:plc:abc123"
}
],
"total": 42
}

pub.chive.admin.deleteContent

Soft-deletes content by setting deleted_at in the database. Publishes a deletion event to Redis for audit trail.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
uristringYesAT URI of the content to delete
collectionstringYesLexicon collection name
reasonstringNoReason for deletion

Supported collections: pub.chive.eprint.submission, pub.chive.review.comment, pub.chive.review.endorsement, pub.chive.eprint.userTag.

Response

{
"success": true,
"uri": "at://did:plc:abc123/pub.chive.eprint.submission/rkey"
}

The deletion event is published to chive:admin:content-deleted Redis channel with the URI, collection, reason, deleting admin DID, and timestamp. Increments chive_admin_actions_total{action="delete", target="{collection}"}.


Firehose and DLQ

pub.chive.admin.getFirehoseStatus

Returns firehose cursor position and DLQ entry count.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

{
"cursor": "1709553600000000",
"dlqCount": 3,
"timestamp": "2026-03-04T12:00:00.000Z"
}

The cursor is the current firehose cursor stored in Redis (chive:firehose:cursor). A null cursor means the firehose consumer has not yet started or the cursor was lost.


pub.chive.admin.listDLQEntries

Returns entries from the firehose dead-letter queue.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum entries (default: 50)
offsetnumberNoOffset into the DLQ list (default: 0)

Response

{
"entries": [
{
"uri": "at://did:plc:abc123/pub.chive.eprint.submission/rkey",
"error": "ValidationError",
"errorType": "VALIDATION_ERROR",
"timestamp": "2026-03-04T11:30:00Z"
}
],
"total": 3
}

Updates the chive_dlq_entries_total gauge to the current DLQ length.


pub.chive.admin.retryDLQEntry

Requeues a single DLQ entry for reprocessing.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
indexnumberYesZero-based index of the entry in the DLQ list

Response

{
"success": true,
"message": "Entry requeued for retry"
}

The entry is pushed to chive:firehose:retry for reprocessing. If the index is out of range, returns success: false.


pub.chive.admin.retryAllDLQ

Batch retries all DLQ entries, optionally filtered by error type.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
errorTypestringNoFilter entries by error type before retrying

Response

{
"success": true,
"retriedCount": 3
}

If no errorType filter is provided, all entries are retried and the DLQ is cleared. If a filter is provided, only matching entries are moved to the retry queue; non-matching entries remain in the DLQ.


pub.chive.admin.dismissDLQEntry

Removes a single DLQ entry without retrying it.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
indexnumberYesZero-based index of the entry to dismiss

Response

{
"success": true,
"message": "Entry dismissed"
}

Uses a sentinel-and-remove pattern to atomically delete the entry at the given index. Decrements chive_dlq_entries_total.


pub.chive.admin.purgeOldDLQ

Purges DLQ entries older than a specified number of days.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
olderThanDaysnumberNoAge threshold in days (default: 7)

Response

{
"success": true,
"purgedCount": 5
}

Iterates through all DLQ entries, parses the timestamp or createdAt field, and removes entries older than the cutoff. Entries that fail to parse are skipped.


Backfill operations

pub.chive.admin.triggerPDSScan

Triggers a PDS scan against registered PDSes.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

None.

Response

{
"operationId": "uuid",
"status": "running"
}

The scan runs in the background. It fetches PDSes ready for scanning from the registry and invokes the PDS scanner against each (batch size 10, concurrency 2). Monitor progress with getBackfillStatus.


pub.chive.admin.triggerFreshnessScan

Triggers a freshness scan to detect and refresh stale records.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

None.

Response

{
"operationId": "uuid",
"status": "running"
}

Detects stale records via PDSSyncService.detectStaleRecords(), then refreshes each from its source PDS. Progress is updated as each record is processed.


pub.chive.admin.triggerCitationExtraction

Triggers citation extraction for all indexed eprints.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

None.

Response

{
"operationId": "uuid",
"status": "running"
}

Fetches all eprint URIs in batches of 500, then runs the CitationExtractionService against each eprint using GROBID, Crossref, and Semantic Scholar. Progress is updated every 10 eprints.


pub.chive.admin.triggerFullReindex

Triggers a full Elasticsearch reindex from PostgreSQL.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

None.

Response

{
"operationId": "uuid",
"status": "running"
}

Reads all eprints from PostgreSQL (via the admin service, in batches of 500), builds IndexableEprintDocument objects, and indexes each into Elasticsearch. Progress is updated every 50 eprints.


pub.chive.admin.triggerGovernanceSync

Triggers an immediate governance sync from the Chive Governance PDS.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

None.

Response

{
"operationId": "uuid",
"status": "running"
}

Creates a temporary GovernanceSyncJob instance and runs a single sync cycle, pulling authority records from the Governance PDS at GRAPH_PDS_URL (default: https://governance.chive.pub).


pub.chive.admin.triggerDIDSync

Triggers a sync for a specific DID by resolving it to a PDS and scanning all Chive collections.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
didstringYesDID to sync (e.g., did:plc:abc123)

Response

{
"operationId": "uuid",
"did": "did:plc:abc123",
"status": "running"
}

Resolves the DID to its PDS endpoint via PLC directory (for did:plc:) or .well-known/did.json (for did:web:), then scans all pub.chive.* collections for that user. Registers the PDS in the discovery registry as a side effect.


pub.chive.admin.triggerBackfill

Generic handler for triggering any supported backfill operation type.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
typestringYesOperation type
(additional)anyNoExtra metadata stored with the operation

Valid types: pdsScan, freshnessScan, citationExtraction, fullReindex, governanceSync, didSync.

Response

{
"operation": {
"id": "uuid",
"type": "pdsScan",
"status": "running",
"startedAt": "2026-03-04T12:00:00Z",
"progress": 0,
"recordsProcessed": 0
}
}

This is a lower-level endpoint compared to the specific trigger endpoints. It creates the operation record in Redis but does not start the actual work (the specific trigger endpoints do both).


pub.chive.admin.getBackfillStatus

Returns status of a specific operation or lists all operations.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
idstringNoSpecific operation ID to query
statusstringNoFilter by status: running, completed, failed, cancelled

Response

When id is provided:

{
"operation": {
"id": "uuid",
"type": "fullReindex",
"status": "running",
"startedAt": "2026-03-04T12:00:00Z",
"progress": 45,
"recordsProcessed": 230
}
}

When id is omitted:

{
"operations": [...]
}

pub.chive.admin.getBackfillHistory

Returns completed, failed, and cancelled backfill operations sorted by start time (newest first).

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

{
"operations": [
{
"id": "uuid",
"type": "fullReindex",
"status": "completed",
"startedAt": "2026-03-04T10:00:00Z",
"completedAt": "2026-03-04T10:15:00Z",
"progress": 100,
"recordsProcessed": 1234
}
]
}

Running operations are excluded from the history.


pub.chive.admin.cancelBackfill

Cancels a running backfill operation by signaling its AbortController.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
idstringYesOperation ID to cancel

Response

{
"success": true,
"id": "uuid"
}

Returns success: false if the operation is not found or not in running status.


PDS and imports

pub.chive.admin.listPDSes

Returns registered PDS entries with status, record counts, and user counts.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

{
"stats": {
"total": 15,
"healthy": 12,
"unhealthy": 3,
"withRecords": 8,
"items": [
{
"pdsUrl": "https://bsky.social",
"status": "active",
"recordCount": 42,
"userCount": 5,
"lastScanAt": "2026-03-04T10:00:00Z"
}
]
}
}

pub.chive.admin.rescanPDS

Triggers a rescan of a specific PDS by re-registering it in the PDS discovery registry.

PropertyValue
TypeProcedure (POST)
AuthRequired (admin)

Input

NameTypeRequiredDescription
pdsUrlstringYesURL of the PDS to rescan

Response

{
"success": true,
"pdsUrl": "https://bsky.social"
}

Increments chive_admin_actions_total{action="rescan", target="pds"}.


pub.chive.admin.listImports

Queries imported eprints with optional source filter.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 50)
sourcestringNoFilter by import source

Response

{
"items": [
{
"uri": "at://did:plc:abc123/pub.chive.eprint.submission/rkey",
"source": "firehose",
"importedAt": "2026-03-01T10:00:00Z"
}
],
"total": 1234
}

Knowledge graph

pub.chive.admin.getGraphStats

Returns knowledge graph statistics including node counts by type, edge count, and pending governance proposals.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

{
"totalNodes": 5000,
"totalEdges": 12000,
"fieldNodes": 3500,
"authorNodes": 1200,
"institutionNodes": 300,
"pendingProposals": 7
}

Queries the node and edge repositories in parallel. Falls back to zero on errors.


Analytics and metrics

pub.chive.admin.getMetricsOverview

Returns trending eprints for a given time window.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
daysnumberNoNumber of days for the trending window (default: 7)

The days value is mapped to the closest supported window: 1 day maps to 24h, 2-7 days to 7d, 8+ days to 30d.

Response

{
"trending": [{ "uri": "at://did:plc:abc123/...", "score": 42 }],
"periodInfo": {
"days": 7,
"startDate": "2026-02-25T12:00:00Z",
"endDate": "2026-03-04T12:00:00Z"
}
}

pub.chive.admin.getSearchAnalytics

Returns search analytics data including top queries and click-through metrics.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

Returns analytics data from AdminService.getSearchAnalytics(). The shape depends on the search analytics implementation.


pub.chive.admin.getActivityCorrelation

Returns cross-metric activity correlation data.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

None.

Response

{
"metrics": [...],
"timestamp": "2026-03-04T12:00:00.000Z"
}

Reads from the activity correlation service. Returns an empty metrics array if the service is not configured.


pub.chive.admin.getTrendingVelocity

Returns trending eprints enriched with velocity scores, view counts, and download counts.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 20)
windowstringNoTrending window: 24h, 7d, or 30d (default: 24h)

Response

{
"items": [
{
"uri": "at://did:plc:abc123/...",
"title": "An Eprint Title",
"velocity": 0.523,
"views": 142,
"downloads": 38,
"trend": "rising"
}
]
}

The trend field is determined by velocity: rising (> 0.1), falling (< -0.1), or stable (between -0.1 and 0.1).


pub.chive.admin.getViewDownloadTimeSeries

Returns view and download time series data, optionally filtered to a specific eprint.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
uristringNoAT URI of a specific eprint (omit for aggregate)
granularitystringNoTime bucket granularity (e.g., hour, day)

Response

Returns time series data from AdminService.getViewDownloadTimeSeries().


Governance and audit

pub.chive.admin.getAuditLog

Returns paginated audit log entries.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum entries (default: 50)
cursorstringNoNumeric offset as cursor string
actorDidstringNoFilter by acting admin DID

Response

{
"entries": [
{
"action": "assign_role",
"actorDid": "did:plc:admin123",
"targetDid": "did:plc:user456",
"details": { "role": "moderator" },
"timestamp": "2026-03-04T12:00:00Z"
}
],
"cursor": "50",
"total": 120
}

pub.chive.admin.listWarnings

Returns content warnings, optionally filtered by user DID.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 50)
didstringNoFilter warnings by target user DID

Response

{
"warnings": [...]
}

pub.chive.admin.listViolations

Returns content violations, optionally filtered by user DID.

PropertyValue
TypeQuery (GET)
AuthRequired (admin)

Parameters

NameTypeRequiredDescription
limitnumberNoMaximum results (default: 50)
didstringNoFilter violations by target user DID

Response

{
"violations": [...]
}

Actor endpoint

pub.chive.actor.getMyRoles

Returns the authenticated user's roles and boolean flags. This is not an admin endpoint; any authenticated user can call it.

PropertyValue
TypeQuery (GET)
AuthRequired (any authenticated user)

Parameters

None.

Response

{
"roles": ["admin", "alpha-tester"],
"isAdmin": true,
"isAlphaTester": true
}

Reads roles from Redis (chive:authz:roles:{did}). The isAlphaTester flag is true for admins regardless of explicit role assignment.

Next steps