# profiles (/docs/reference/api/profiles)

> The profiles group stores and checks the versioned recipes that provisioning workflows run: steps, drivers, an image, user data and host config. A version becomes immutable the first time a workflow uses it. Lookups see the tenant's own profiles, public ones, and the read-only profiles that modules ship under the tenant `builtin`. See [Profiles and images](/docs/guides/bare-metal/profiles-and-images).



The profiles group stores and checks the versioned recipes that provisioning workflows run: steps, drivers, an image, user data and host config. A version becomes immutable the first time a workflow uses it. Lookups see the tenant's own profiles, public ones, and the read-only profiles that modules ship under the tenant `builtin`. See [Profiles and images](/docs/guides/bare-metal/profiles-and-images).

All 7 methods are served by this release.

| Method                  | Kind     | Authorization                                      | Phase | Status     |
| ----------------------- | -------- | -------------------------------------------------- | ----- | ---------- |
| [`create`](#create)     | mutation | `compute:profiles:manage` @ `compute-tenant`       | v0.2  | registered |
| [`get`](#get)           | read     | `compute:profiles:read` @ `compute-profile`        | v0.2  | registered |
| [`validate`](#validate) | read     | `compute:profiles:read` @ `compute-profile`        | v0.2  | registered |
| [`render`](#render)     | read     | `compute:profiles:read` @ `compute-profile`        | v0.2  | registered |
| [`list`](#list)         | read     | `compute:profiles:read` @ `compute-tenant` + items | v0.2  | registered |
| [`update`](#update)     | mutation | `compute:profiles:manage` @ `compute-profile`      | v0.2  | registered |
| [`delete`](#delete)     | mutation | `compute:profiles:manage` @ `compute-profile`      | v0.2  | registered |

## create [#create]

`POST /api/compute/profiles/create`

Stores a new profile version from a profile document, `private` unless `visibility` says `public`.

* Decided as `compute:profiles:manage` on the tenant.

* The document is checked like `defineProfile`; any problem is `INVALID_INPUT`, with `details.path` naming the first offending field.

* `CONFLICT` when that id and version already exist; create the next version instead.

* **Kind:** mutation

* **Authorization:** `compute:profiles:manage` @ `compute-tenant`

* **Module:** `provision`

* **Phase:** v0.2 (registered)

**Input**

| Field        | Type                       | Required | Constraints                                                |
| ------------ | -------------------------- | -------- | ---------------------------------------------------------- |
| `tenantId`   | string                     | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$` |
| `document`   | object                     | yes      |                                                            |
| `visibility` | one of `private`, `public` |          | default `"private"`                                        |

## get [#get]

`POST /api/compute/profiles/get`

Returns one profile version, the latest when `profileVersion` is omitted.

The lookup prefers the tenant's own profile, then a public stored one, then one a module ships. `NOT_FOUND` when none matches.

* **Kind:** read
* **Authorization:** `compute:profiles:read` @ `compute-profile`
* **Module:** `provision`
* **Phase:** v0.2 (registered)

**Input**

| Field            | Type    | Required | Constraints                                                                 |
| ---------------- | ------- | -------- | --------------------------------------------------------------------------- |
| `tenantId`       | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`                  |
| `profileId`      | string  | yes      | at most 128 characters; matches `^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$` |
| `profileVersion` | integer |          | 1-1000000                                                                   |

## validate [#validate]

`POST /api/compute/profiles/validate`

Expands a profile version against the registered steps and returns `valid` with every issue found, such as a `use` that does not resolve or a `with` its step rejects.

Problems in the profile are returned as `issues` rather than thrown; an unknown profile is `NOT_FOUND`.

* **Kind:** read
* **Authorization:** `compute:profiles:read` @ `compute-profile`
* **Module:** `provision`
* **Phase:** v0.2 (registered)

**Input**

| Field            | Type    | Required | Constraints                                                                 |
| ---------------- | ------- | -------- | --------------------------------------------------------------------------- |
| `tenantId`       | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`                  |
| `profileId`      | string  | yes      | at most 128 characters; matches `^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$` |
| `profileVersion` | integer |          | 1-1000000                                                                   |

## render [#render]

`POST /api/compute/profiles/render`

Returns the profile document and the expanded steps a workflow of this version would run, with their phases.

`INVALID_INPUT` when the profile does not resolve, with the problems in `details.issues`; `NOT_FOUND` for an unknown profile.

* **Kind:** read
* **Authorization:** `compute:profiles:read` @ `compute-profile`
* **Module:** `provision`
* **Phase:** v0.2 (registered)

**Input**

| Field            | Type    | Required | Constraints                                                                 |
| ---------------- | ------- | -------- | --------------------------------------------------------------------------- |
| `tenantId`       | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`                  |
| `profileId`      | string  | yes      | at most 128 characters; matches `^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$` |
| `profileVersion` | integer |          | 1-1000000                                                                   |

## list [#list]

`POST /api/compute/profiles/list`

Returns a page of the tenant's stored profiles, public ones and those modules ship, ordered by id and version.

`limit` defaults to 50 and is at most 200; pass the returned `cursor` to read the next page.

* **Kind:** read
* **Authorization:** `compute:profiles:read` @ `compute-tenant` + items
* **Module:** `provision`
* **Phase:** v0.2 (registered)

**Input**

| Field      | Type    | Required | Constraints                                                |
| ---------- | ------- | -------- | ---------------------------------------------------------- |
| `tenantId` | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$` |
| `limit`    | integer |          | 1-200; default `50`                                        |
| `cursor`   | string  |          | at most 256 characters                                     |

## update [#update]

`POST /api/compute/profiles/update`

Replaces the document of one of the tenant's profile versions, or changes its visibility, and returns the profile.

* Pass `document`, `visibility` or both; neither is `INVALID_INPUT`.

* A version a workflow has used keeps its document: `INVALID_STATE`. Its visibility can still change.

* A new document must keep the profile's id and version (`INVALID_INPUT`).

* `expectedVersion` is the profile's row `version`; a mismatch is `CONFLICT`.

* `NOT_FOUND` when the tenant has no such version.

* **Kind:** mutation

* **Authorization:** `compute:profiles:manage` @ `compute-profile`

* **Module:** `provision`

* **Phase:** v0.2 (registered)

**Input**

| Field             | Type                       | Required | Constraints                                                                 |
| ----------------- | -------------------------- | -------- | --------------------------------------------------------------------------- |
| `tenantId`        | string                     | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`                  |
| `profileId`       | string                     | yes      | at most 128 characters; matches `^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$` |
| `profileVersion`  | integer                    | yes      | 1-1000000                                                                   |
| `document`        | any                        |          |                                                                             |
| `visibility`      | one of `private`, `public` |          |                                                                             |
| `expectedVersion` | integer                    |          | at least 1                                                                  |

## delete [#delete]

`POST /api/compute/profiles/delete`

Hides one version, or every version when `profileVersion` is omitted, from new workflows and returns the number deleted.

Workflows already started keep the profile document they snapshotted. Profiles that modules ship are not stored, so deleting one is `NOT_FOUND`, as is a profile the tenant does not have.

* **Kind:** mutation
* **Authorization:** `compute:profiles:manage` @ `compute-profile`
* **Module:** `provision`
* **Phase:** v0.2 (registered)

**Input**

| Field            | Type    | Required | Constraints                                                                 |
| ---------------- | ------- | -------- | --------------------------------------------------------------------------- |
| `tenantId`       | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`                  |
| `profileId`      | string  | yes      | at most 128 characters; matches `^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$` |
| `profileVersion` | integer |          | 1-1000000                                                                   |
