Admin authentication
Every management route depends onrequire_admin, which reads the token from an
X-Admin-Token header or from an Authorization: Bearer <token> credential and
compares it in constant time (app_admin.py:121-130, auth.py:28-29). The
expected value comes from the ADMIN_TOKEN environment variable, or from the
file at ADMIN_TOKEN_FILE (auth.py:10-18). A mismatch returns 401
(app_admin.py:127-130).
Admin HTML pages
Both depend on
require_admin (app_admin.py:176, app_admin.py:186).
Challenge management routes
All routes below depend onrequire_admin.
POST /v1/admin/challenges
Creates a challenge. Returns 201 Created (app_admin.py:202-234).
Request — ChallengeCreate (schemas/challenge.py:22-41). Required fields:
slug (pattern ^[a-z0-9][a-z0-9-]*[a-z0-9]$, schemas/challenge.py:25),
name, image, version. Optional fields include emission_percent (default
0), status (default draft), description, api_version (default "1.0"),
internal_base_url, required_capabilities (default
["get_weights", "proxy_routes"]), resources, volumes, env, secrets,
and metadata (schemas/challenge.py:29-41).
Response — ChallengeCreateResponse (schemas/challenge.py:131-136):
A duplicate slug returns
409 (app_admin.py:214-218); an image that fails the
production policy returns 400 (app_admin.py:219-220).
GET /v1/admin/challenges/{slug}
Returns a ChallengeAdminView (schemas/challenge.py:106-128); unknown slug
returns 404 (app_admin.py:236-245).
PATCH /v1/admin/challenges/{slug}
Updates mutable metadata and returns a ChallengeAdminView
(app_admin.py:247-264). Request — ChallengeUpdate; all fields optional
(schemas/challenge.py:51-67).
Status transitions
Both return a
ChallengeAdminView (schemas/challenge.py:106-128).
Runtime control
All three return a
RuntimeOperationResponse (schemas/challenge.py:168-174):
Internal service endpoints
The following routes are internal — they run on separate service apps and are authenticated with per-challenge tokens, not the admin token. They are documented here for operators; they are not part of the public API.Docker broker (internal)
The Docker broker runs as its own app (docker_broker.py:653-659). Each request
is authenticated with Authorization: Bearer <broker token> plus an
X-Platform-Challenge-Slug header (_authenticate, docker_broker.py:717-730).
POST /v1/docker/run returns 429 when a workload quota is exceeded
(docker_broker.py:685-688) and 400 on an executor error
(docker_broker.py:689-690). BrokerRunResponse carries container_name,
stdout, stderr, returncode, and timed_out (schemas/docker_broker.py:51-56);
BrokerCleanupResponse carries status (schemas/docker_broker.py:82-83);
BrokerListResponse carries containers (schemas/docker_broker.py:74-75).
Challenge weights collection (internal)
The master collects per-challenge weights by calling each challenge’sGET /internal/v1/get_weights, authenticated with the challenge’s bearer token
and an X-Platform-Challenge-Slug header (challenge_client.py:31-36). The
challenge replies with a ChallengeWeightsResponse
(challenge_client.py:43; see Weights schema).
Related
Security model
How the admin token gates these management routes.
Broker
The internal Docker broker documented on this page.
API overview
The full endpoint map and authentication models.