mehendocs

ReferenceHTTP surfaces

HTTP surfaces#

What does a client see on the wire?

On this page

mehen is the supported client; nothing here is needed to use Mehen. This page is for reading what goes over the wire.

Machine requests#

Machines talk to the vault under https://app.mehen.dev/v1/. Every request from an enrolled machine carries a Mehen-Proof header, a signature over the method, the full URL and a hash of the exact body (Keys, proofs and signing). There is no bearer token.

RouteWhat it is
POST /v1/enrol, GET /v1/enrol/:enrolment, POST /v1/enrol/:enrolment/renewStart an enrolment, poll it, renew its lease in place. Signed by the key being enrolled.
GET /v1/meThis machine's identity, owner, scope and state.
GET /v1/items, GET /v1/items/:slugItems this machine may use, and one item's public description.
POST /v1/relayOne HTTP request through the vault relay.
POST /v1/intakes, GET /v1/intakes/:id, POST /v1/intakes/:id/cancelAsk for a credential, poll the intake, cancel your own.
POST /v1/connect, GET /v1/connect/:id, POST /v1/connect/:id/cancelAsk for an OAuth connection, poll it, cancel your own.
GET /v1/approvals/:idPoll an approval; ?wait=1 long-polls up to 25 seconds.
GET /v1/pendingThis machine's own open asks, and the one notice a machine gets, that it was added to the workspace.
POST /v1/projects, GET /v1/projects/:id, /v1/projects/:id/vars/:nameCreate a project, read it, set a variable.
POST /v1/runs, POST /v1/runs/:id/renew, DELETE /v1/runs/:id, POST /v1/leaseStart, renew and end a run; fetch a lease mid-run.
POST /v1/freezeFreeze the workspace.
POST /v1/devices/self/revokeRevoke this machine.
GET /v1/seal-keyUnauthenticated: the vault's public seal key, which browsers seal secret fields to.

Headers#

HeaderDirectionMeaning
Mehen-ProofrequestThe machine's signature over this exact request.
Mehen-Error: 1responseThe vault refused; the body is an error object (Errors and exit codes).
Mehen-Upstream: 1responseA relayed upstream response, never a vault refusal.
Mehen-ItemresponseThe item that acted, <slug> (<account>), so the transcript says which account was used.
Mehen-CliresponseOn every /v1 answer: minimum=<v>, with ; recommended=<v> when the vault sets one. A mehen below the minimum is refused with cli_outdated (HTTP 426), except freeze and self-revoke.
User-Agentrequestmehen/<version>.

An upstream 403 and a vault refusal are never the same thing: only the vault's carries Mehen-Error.

Errors#

type ApiError = {
  error: ErrorCode
  message: string
  next?: { url?: string; command?: string; say: string }
  approval?: string
  bindingCode?: string
  choices?: { slug: string; account: string | null }[]
  retryAfter?: number
  expiresAt?: string
  deciders?: string[]
  transition?: ...
}

Every code, its HTTP status and the exit code mehen gives it are in Errors and exit codes, and as JSON at /reference/errors.json.

The release channel#

Releases are served from https://mehen.dev/dl/:

PathWhat it is
/dl/latest.jsonThe signed manifest of the current release.
/dl/v<version>/manifest.jsonOne release's signed manifest: { version, commit, builtAt, files, signatures }, each file with its name, platform, size and SHA-256, compressed and uncompressed.
/dl/v<version>/mehen-<os>-<arch>.gzThe binary, for darwin or linux on arm64 or x64.

https://mehen.dev/install is the installer for a machine with no mehen. Its last line is the receipt, mehen-install: {"v":1,"result":"installed","version":...,"path":...,"onPath":...,"env":...,"rc":{...}}, where result is installed, already-installed or forced. Keys, proofs and signing says how a release is checked.