Engine Worker API

The engine Worker (averase) is the edge gateway every booted AVERASE device talks to — verify, check-in, asset reports, wipe results. This reference documents its routes, authentication, and error model.

A stateless edge gateway

The Worker owns no database — no D1, no R2, no KV. It does exactly two things per request:

  1. Verifies the device token at the edge (Ed25519 signature check against the fleet public key), rejecting anything unsigned before it costs an origin round-trip.
  2. Forwards the request to the AVERASE cloud over an HMAC-signed internal channel: POST {internal base}{path} with X-Averase-Timestamp and X-Averase-Signature: sha256=<hex>, the signature being HMAC-SHA256 over {timestamp}.{body}.

The cloud (Rails) is the single authority for entitlement, quota, and persistence. The Worker's signature check proves a request came from a genuinely issued ISO — it says nothing about whether that ISO is still entitled. Rails re-decides allow/deny on every call, which is what makes remote revocation immediate.

Authentication

Every route except GET /api/health's liveness semantics requires:

Authorization: Bearer <compact JWS>

The token is an EdDSA (Ed25519) compact JWS, minted by the cloud when the ISO was downloaded and spliced into the image. One fleet-wide keypair covers all devices: the cloud holds the private seed and mints; the Worker verifies with the public half (DEVICE_TOKEN_PUBKEY, a base64-encoded raw 32-byte Ed25519 public key).

Token claims

ClaimMeaning
subThe account identifier (acct_…) the token was minted for
jtiThe licence token's UUID — the row the cloud checks for status and quota
iatIssued-at timestamp
expExpiry timestamp

Any verification failure — missing header, malformed JWS, bad signature, or the Worker's public key being unset — returns 401 {"error":"unauthorized"}. The Worker fails closed: no key configured means no request passes.

Errors

StatusBodyWhen
401{"error":"unauthorized"}Bearer token missing, malformed, or signature invalid (or verification key unset)
400{"allow":false,"reason":"invalid_token"}Token verified but carries no jti
503{"allow":false,"reason":"validation_unavailable"}The cloud is unreachable — fail closed: the device treats this as a denial
4xx{"allow":false,"reason":…}The cloud denied — its status code is passed through (403 when it supplied none)
400{"error":"invalid payload"}Request body failed validation
4xx/5xx{"error":"rails rejected …","status":n}The cloud rejected a write (asset report, wipe result, …)
404{"error":"not found"}Unknown route

The healthy boot-and-wipe trace

A device working correctly produces this sequence against the Worker:

GET  /api/health        connectivity probe
POST /api/verify        unlock the UI (unmetered)
POST /api/record        once-per-boot asset report
POST /api/checkin       pre-wipe entitlement + quota (metered)
POST /api/wipe_result   one per wiped drive

GET/api/health

Health check

Connectivity probe. The engine calls it (with its bearer token) as the first step of the unlock sequence — up to 3 attempts, 4 seconds apart — before attempting verification. No forward to the cloud; the Worker answers directly.

Request

GET
/api/health
curl https://<your-worker>.workers.dev/api/health \
  -H "Authorization: Bearer <device token>"

Response

{
  "ok": true
}

POST/api/verify

Verify a device

Boot-time licence verification — the call that unlocks the kiosk UI. Forwards to the cloud's token-verify endpoint, which applies the full entitlement decision (status, quota, account state) but does not meter quota: booting isn't wiping, so repeated boots and re-verifications are free and idempotent.

Only an affirmative allow: true unlocks the device, and only for that boot. A denial carries a reason the engine maps to an operator message (revoked, suspended, disabled, quota_exceeded, account_inactive, not_found, …) — see Booting & verification.

Request

POST
/api/verify
curl -X POST https://<your-worker>.workers.dev/api/verify \
  -H "Authorization: Bearer <device token>"

Response

{
  "allow": true,
  "account": "acct_1a2b3c",
  "quota_remaining": 42
}

Denied

{
  "allow": false,
  "reason": "revoked"
}

POST/api/checkin

Check in before a wipe

The pre-wipe entitlement gate. Forwards to the cloud's token-validate endpoint, which makes the allow/deny decision, atomically increments the token's use count against its quota, and issues the job_id for the run. This is the metered call — the counterpart to the unmetered verify.

The engine checks in once per run and suffixes the returned job_id per drive (-0, -1, …) on its wipe results; the hotswap station checks in once per drive, each with its own unsuffixed job_id, so quota meters per drive there.

A denial, a missing job_id, or any transport failure blocks the wipe entirely — see the check-in gate.

Request

POST
/api/checkin
curl -X POST https://<your-worker>.workers.dev/api/checkin \
  -H "Authorization: Bearer <device token>"

Response

{
  "allow": true,
  "job_id": "job_abc123",
  "quota_remaining": 41
}

Denied

{
  "allow": false,
  "reason": "quota_exceeded"
}

POST/api/record

Submit an asset report

The once-per-boot hardware report: the complete serialized fingerprint plus internal storage, exactly as collected — nothing is summarized on-device. The cloud upserts one asset per physical machine per account (keyed by DMI UUID + serial), and the machine appears in Inventory.

The engine sends this only once it is verified, connected, and hardware collection has settled; on failure it retries (3 attempts) and re-arms so a later connection re-sends.

Request fields

  • Name
    record_id
    Type
    string
    Description

    Boot record id, generated at startup: CW-YYYYMMDD-HHMMSS (UTC). Tests and notes key on it.

  • Name
    engine_version
    Type
    string
    Description

    The engine's version string.

  • Name
    fingerprint
    Type
    object
    Description

    The full hardware fingerprint document; its storage array contains internal drives only.

Request

POST
/api/record
{
  "record_id": "CW-20260623-221305",
  "engine_version": "1.0.0",
  "fingerprint": {
    "...": "...",
    "storage": [ { "...": "internal drives only" } ]
  }
}

Response

{
  "ok": true,
  "asset_id": "asset_9f8e7d"
}

POST/api/tests

Submit test results

A full snapshot of the hardware-test board, sent on every settled change (not a delta). Keys on the boot's record_id, so it is only sent after the asset report has been acknowledged. Each test is one of the nine wire ids from Hardware audit & tests with a status of not_started, passed, or failed, plus an optional detail string.

Request

POST
/api/tests
{
  "record_id": "CW-20260623-221305",
  "tests": {
    "keyboard": { "status": "passed" },
    "battery": { "status": "passed", "detail": "84%" },
    "webcam": { "status": "failed" }
  }
}

Response

{
  "ok": true
}

POST/api/notes

Attach operator notes

Free-text operator notes from the kiosk's notes panel, attached to the boot's asset. Autosaved from the device (debounced) and fire-and-forget.

Request

POST
/api/notes
{
  "record_id": "CW-20260623-221305",
  "notes": "Cracked bezel, otherwise clean. Lot 84."
}

Response

{
  "ok": true
}

POST/api/wipe_result

Submit a wipe result

One result per wiped drive, sent after all of a run's jobs reach a terminal state. The Worker forwards it to the cloud awaited — persistence happens before the acknowledgment — and the cloud keys it idempotently on job_id, then enqueues certificate generation for certifiable results.

The full payload and every field's derivation are documented in Verification & results. The certificate_status in the acknowledgment is logged by the engine but never displayed — certificates live in the web app.

Request

POST
/api/wipe_result
{
  "job_id": "job_abc123-0",
  "drive_serial": "S6MZNF1WA04527",
  "drive_model": "PM9B1 NVMe Samsung 512GB",
  "drive_capacity_gb": 512,
  "wipe_method": "NIST 800-88 R2 Purge",
  "passes_completed": null,
  "started_at": "2026-06-21T11:30:05Z",
  "completed_at": "2026-06-21T11:47:12Z",
  "verification_hash": "9f2c…",
  "wipe_status": "completed",
  "technique": "NVMe Sanitize — crypto erase",
  "validation": "approved",
  "disposition": "sanitized",
  "markings_removed": true,
  "tool_components": "averase-engine 1.0.0; nvme version 2.4",
  "verification_result": "Pass — 32/32 fingerprint sectors overwritten (prior data non-recoverable)"
}

Response

{
  "ok": true,
  "wipe_result_id": "wr_5c6d7e",
  "certificate_status": "queued"
}

POST/api/chassis_map

Save a chassis map

Used by the hotswap station: the mapping wizard saves the chassis's physical bay layout to the cloud, which persists the map and creates a one-time asset for the chassis itself, keyed by its DMI UUID + serial. Every subsequent boot fetches the map back instead of re-running the wizard.

See Chassis mapping for the wizard flow and what the map contains.

Request

POST
/api/chassis_map
curl -X POST https://<your-worker>.workers.dev/api/chassis_map \
  -H "Authorization: Bearer <device token>" \
  -H "Content-Type: application/json" \
  -d '{ ...chassis map document... }'

Response

{
  "ok": true,
  "chassis_map_id": "cmap_2b3c4d",
  "asset_id": "asset_9f8e7d"
}

POST/api/chassis_map/lookup

Look up a chassis map

The boot-time counterpart: the hotswap station identifies its chassis (DMI UUID + serial) and asks whether a saved map exists. found: false with a null map means the station runs the mapping wizard.

Request

POST
/api/chassis_map/lookup
curl -X POST https://<your-worker>.workers.dev/api/chassis_map/lookup \
  -H "Authorization: Bearer <device token>" \
  -H "Content-Type: application/json" \
  -d '{ ...chassis identity... }'

Response (found)

{
  "found": true,
  "map": { "...": "..." }
}

Response (not found)

{
  "found": false,
  "map": null
}

POST/api/diag

Send diagnostics

Device-side diagnostics for live debugging. The Worker writes the payload to its console output only (visible in a live log tail) — nothing is forwarded to the cloud or stored. Payloads are capped at 16 KiB.

Response

{
  "ok": true
}

Retired certificate endpoints

POST /api/certificate, POST /api/sign, and POST /api/timestamp are gone and return 410: certificates are issued exclusively by the AVERASE cloud, triggered by /api/wipe_result — the Worker no longer renders or signs anything, and no signing key exists at the edge. See Certificates for how certificates are generated and verified today.

Was this page helpful?