Bootstrap
Download Artifact
Stream encrypted artifact bundle.
Requires:
- mTLS client cert matching instance
- X-Download-Token header (from /secrets)
Download token allows 3 attempts, consumed on successful transfer.
Args: instance_id: Instance UUID request: FastAPI request (for mTLS cert extraction) db: Database session x_download_token: Download token from /secrets (64 hex chars)
Returns: StreamingResponse with encrypted bundle (application/octet-stream)
Errors: 401: Invalid mTLS cert or download token 404: Instance or artifact not found 429: Too many download attempts
Path Parameters
uuidHeader Parameters
Response Body
curl -X GET "https://loading/internal/bootstrap/artifacts/497f6eca-6276-4993-bfeb-53cbbbba6f08" \ -H "x-download-token: string"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Download Website Bundle
Download website bundle for an instance (unencrypted static assets).
Same auth as agent artifact: mTLS cert + download token. Returns the website tarball from R2 if one was provisioned. No-op 404 if no website was deployed with this instance.
"It's just a flesh wound." — The Black Knight, Monty Python (websites are optional — no wound if missing)
Path Parameters
uuidHeader Parameters
Response Body
curl -X GET "https://loading/internal/bootstrap/artifacts/497f6eca-6276-4993-bfeb-53cbbbba6f08/website" \ -H "x-download-token: string"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Receive Callback
Receive bootstrap callback from agent.
Validates callback JWT and enforces strict monotonic sequence. Sequence: installing(1) → configuring(2) → securing(3) → ready(4) Error can occur at seq 2 or 3 only.
Args: request: Stage + seq + optional message db: Database session authorization: Bearer {callback_jwt}
Returns: status: "ok" message: Confirmation message
Errors: 401: Invalid or expired JWT 400: Invalid stage/seq or sequence violation 404: Instance or callback state not found
Header Parameters
1 <= value <= 4^(installing|configuring|securing|ready|error)$Response Body
curl -X POST "https://loading/internal/bootstrap/callback" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{ "seq": 1, "stage": "string" }'{
"message": "string",
"status": "string"
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Issue Certificate
Issue mTLS certificate from bootstrap token and CSR.
Two-step bootstrap: This is step 1 (bootstrap token → mTLS cert). Step 2 is /secrets (mTLS → secrets + callback JWT).
NOTE: Bootstrap token is NOT consumed here (consumed in /secrets after mTLS).
Args: request: Bootstrap token + CSR PEM db: Database session
Returns: cert_pem: PEM-encoded mTLS certificate session_id: Bootstrap session UUID for /secrets call
Errors: 401: Invalid, expired, or consumed token 400: Invalid CSR 500: CA error
^[0-9a-f]{64}$64 <= length <= 64100 <= length <= 10000Response Body
curl -X POST "https://loading/internal/bootstrap/cert" \ -H "Content-Type: application/json" \ -d '{ "bootstrap_token": "stringstringstringstringstringstringstringstringstringstringstri", "csr_pem": "stringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstri" }'{
"cert_pem": "string",
"session_id": "string"
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Receive Diagnostic
Free-form trace breadcrumbs from bootstrap-agent.sh.
Same JWT auth as /callback (the callback_jwt issued at /secrets
is reused). No monotonic-sequence enforcement — every accepted
request appends a row to provision_logs with the given label as
stage and the message body as message. Designed for shipping
"where am I" traces during fault diagnosis without disturbing
the production callback state machine.
Why a separate endpoint:
The strict /callback handler rejects out-of-sequence stage+
seq combos with 400, which the shell helper's || true
silently swallows — so trace breadcrumbs aimed at /callback
never reached provision_logs. This endpoint accepts anything
JWT-valid + label + message.
Header Parameters
1 <= length <= 80"info"^(info|warn|error)$length <= 2000Response Body
curl -X POST "https://loading/internal/bootstrap/diagnostic" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{ "label": "string", "message": "string" }'{
"message": "string",
"status": "string"
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Receive Early Diagnostic
Pre-mTLS bootstrap trace logging.
The strict /callback endpoint and the JWT-protected /diagnostic endpoint both require artefacts that bootstrap-agent.sh only has AFTER Phase 1 (cert exchange) + Phase 2 (secrets fetch + JWT). When bootstrap hangs in Phase 0/1/2 we get nothing back.
This endpoint authenticates against the instance's bootstrap_token (a one-shot per-instance secret already known to the script from cloud-init Jinja templating). Token is hashed and compared in constant time against the stored bootstrap_tokens row; we do NOT consume it (consumption stays bound to /secrets).
Writes the message to provision_logs. Same effect as /diagnostic but available before mTLS is up.
10 <= length <= 2001 <= length <= 801 <= length <= 80"info"^(info|warn|error)$length <= 2000Response Body
curl -X POST "https://loading/internal/bootstrap/early-diagnostic" \ -H "Content-Type: application/json" \ -d '{ "bootstrap_token": "stringstri", "instance_id": "string", "label": "string", "message": "string" }'{
"message": "string",
"status": "string"
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}Get Secrets
Provide decryption secrets after mTLS verification.
Two-step bootstrap: This is step 2 (mTLS → secrets + callback JWT). Requires client cert from step 1 (/cert).
Bootstrap token is consumed HERE (after mTLS verification succeeds). Callback JWT is created here. Download token is created here (one-time use, cannot retry /secrets).
Args: request_body: Session ID from /cert request: FastAPI request (for mTLS cert extraction) db: Database session
Returns: callback_jwt: JWT for /callback endpoint artifact_download_token: Token for /artifacts (raw hex) decryption_key_hex: Bundle decryption key (64 hex chars) artifact_cipher_hash: Expected ciphertext hash (sha256:...) bundle_plain_hash: Expected plaintext hash (sha256:...) agent_config: Agent configuration (non-secret) agent_secrets: Agent secrets (API keys, etc.)
Errors: 401: Invalid mTLS cert or session 404: Session not found 410: Session expired or already complete
Response Body
curl -X POST "https://loading/internal/bootstrap/secrets" \ -H "Content-Type: application/json" \ -d '{ "session_id": "string" }'{
"agent_config": {},
"agent_secrets": {},
"artifact_cipher_hash": "string",
"artifact_download_token": "string",
"bundle_plain_hash": "string",
"callback_jwt": "string",
"decryption_key_hex": "string",
"skill_lockfile": {}
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string"
}
]
}