Check a join code before installing (join listener only).
curl --request POST \ --url https://stratum.example.com/v1/join/code-checks \ --header 'Content-Type: application/json' \ --data '{ "pake": { "session": "pk-4f7k2q9mabcdefgh", "ke3": "example" }, "release": "0.5.0", "selfUpgrade": true }'. Stage 1 of the installer calls it
on a machine about to be installed as a joiner, with a throwaway TLS
client certificate, on the connection it proved the code on (POST /v1/join/pake). It runs the checks a registration runs on the code and
the release, and records nothing: no registration, no key.
Refused as a registration is: a code not proven (401
JOIN_CODE_INVALID: mistyped, or not this cluster’s), an expired or
revoked code (401, with the reason); a proof for no waiting exchange of
this key on this connection (409 JOIN_PAKE_RESTART: start again); a
release other than the cluster’s (409
RELEASE_MISMATCH, naming the cluster’s release and its ISO path, and why
an older machine that can upgrade itself may not:); too
many calls from one address (429); an upgrade in progress (503).
Request Bodyrequired
Section titled “Request Bodyrequired”A join code to check before an install, proven by the
PAKE exchange the joiner started with POST /v1/join/pake. Nothing is
recorded.
object
The joiner’s proof of its join code: the OPAQUE KE3 for the exchange the listener answered. Sent on the same TLS connection as that exchange, with the same client certificate; a session is used once.
object
The exchange, from the POST /v1/join/pake answer.
Example
pk-4f7k2q9mabcdefghThe OPAQUE KE3 message (RFC 9807), base64.
The release the machine would be installed from.
Example
0.5.0The machine can upgrade itself to the cluster’s release. Absent or false: only the cluster’s own release passes.
Responses
Section titled “Responses”The code is live and the release is the cluster’s, or (with
selfUpgrade) older, within the cluster’s upgrade rules and one the
founder can serve: upgrade then says to which release.
A join code that passed the checks.
object
The release the cluster runs.
When the code expires.
The upgrade a joiner on an older release makes before it can register: from the release it was installed with to
the release the cluster runs. Only a joiner that sent selfUpgrade: true
is ever offered one; any other joiner on another release is refused with
RELEASE_MISMATCH.
object
The release the joiner reported.
The release the cluster runs, which the joiner upgrades to.
Where the joiner fetches the release from (the release mirror’s URL of the release directory). Every file is checked against the release’s signed manifest. Empty when the founder names none.
The founder gives the release itself, when no release mirror can (a lab,
an air gap): fetch it from GET /v1/join/registrations/{joinId}/release/{path}
on the join listener, the release layout a mirror publishes
(payload/manifest.json, os/blobs/..., sysext/...). source is then
empty. Served only to this registration while it is needs-upgrade,
read only, a few files at once (503 RELEASE_BUSY: retry); ranges are
accepted so a download resumes. The joiner verifies the manifest’s
signature against the release keys of its own OS and every file against
the manifest, as it does from a mirror.
Example
{ "clusterRelease": "0.5.0", "upgrade": { "from": "0.5.0", "to": "0.6.0", "source": "https://mirror.example/releases/stratum/0.6.0/bundle" }}Bad request.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Missing or invalid token.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Headers
Section titled “Headers”Conflicting state.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Request rate limit exceeded. The API-boundary throttle caps request throughput per principal and per project; code is RATE_LIMITED (distinct from the quota engine’s QUOTA_EXCEEDED). The Retry-After header carries the seconds to wait. Applies to any authenticated endpoint — it is enforced by middleware, not per-path.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Headers
Section titled “Headers”Seconds to wait before retrying.
Upstream temporarily unavailable (driver / scheduler / dependency).
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}