Skip to content

This control plane's own build identity (admin).

GET
/v1/admin/platform/identity
curl --request GET \
--url http://localhost:8080/v1/admin/platform/identity \
--header 'Authorization: Bearer <token>'

What THIS control plane is: the stamped semver, the source commit and build time it was built from, and schema_version, the highest migration version its binary embeds. schema_version is the ORDERING KEY for the whole release surface because it is the only one with a consequence: boot runs migrations forward and crash-loops against a database ahead of the binary (ADR 0002). A read of the running binary - it touches no row and does not vary with the channel.

OK.

Media typeapplication/json
object
identity
required

What one component IS. Served for the control plane by GET /v1/admin/platform/identity and carried inside the release view.

object
version
required

Stamped semver without a leading “v”. “dev” when the binary was built unstamped (a developer build, or a source deploy that skipped the linker flags). NEVER NULL - a build always has some answer, and “dev” is the honest one.

string
source_commit
required

Full 40-character lowercase hex; null on an unstamped build.

string | null
built_at
required

RFC3339 UTC; null on an unstamped build.

string | null format: date-time
schema_version
required

The highest migration version the binary embeds (the 0NNN file number as an integer). ALWAYS KNOWN, because it is derived from the embedded migration set rather than a build flag - which is why it, and not semver or built_at, is the ordering key everywhere in this surface (ADR 0002).

integer
install_mode

Owned when this machine’s recovery actor answered; otherwise null. The enum is the host’s; this amendment defines only when owned is reported. A transient failure to reach the actor also reads null, so a developer apply to the control-plane target is refused 409 target_not_owned until it answers; the updater_socket preflight surfaces that condition.

string | null
Allowed values: registry source owned
recovery_actor_version

Semver of this machine’s recovery actor; null when absent or unparseable.

string | null
recovery_actor_source_commit

7-40 lowercase hex, the commit that recovery actor was built from.

string | null
seed_version

Opaque version of the seed the recovery actor last saw on this machine.

string | null
database_mode

Owned = Quasar created this database and takes its pre-update dump; external = the operator’s own database, only used, so a migrating update needs external_backup_confirmed. What tells a client when to show that confirmation and backup_space. A client meeting an unrecognized value shows it as unknown.

string | null
Allowed values: owned external
machine_role

Non-null exactly when a recovery actor created this control plane, whether or not the actor is answering (install_mode alone reads null then); null on a Compose or source control plane, and from an older server. A client meeting an unknown value shows the shape as unknown and treats no host as this machine’s.

string | null
Allowed values: combined control_only
machine_node_name

Non-null exactly when machine_role is. On combined, the node name the machine’s own agent registers under. A client identifies the control plane’s own host only when machine_role is combined and the host’s node_name equals this; never on control_only, where a GPU host could share the name.

string | null
Example
{
"identity": {
"install_mode": "registry",
"database_mode": "owned",
"machine_role": "combined"
}
}

Missing/invalid/expired/revoked token.

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, host_not_ready, restart_required, stale_revision, unsupported_source, approval_superseded, approval_expired, attempt_conflict, cancel_too_late, retry_exhausted, home_conflict, placement_ineligible, inherited_placement, recovery_uncertain, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Also omitted when the holder is the caller’s parked session or released runtime (amendment 39). Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
reason

Amendment 40 (#602), ADDITIVE: a machine-readable cause under code. On 503 no_host_available, home_host_unavailable: the launch is pinned to the host that holds the caller’s home for this app (Amendment 53: or it is pinned to the host of the caller’s Steam home for a sharing launch) and that host is offline or no longer enrolled. Only an admin clears it, so a client does not spend its automatic retry on it. Names no host. Amendment 53 (#1001), on 409 home_in_use: steam_library_open_in_desktop (the holder mounts the Steam library as a shared home) or steam_game_running (the refused launch shares the library and a Steam session holds it); absent when the holder is already stopping. Open string: a client treats an unknown value as absent.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
],
"reason": "example"
}
}

Authenticated but insufficient role / not the owner (precedes resource lookup).

Media typeapplication/json
object
error
required
object
code
required

E.g. validation_failed, unauthorized, forbidden, not_found, conflict, session_quota_exceeded, home_in_use, home_not_provisioned, parent_app_disabled, profile_ineligible, profile_not_launchable_for_app, no_host_available, capacity_exhausted, host_not_ready, restart_required, stale_revision, unsupported_source, approval_superseded, approval_expired, attempt_conflict, cancel_too_late, retry_exhausted, home_conflict, placement_ineligible, inherited_placement, recovery_uncertain, rate_limited, internal. Open string, not an enum: new codes are additive and an unknown one falls through to a client’s generic per-status branch.

string
message
required
string
live_sessions

Present on restart_required.

integer
session_id

Steam library discovery Phase 3, ADDITIVE: present on home_in_use when the guard could name the CONFLICTING live session - the one already holding the home. It is here so the client can offer “go to your running session” with a link instead of a dead-end toast. OMITTED rather than empty when the conflict is known but the session is not, so a client branches on presence and never renders a link to nowhere. Also omitted when the holder is the caller’s parked session or released runtime (amendment 39). Load-bearing once derived tiles exist: the lock is held by the PARENT’s home, so a user who clicks a game tile can be refused because a DIFFERENT app (the Steam launcher, or another game from the same install) is running, and without the session id the refusal reads as a bug. See control-api.md §Derived tiles.

string format: uuid
derived_tiles

Steam library discovery Phase 3, ADDITIVE: present on the 409 conflict from DELETE /v1/apps/{id} when the app has derived tiles and ?delete_derived=true was not sent. A LIST, not a count - the point of the confirmation is that the admin sees what they are about to destroy. Capped; an empty array means the tiles could not be listed, never that there are none.

Array<object>
object
id
required
string format: uuid
name
required
string
reason

Amendment 40 (#602), ADDITIVE: a machine-readable cause under code. On 503 no_host_available, home_host_unavailable: the launch is pinned to the host that holds the caller’s home for this app (Amendment 53: or it is pinned to the host of the caller’s Steam home for a sharing launch) and that host is offline or no longer enrolled. Only an admin clears it, so a client does not spend its automatic retry on it. Names no host. Amendment 53 (#1001), on 409 home_in_use: steam_library_open_in_desktop (the holder mounts the Steam library as a shared home) or steam_game_running (the refused launch shares the library and a Steam session holds it); absent when the holder is already stopping. Open string: a client treats an unknown value as absent.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"live_sessions": 1,
"session_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"derived_tiles": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example"
}
],
"reason": "example"
}
}