@datocms/cma-client 5.4.16 → 5.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,6 +42,16 @@ export type RoleIdentity = string;
42
42
  * via the `definition` "type".
43
43
  */
44
44
  export type RoleType = 'role';
45
+ /**
46
+ * ID of environment. Can only contain lowercase letters, numbers and dashes
47
+ *
48
+ * This interface was referenced by `Environment`'s JSON-Schema
49
+ * via the `definition` "identity".
50
+ *
51
+ * This interface was referenced by `Environment`'s JSON-Schema
52
+ * via the `definition` "id".
53
+ */
54
+ export type EnvironmentIdentity = string;
45
55
  /**
46
56
  * RFC 4122 UUID of item type expressed in URL-safe base64 format
47
57
  *
@@ -62,16 +72,6 @@ export type ItemTypeIdentity = string;
62
72
  * via the `definition` "id".
63
73
  */
64
74
  export type WorkflowIdentity = string;
65
- /**
66
- * ID of environment. Can only contain lowercase letters, numbers and dashes
67
- *
68
- * This interface was referenced by `Environment`'s JSON-Schema
69
- * via the `definition` "identity".
70
- *
71
- * This interface was referenced by `Environment`'s JSON-Schema
72
- * via the `definition` "id".
73
- */
74
- export type EnvironmentIdentity = string;
75
75
  /**
76
76
  * RFC 4122 UUID of upload collection expressed in URL-safe base64 format
77
77
  *
@@ -224,9 +224,9 @@ export type AccessTokenInstancesTargetSchema = AccessToken[];
224
224
  */
225
225
  export type AccessTokenDestroyHrefSchema = {
226
226
  /**
227
- * New owner for resources previously owned by the deleted access token. This argument specifies the new owner type.
227
+ * New owner for resources previously owned by the deleted access token. This argument specifies the new owner type. Use `account` or `organization` to reassign to the project's owner — `client.site.find().owner` returns the right type/id pair to pass.
228
228
  */
229
- destination_user_type?: 'account' | 'user' | 'access_token' | 'sso_user';
229
+ destination_user_type?: 'account' | 'organization' | 'user' | 'access_token' | 'sso_user';
230
230
  /**
231
231
  * New owner for resources previously owned by the deleted access token. This argument specifies the new owner ID.
232
232
  */
@@ -1921,7 +1921,82 @@ export type SiteSelfHrefSchema = {
1921
1921
  */
1922
1922
  export type WorkflowInstancesTargetSchema = Workflow[];
1923
1923
  /**
1924
- * A Role represents a specific set of actions an editor (or an API token) can perform on your administrative area.
1924
+ * A Role groups the permissions that govern what a credential can do in a project. The same role definition is applied to **collaborators**, **SSO users**, and **API tokens** alike design roles around what the *credential* should be allowed to do, not who is holding it.
1925
+ *
1926
+ * > [!PROTIP] 📘 Same role, different identities
1927
+ * > Ask "what is the *credential* allowed to do?" — not "what is this *person* allowed to do?". For API tokens specifically, the role's permissions are further constrained by the token's API surface flags (`can_access_cda`, `can_access_cda_preview`, `can_access_cma`); see the [API token](/docs/content-management-api/resources/access-token) resource for details.
1928
+ *
1929
+ * ## How permissions are computed
1930
+ *
1931
+ * Most of the granular permissions on a role come as a `positive_<resource>_permissions` / `negative_<resource>_permissions` pair: build triggers, search indexes, records (`item_type`), uploads. They all follow the same rule:
1932
+ *
1933
+ * > Effective permissions = `(inherited ∪ positive_*) − negative_*`
1934
+ *
1935
+ * Positive entries (and entries pulled in via `relationships.inherits_permissions_from`) grant access. Negative entries always win when they overlap. The idiomatic recipe for "almost everything" is a single `action: "all"` positive entry plus targeted negative entries to subtract — instead of enumerating each allowed action.
1936
+ *
1937
+ * > [!WARNING] ⚠️ Send `positive_*` and `negative_*` together
1938
+ * > For each resource family (records, uploads, build triggers, search indexes), the matching `positive_*` and `negative_*` arrays must be **both present or both absent** in a create/update payload. On **update**, sent arrays *replace* the stored ones wholesale, so always read the role first and pass back the existing entries on the side you're not changing — sending `[]` to satisfy the constraint will erase everything that was there. (On create, `[]` is fine since there's nothing to lose.) The [Update endpoint](/docs/content-management-api/resources/role/update) documents an SDK helper that handles this diff for records and uploads.
1939
+ *
1940
+ * The computed result is exposed on every role response under `meta.final_permissions`; the raw declared values stay on `attributes.*`. See [Effective vs declared permissions](#effective-vs-declared-permissions) below.
1941
+ *
1942
+ * ## Project-level permissions
1943
+ *
1944
+ * These attributes gate access to project-wide capabilities. They apply uniformly across the whole project; granular control over individual records and uploads lives under [Per-environment content permissions](#per-environment-content-permissions).
1945
+ *
1946
+ * - **Project-wide flags.** Boolean attributes named `can_*` (`can_edit_schema`, `can_manage_environments`, `can_manage_access_tokens`, …) cover the schema, environments, users, webhooks, and so on — see the property table for the full list.
1947
+ * - **Environment access.** `environments_access` controls *which* environments the credential can enter at all (`all`, `primary_only`, `sandbox_only`, or `none`). Use `none` when the role is meant only to be inherited from.
1948
+ * - **Build triggers.** The role may **manually fire** the build triggers listed in `positive_build_trigger_permissions`, minus those listed in `negative_build_trigger_permissions`. Use `build_trigger: null` on an entry to cover every trigger at once. Creating, editing, or deleting trigger definitions is gated separately by `can_manage_build_triggers`.
1949
+ * - **Search indexes.** The role may **manually re-index** the search indexes listed in `positive_search_index_permissions`, minus those listed in `negative_search_index_permissions`. Use `search_index: null` on an entry to cover every index. Managing the index definitions themselves is gated separately by `can_manage_search_indexes`.
1950
+ *
1951
+ * ## Per-environment content permissions
1952
+ *
1953
+ * The role's access to **records** and **uploads** is governed by two positive/negative array pairs. Every entry is **scoped to a single environment** via the required `environment` field — to grant the same permission across multiple environments, repeat the entry once per environment id (or use `inherits_permissions_from` together with `environments_access`). The computation is the same `(inherited ∪ positive_*) − negative_*` rule from [How permissions are computed](#how-permissions-are-computed), evaluated per environment.
1954
+ *
1955
+ * ###### Records
1956
+ *
1957
+ * Permission entries live in `positive_item_type_permissions` (and the `negative_*` counterpart). Each entry is a discriminated union keyed by `action`:
1958
+ *
1959
+ * - `all` — every action below
1960
+ * - `read` — read records
1961
+ * - `create` — create new records
1962
+ * - `update` — edit existing records
1963
+ * - `publish` — publish/unpublish records
1964
+ * - `duplicate` — duplicate records
1965
+ * - `delete` — destroy records
1966
+ * - `edit_creator` — change a record's `creator` relationship
1967
+ * - `take_over` — wrest a record from another user currently editing it
1968
+ * - `move_to_stage` — move a record between workflow stages
1969
+ *
1970
+ * Per entry you can also restrict by:
1971
+ *
1972
+ * - `item_type` — restrict to a specific model (`null` = all models)
1973
+ * - `workflow` — restrict to records associated with a workflow (mutually exclusive with `item_type`)
1974
+ * - `on_creator` — `anyone`, `self` (records the credential created), or `role` (records created by anyone with this role)
1975
+ * - `localization_scope` + `locale` — for `create`/`update`/`publish`/`all`: restrict to localized vs non-localized content, optionally pinning to one locale (on `all` the scope is forced to `"all"`)
1976
+ * - `on_stage` / `to_stage` — for workflow-aware actions: restrict to records currently on a stage, or to moves towards a stage
1977
+ *
1978
+ * The shape of each entry depends on the `action` — see the property tables on each endpoint for which sub-fields are valid per branch.
1979
+ *
1980
+ * > [!WARNING] ⚠️ Some restrictors require an Enterprise plan
1981
+ * > Workflow-aware permissions — the `move_to_stage` action and the `workflow` / `on_stage` / `to_stage` restrictors — require [Workflows](https://www.datocms.com/features/workflows), an Enterprise feature. Per-content-scope restrictions are also gated: only `localization_scope: "all"` is available on every plan, while `"localized"` (with its companion `locale`) and `"not_localized"` both require Enterprise. Setting any of these on a non-Enterprise project will return an error — check the [pricing page](https://www.datocms.com/pricing) before relying on them.
1982
+ *
1983
+ * ###### Uploads
1984
+ *
1985
+ * Permission entries live in `positive_upload_permissions` (and the `negative_*` counterpart). Same discriminated-union shape as records, with the upload-relevant actions (`read`, `create`, `update`, `delete`, `edit_creator`, `replace_asset`, `move`, `all`), scoped by `upload_collection` instead of `item_type`. The `move` action also accepts `move_to_upload_collection` to restrict the destination of the move.
1986
+ *
1987
+ * ## Inheriting from other roles
1988
+ *
1989
+ * `relationships.inherits_permissions_from` accepts a list of role ids whose permissions are unioned into this role's positive set before the negative set is subtracted (per [How permissions are computed](#how-permissions-are-computed)). This is how built-in roles are typically extended without copying their full permission tree — duplicate the closest built-in role, then add a `negative_*` entry to take something away, or set `inherits_permissions_from` and add only the positive entries that differ.
1990
+ *
1991
+ * ## Effective vs declared permissions
1992
+ *
1993
+ * Two views of a role's permissions are surfaced on the response:
1994
+ *
1995
+ * - **`attributes.*`** — the permissions declared *on this role directly*. This is what was sent on create/update; it does not reflect anything inherited from `relationships.inherits_permissions_from`.
1996
+ * - **`meta.final_permissions`** — the **effective** permissions after walking the inheritance chain and applying the rule from [How permissions are computed](#how-permissions-are-computed). This is the set actually enforced when a credential bound to this role makes a request.
1997
+ *
1998
+ * When debugging "why can't this user do X?", read `meta.final_permissions`, not `attributes`.
1999
+ *
1925
2000
  *
1926
2001
  * This interface was referenced by `DatoApi`'s JSON-Schema
1927
2002
  * via the `definition` "role".
@@ -1938,11 +2013,11 @@ export type Role = {
1938
2013
  */
1939
2014
  can_edit_favicon: boolean;
1940
2015
  /**
1941
- * Can change project global properties
2016
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
1942
2017
  */
1943
2018
  can_edit_site: boolean;
1944
2019
  /**
1945
- * Can create and edit models and plugins
2020
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
1946
2021
  */
1947
2022
  can_edit_schema: boolean;
1948
2023
  /**
@@ -1950,11 +2025,11 @@ export type Role = {
1950
2025
  */
1951
2026
  can_manage_menu: boolean;
1952
2027
  /**
1953
- * Can change locales, timezone and UI theme
2028
+ * Can edit per-environment settings of the environments this role has access to: locales, timezone, and UI theme. This is *not* about creating or switching environments — see `can_manage_environments` for that, and `environments_access` for which environments this role can enter at all.
1954
2029
  */
1955
2030
  can_edit_environment: boolean;
1956
2031
  /**
1957
- * Can promote environments to primary and manage maintenance mode
2032
+ * Can promote a sandbox environment to primary (atomic swap) and toggle the project's maintenance mode. Distinct from `can_manage_environments`, which covers creating/forking/deleting sandboxes.
1958
2033
  */
1959
2034
  can_promote_environments: boolean;
1960
2035
  /**
@@ -1986,7 +2061,7 @@ export type Role = {
1986
2061
  */
1987
2062
  can_manage_webhooks: boolean;
1988
2063
  /**
1989
- * Can create and delete sandbox environments and promote them to primary environment
2064
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
1990
2065
  */
1991
2066
  can_manage_environments: boolean;
1992
2067
  /**
@@ -2018,125 +2093,47 @@ export type Role = {
2018
2093
  */
2019
2094
  can_access_search_index_events_log: boolean;
2020
2095
  /**
2021
- * Allowed actions on a model (or all) for a role
2096
+ * Allowed actions on a model (or all) for a role.
2097
+ *
2098
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2099
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2100
+ * - To grant a subset (e.g. create+read+update but not delete), prefer a single `action: "all"` entry plus `negative_item_type_permissions` entries for the actions to exclude — instead of listing each allowed action separately.
2022
2101
  */
2023
- positive_item_type_permissions: {
2024
- item_type?: ItemTypeIdentity | null;
2025
- workflow?: WorkflowIdentity | null;
2026
- on_stage?: null | string;
2027
- to_stage?: null | string;
2028
- environment: EnvironmentIdentity;
2029
- /**
2030
- * Permitted action
2031
- */
2032
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2033
- /**
2034
- * Permitted creator
2035
- */
2036
- on_creator?: 'anyone' | 'self' | 'role' | null;
2037
- /**
2038
- * Permitted content scope
2039
- */
2040
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2041
- /**
2042
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2043
- */
2044
- locale?: string | null;
2045
- }[];
2102
+ positive_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2046
2103
  /**
2047
- * Prohibited actions on a model (or all) for a role
2104
+ * Prohibited actions on a model (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions (e.g. forbid `delete`).
2048
2105
  */
2049
- negative_item_type_permissions: {
2050
- item_type?: ItemTypeIdentity | null;
2051
- workflow?: WorkflowIdentity | null;
2052
- on_stage?: null | string;
2053
- to_stage?: null | string;
2054
- environment: EnvironmentIdentity;
2055
- /**
2056
- * Permitted action
2057
- */
2058
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2059
- /**
2060
- * Permitted creator
2061
- */
2062
- on_creator?: 'anyone' | 'self' | 'role' | null;
2063
- /**
2064
- * Permitted content scope
2065
- */
2066
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2067
- /**
2068
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2069
- */
2070
- locale?: string | null;
2071
- }[];
2106
+ negative_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2072
2107
  /**
2073
- * Allowed actions on a model (or all) for a role
2108
+ * Allowed actions on uploads (or all) for a role.
2109
+ *
2110
+ * The shape of each entry depends on the `action` (discriminated union). To grant a subset, prefer a single `action: "all"` entry plus `negative_upload_permissions` entries for the actions to exclude.
2074
2111
  */
2075
- positive_upload_permissions: {
2076
- environment: EnvironmentIdentity;
2077
- /**
2078
- * Permitted action
2079
- */
2080
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2081
- /**
2082
- * Permitted creator
2083
- */
2084
- on_creator?: 'anyone' | 'self' | 'role' | null;
2085
- /**
2086
- * Permitted content scope
2087
- */
2088
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2089
- /**
2090
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2091
- */
2092
- locale?: string | null;
2093
- upload_collection?: UploadCollectionIdentity | null;
2094
- move_to_upload_collection?: UploadCollectionIdentity | null;
2095
- }[];
2112
+ positive_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2096
2113
  /**
2097
- * Prohibited actions on a model (or all) for a role
2114
+ * Prohibited actions on uploads (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions.
2098
2115
  */
2099
- negative_upload_permissions: {
2100
- environment: EnvironmentIdentity;
2101
- /**
2102
- * Permitted action
2103
- */
2104
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2105
- /**
2106
- * Permitted creator
2107
- */
2108
- on_creator?: 'anyone' | 'self' | 'role' | null;
2109
- /**
2110
- * Permitted content scope
2111
- */
2112
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2113
- /**
2114
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2115
- */
2116
- locale?: string | null;
2117
- upload_collection?: UploadCollectionIdentity | null;
2118
- move_to_upload_collection?: UploadCollectionIdentity | null;
2119
- }[];
2116
+ negative_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2120
2117
  /**
2121
- * Allowed build triggers for a role
2118
+ * Build triggers this role is allowed to **manually fire**. An entry with `build_trigger: null` covers every build trigger. Note: this does not control creating/editing build triggers themselves that is gated by `can_manage_build_triggers`.
2122
2119
  */
2123
2120
  positive_build_trigger_permissions: {
2124
2121
  build_trigger?: BuildTriggerIdentity | null;
2125
2122
  }[];
2126
2123
  /**
2127
- * Prohibited build triggers for a role
2124
+ * Build triggers this role is **forbidden** from manually firing. Negative entries take precedence over positive ones; pair with a `build_trigger: null` positive entry to allow all-but-N.
2128
2125
  */
2129
2126
  negative_build_trigger_permissions: {
2130
2127
  build_trigger?: BuildTriggerIdentity | null;
2131
2128
  }[];
2132
2129
  /**
2133
- * Search indexes that can be triggered by a role
2130
+ * Search indexes this role is allowed to **manually re-index**. An entry with `search_index: null` covers every search index. Note: this does not control creating/editing search indexes themselves — that is gated by `can_manage_search_indexes`.
2134
2131
  */
2135
2132
  positive_search_index_permissions: {
2136
2133
  search_index?: SearchIndexIdentity | null;
2137
2134
  }[];
2138
2135
  /**
2139
- * Search indexes that can't be triggered by a role
2136
+ * Search indexes this role is **forbidden** from manually re-indexing. Negative entries take precedence over positive ones; pair with a `search_index: null` positive entry to allow all-but-N.
2140
2137
  */
2141
2138
  negative_search_index_permissions: {
2142
2139
  search_index?: SearchIndexIdentity | null;
@@ -2149,6 +2146,350 @@ export type RoleUpdateTargetSchema = Role;
2149
2146
  export type RoleSelfTargetSchema = Role;
2150
2147
  export type RoleDestroyTargetSchema = Role;
2151
2148
  export type RoleDuplicateTargetSchema = Role;
2149
+ /**
2150
+ * Item-type permission entry granting all actions on a model. Requires `localization_scope: "all"`.
2151
+ *
2152
+ * This interface was referenced by `Role`'s JSON-Schema
2153
+ * via the `definition` "item_type_permission_all".
2154
+ */
2155
+ export type RoleItemTypePermissionAll = {
2156
+ /**
2157
+ * Permitted action
2158
+ */
2159
+ action: 'all';
2160
+ environment: EnvironmentIdentity;
2161
+ /**
2162
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2163
+ */
2164
+ item_type?: ItemTypeIdentity | null;
2165
+ /**
2166
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2167
+ */
2168
+ workflow?: WorkflowIdentity | null;
2169
+ /**
2170
+ * Restrict to records currently on a workflow stage.
2171
+ */
2172
+ on_stage?: string | null;
2173
+ /**
2174
+ * Restrict to moves towards a specific workflow stage.
2175
+ */
2176
+ to_stage?: string | null;
2177
+ /**
2178
+ * Permitted creator
2179
+ */
2180
+ on_creator: 'anyone' | 'self' | 'role';
2181
+ /**
2182
+ * For `action: "all"` this must be `"all"`.
2183
+ */
2184
+ localization_scope: 'all';
2185
+ [k: string]: unknown;
2186
+ };
2187
+ /**
2188
+ * Item-type permission entry granting `read` on records. `localization_scope` and `locale` must be omitted (or null).
2189
+ *
2190
+ * This interface was referenced by `Role`'s JSON-Schema
2191
+ * via the `definition` "item_type_permission_read".
2192
+ */
2193
+ export type RoleItemTypePermissionRead = {
2194
+ /**
2195
+ * Permitted action
2196
+ */
2197
+ action: 'read';
2198
+ environment: EnvironmentIdentity;
2199
+ /**
2200
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2201
+ */
2202
+ item_type?: ItemTypeIdentity | null;
2203
+ /**
2204
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2205
+ */
2206
+ workflow?: WorkflowIdentity | null;
2207
+ /**
2208
+ * Permitted creator
2209
+ */
2210
+ on_creator: 'anyone' | 'self' | 'role';
2211
+ [k: string]: unknown;
2212
+ };
2213
+ /**
2214
+ * Item-type permission entry granting `create` on records. Requires `localization_scope`; if `localization_scope: "localized"`, `locale` is also required. `on_creator`, `on_stage`, and `to_stage` are not applicable and must be omitted (or null).
2215
+ *
2216
+ * This interface was referenced by `Role`'s JSON-Schema
2217
+ * via the `definition` "item_type_permission_create".
2218
+ */
2219
+ export type RoleItemTypePermissionCreate = {
2220
+ /**
2221
+ * Permitted action
2222
+ */
2223
+ action: 'create';
2224
+ environment: EnvironmentIdentity;
2225
+ /**
2226
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2227
+ */
2228
+ item_type?: ItemTypeIdentity | null;
2229
+ /**
2230
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2231
+ */
2232
+ workflow?: WorkflowIdentity | null;
2233
+ /**
2234
+ * Permitted content scope
2235
+ */
2236
+ localization_scope: 'all' | 'localized' | 'not_localized';
2237
+ /**
2238
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2239
+ */
2240
+ locale?: string | null;
2241
+ [k: string]: unknown;
2242
+ };
2243
+ /**
2244
+ * Item-type permission entry granting `update` or `publish` on records. Requires `localization_scope`; if `localization_scope: "localized"`, `locale` is also required.
2245
+ *
2246
+ * This interface was referenced by `Role`'s JSON-Schema
2247
+ * via the `definition` "item_type_permission_update_or_publish".
2248
+ */
2249
+ export type RoleItemTypePermissionUpdateOrPublish = {
2250
+ /**
2251
+ * Permitted action
2252
+ */
2253
+ action: 'update' | 'publish';
2254
+ environment: EnvironmentIdentity;
2255
+ /**
2256
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2257
+ */
2258
+ item_type?: ItemTypeIdentity | null;
2259
+ /**
2260
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2261
+ */
2262
+ workflow?: WorkflowIdentity | null;
2263
+ /**
2264
+ * Restrict to records currently on a workflow stage.
2265
+ */
2266
+ on_stage?: string | null;
2267
+ /**
2268
+ * Permitted creator
2269
+ */
2270
+ on_creator: 'anyone' | 'self' | 'role';
2271
+ /**
2272
+ * Permitted content scope
2273
+ */
2274
+ localization_scope: 'all' | 'localized' | 'not_localized';
2275
+ /**
2276
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2277
+ */
2278
+ locale?: string | null;
2279
+ [k: string]: unknown;
2280
+ };
2281
+ /**
2282
+ * Item-type permission entry granting `duplicate` on records. `on_creator`, `localization_scope` and `locale` are not applicable and must be omitted (or null).
2283
+ *
2284
+ * This interface was referenced by `Role`'s JSON-Schema
2285
+ * via the `definition` "item_type_permission_duplicate".
2286
+ */
2287
+ export type RoleItemTypePermissionDuplicate = {
2288
+ /**
2289
+ * Permitted action
2290
+ */
2291
+ action: 'duplicate';
2292
+ environment: EnvironmentIdentity;
2293
+ /**
2294
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2295
+ */
2296
+ item_type?: ItemTypeIdentity | null;
2297
+ /**
2298
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2299
+ */
2300
+ workflow?: WorkflowIdentity | null;
2301
+ /**
2302
+ * Restrict to records currently on a workflow stage.
2303
+ */
2304
+ on_stage?: string | null;
2305
+ [k: string]: unknown;
2306
+ };
2307
+ /**
2308
+ * Item-type permission entry granting `delete`, `edit_creator`, or `take_over` on records. `localization_scope` and `locale` must be omitted (or null).
2309
+ *
2310
+ * This interface was referenced by `Role`'s JSON-Schema
2311
+ * via the `definition` "item_type_permission_delete_or_edit_creator_or_take_over".
2312
+ */
2313
+ export type RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver = {
2314
+ /**
2315
+ * Permitted action
2316
+ */
2317
+ action: 'delete' | 'edit_creator' | 'take_over';
2318
+ environment: EnvironmentIdentity;
2319
+ /**
2320
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2321
+ */
2322
+ item_type?: ItemTypeIdentity | null;
2323
+ /**
2324
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2325
+ */
2326
+ workflow?: WorkflowIdentity | null;
2327
+ /**
2328
+ * Restrict to records currently on a workflow stage.
2329
+ */
2330
+ on_stage?: string | null;
2331
+ /**
2332
+ * Permitted creator
2333
+ */
2334
+ on_creator: 'anyone' | 'self' | 'role';
2335
+ [k: string]: unknown;
2336
+ };
2337
+ /**
2338
+ * Item-type permission entry granting `move_to_stage` on records. `localization_scope` and `locale` must be omitted (or null).
2339
+ *
2340
+ * This interface was referenced by `Role`'s JSON-Schema
2341
+ * via the `definition` "item_type_permission_move_to_stage".
2342
+ */
2343
+ export type RoleItemTypePermissionMoveToStage = {
2344
+ /**
2345
+ * Permitted action
2346
+ */
2347
+ action: 'move_to_stage';
2348
+ environment: EnvironmentIdentity;
2349
+ /**
2350
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2351
+ */
2352
+ item_type?: ItemTypeIdentity | null;
2353
+ /**
2354
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2355
+ */
2356
+ workflow?: WorkflowIdentity | null;
2357
+ /**
2358
+ * Restrict to records currently on a workflow stage.
2359
+ */
2360
+ on_stage?: string | null;
2361
+ /**
2362
+ * Restrict to moves towards a specific workflow stage.
2363
+ */
2364
+ to_stage?: string | null;
2365
+ /**
2366
+ * Permitted creator
2367
+ */
2368
+ on_creator: 'anyone' | 'self' | 'role';
2369
+ [k: string]: unknown;
2370
+ };
2371
+ /**
2372
+ * Upload permission entry granting all actions on uploads. Requires `localization_scope: "all"`.
2373
+ *
2374
+ * This interface was referenced by `Role`'s JSON-Schema
2375
+ * via the `definition` "upload_permission_all".
2376
+ */
2377
+ export type RoleUploadPermissionAll = {
2378
+ /**
2379
+ * Permitted action
2380
+ */
2381
+ action: 'all';
2382
+ environment: EnvironmentIdentity;
2383
+ /**
2384
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2385
+ */
2386
+ upload_collection?: UploadCollectionIdentity | null;
2387
+ /**
2388
+ * Permitted creator
2389
+ */
2390
+ on_creator: 'anyone' | 'self' | 'role';
2391
+ /**
2392
+ * For `action: "all"` this must be `"all"`.
2393
+ */
2394
+ localization_scope: 'all';
2395
+ [k: string]: unknown;
2396
+ };
2397
+ /**
2398
+ * Upload permission entry granting `update` on uploads. Requires `localization_scope`; if `localization_scope: "localized"`, `locale` is also required.
2399
+ *
2400
+ * This interface was referenced by `Role`'s JSON-Schema
2401
+ * via the `definition` "upload_permission_update".
2402
+ */
2403
+ export type RoleUploadPermissionUpdate = {
2404
+ /**
2405
+ * Permitted action
2406
+ */
2407
+ action: 'update';
2408
+ environment: EnvironmentIdentity;
2409
+ /**
2410
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2411
+ */
2412
+ upload_collection?: UploadCollectionIdentity | null;
2413
+ /**
2414
+ * Permitted creator
2415
+ */
2416
+ on_creator: 'anyone' | 'self' | 'role';
2417
+ /**
2418
+ * Permitted content scope
2419
+ */
2420
+ localization_scope: 'all' | 'localized' | 'not_localized';
2421
+ /**
2422
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2423
+ */
2424
+ locale?: string | null;
2425
+ [k: string]: unknown;
2426
+ };
2427
+ /**
2428
+ * Upload permission entry granting `create` on uploads. `on_creator`, `localization_scope` and `locale` are not applicable and must be omitted (or null).
2429
+ *
2430
+ * This interface was referenced by `Role`'s JSON-Schema
2431
+ * via the `definition` "upload_permission_create".
2432
+ */
2433
+ export type RoleUploadPermissionCreate = {
2434
+ /**
2435
+ * Permitted action
2436
+ */
2437
+ action: 'create';
2438
+ environment: EnvironmentIdentity;
2439
+ /**
2440
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2441
+ */
2442
+ upload_collection?: UploadCollectionIdentity | null;
2443
+ [k: string]: unknown;
2444
+ };
2445
+ /**
2446
+ * Upload permission entry granting `read`, `delete`, `edit_creator`, or `replace_asset` on uploads. `localization_scope` and `locale` must be omitted (or null).
2447
+ *
2448
+ * This interface was referenced by `Role`'s JSON-Schema
2449
+ * via the `definition` "upload_permission_read_or_delete_or_edit_creator_or_replace_asset".
2450
+ */
2451
+ export type RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset = {
2452
+ /**
2453
+ * Permitted action
2454
+ */
2455
+ action: 'read' | 'delete' | 'edit_creator' | 'replace_asset';
2456
+ environment: EnvironmentIdentity;
2457
+ /**
2458
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2459
+ */
2460
+ upload_collection?: UploadCollectionIdentity | null;
2461
+ /**
2462
+ * Permitted creator
2463
+ */
2464
+ on_creator: 'anyone' | 'self' | 'role';
2465
+ [k: string]: unknown;
2466
+ };
2467
+ /**
2468
+ * Upload permission entry granting `move` on uploads. `localization_scope` and `locale` must be omitted (or null). `move_to_upload_collection` is only valid here.
2469
+ *
2470
+ * This interface was referenced by `Role`'s JSON-Schema
2471
+ * via the `definition` "upload_permission_move".
2472
+ */
2473
+ export type RoleUploadPermissionMove = {
2474
+ /**
2475
+ * Permitted action
2476
+ */
2477
+ action: 'move';
2478
+ environment: EnvironmentIdentity;
2479
+ /**
2480
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2481
+ */
2482
+ upload_collection?: UploadCollectionIdentity | null;
2483
+ /**
2484
+ * Restricts the destination upload collection of the move action. When `null`, any destination is allowed.
2485
+ */
2486
+ move_to_upload_collection?: UploadCollectionIdentity | null;
2487
+ /**
2488
+ * Permitted creator
2489
+ */
2490
+ on_creator: 'anyone' | 'self' | 'role';
2491
+ [k: string]: unknown;
2492
+ };
2152
2493
  /**
2153
2494
  * JSON API data
2154
2495
  *
@@ -2175,11 +2516,11 @@ export type RoleMeta = {
2175
2516
  */
2176
2517
  can_edit_favicon: boolean;
2177
2518
  /**
2178
- * Can change project global properties
2519
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2179
2520
  */
2180
2521
  can_edit_site: boolean;
2181
2522
  /**
2182
- * Can create and edit models and plugins
2523
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2183
2524
  */
2184
2525
  can_edit_schema: boolean;
2185
2526
  /**
@@ -2187,11 +2528,11 @@ export type RoleMeta = {
2187
2528
  */
2188
2529
  can_manage_menu: boolean;
2189
2530
  /**
2190
- * Can change locales, timezone and UI theme
2531
+ * Can edit per-environment settings of the environments this role has access to: locales, timezone, and UI theme. This is *not* about creating or switching environments — see `can_manage_environments` for that, and `environments_access` for which environments this role can enter at all.
2191
2532
  */
2192
2533
  can_edit_environment: boolean;
2193
2534
  /**
2194
- * Can promote environments to primary and manage maintenance mode
2535
+ * Can promote a sandbox environment to primary (atomic swap) and toggle the project's maintenance mode. Distinct from `can_manage_environments`, which covers creating/forking/deleting sandboxes.
2195
2536
  */
2196
2537
  can_promote_environments: boolean;
2197
2538
  /**
@@ -2223,7 +2564,7 @@ export type RoleMeta = {
2223
2564
  */
2224
2565
  can_manage_webhooks: boolean;
2225
2566
  /**
2226
- * Can create and delete sandbox environments and promote them to primary environment
2567
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2227
2568
  */
2228
2569
  can_manage_environments: boolean;
2229
2570
  /**
@@ -2255,125 +2596,47 @@ export type RoleMeta = {
2255
2596
  */
2256
2597
  can_access_search_index_events_log: boolean;
2257
2598
  /**
2258
- * Allowed actions on a model (or all) for a role
2599
+ * Allowed actions on a model (or all) for a role.
2600
+ *
2601
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2602
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2603
+ * - To grant a subset (e.g. create+read+update but not delete), prefer a single `action: "all"` entry plus `negative_item_type_permissions` entries for the actions to exclude — instead of listing each allowed action separately.
2259
2604
  */
2260
- positive_item_type_permissions: {
2261
- item_type?: ItemTypeIdentity | null;
2262
- workflow?: WorkflowIdentity | null;
2263
- on_stage?: null | string;
2264
- to_stage?: null | string;
2265
- environment: EnvironmentIdentity;
2266
- /**
2267
- * Permitted action
2268
- */
2269
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2270
- /**
2271
- * Permitted creator
2272
- */
2273
- on_creator?: 'anyone' | 'self' | 'role' | null;
2274
- /**
2275
- * Permitted content scope
2276
- */
2277
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2278
- /**
2279
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2280
- */
2281
- locale?: string | null;
2282
- }[];
2605
+ positive_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2283
2606
  /**
2284
- * Prohibited actions on a model (or all) for a role
2607
+ * Prohibited actions on a model (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions (e.g. forbid `delete`).
2285
2608
  */
2286
- negative_item_type_permissions: {
2287
- item_type?: ItemTypeIdentity | null;
2288
- workflow?: WorkflowIdentity | null;
2289
- on_stage?: null | string;
2290
- to_stage?: null | string;
2291
- environment: EnvironmentIdentity;
2292
- /**
2293
- * Permitted action
2294
- */
2295
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2296
- /**
2297
- * Permitted creator
2298
- */
2299
- on_creator?: 'anyone' | 'self' | 'role' | null;
2300
- /**
2301
- * Permitted content scope
2302
- */
2303
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2304
- /**
2305
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2306
- */
2307
- locale?: string | null;
2308
- }[];
2609
+ negative_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2309
2610
  /**
2310
- * Allowed actions on a model (or all) for a role
2611
+ * Allowed actions on uploads (or all) for a role.
2612
+ *
2613
+ * The shape of each entry depends on the `action` (discriminated union). To grant a subset, prefer a single `action: "all"` entry plus `negative_upload_permissions` entries for the actions to exclude.
2311
2614
  */
2312
- positive_upload_permissions: {
2313
- environment: EnvironmentIdentity;
2314
- /**
2315
- * Permitted action
2316
- */
2317
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2318
- /**
2319
- * Permitted creator
2320
- */
2321
- on_creator?: 'anyone' | 'self' | 'role' | null;
2322
- /**
2323
- * Permitted content scope
2324
- */
2325
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2326
- /**
2327
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2328
- */
2329
- locale?: string | null;
2330
- upload_collection?: UploadCollectionIdentity | null;
2331
- move_to_upload_collection?: UploadCollectionIdentity | null;
2332
- }[];
2615
+ positive_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2333
2616
  /**
2334
- * Prohibited actions on a model (or all) for a role
2617
+ * Prohibited actions on uploads (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions.
2335
2618
  */
2336
- negative_upload_permissions: {
2337
- environment: EnvironmentIdentity;
2338
- /**
2339
- * Permitted action
2340
- */
2341
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2342
- /**
2343
- * Permitted creator
2344
- */
2345
- on_creator?: 'anyone' | 'self' | 'role' | null;
2346
- /**
2347
- * Permitted content scope
2348
- */
2349
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2350
- /**
2351
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2352
- */
2353
- locale?: string | null;
2354
- upload_collection?: UploadCollectionIdentity | null;
2355
- move_to_upload_collection?: UploadCollectionIdentity | null;
2356
- }[];
2619
+ negative_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2357
2620
  /**
2358
- * Allowed build triggers for a role
2621
+ * Build triggers this role is allowed to **manually fire**. An entry with `build_trigger: null` covers every build trigger. Note: this does not control creating/editing build triggers themselves that is gated by `can_manage_build_triggers`.
2359
2622
  */
2360
2623
  positive_build_trigger_permissions: {
2361
2624
  build_trigger?: BuildTriggerIdentity | null;
2362
2625
  }[];
2363
2626
  /**
2364
- * Prohibited build triggers for a role
2627
+ * Build triggers this role is **forbidden** from manually firing. Negative entries take precedence over positive ones; pair with a `build_trigger: null` positive entry to allow all-but-N.
2365
2628
  */
2366
2629
  negative_build_trigger_permissions: {
2367
2630
  build_trigger?: BuildTriggerIdentity | null;
2368
2631
  }[];
2369
2632
  /**
2370
- * Search indexes that can be triggered by a role
2633
+ * Search indexes this role is allowed to **manually re-index**. An entry with `search_index: null` covers every search index. Note: this does not control creating/editing search indexes themselves — that is gated by `can_manage_search_indexes`.
2371
2634
  */
2372
2635
  positive_search_index_permissions: {
2373
2636
  search_index?: SearchIndexIdentity | null;
2374
2637
  }[];
2375
2638
  /**
2376
- * Search indexes that can't be triggered by a role
2639
+ * Search indexes this role is **forbidden** from manually re-indexing. Negative entries take precedence over positive ones; pair with a `search_index: null` positive entry to allow all-but-N.
2377
2640
  */
2378
2641
  negative_search_index_permissions: {
2379
2642
  search_index?: SearchIndexIdentity | null;
@@ -2396,11 +2659,11 @@ export type RoleAttributes = {
2396
2659
  */
2397
2660
  can_edit_favicon: boolean;
2398
2661
  /**
2399
- * Can change project global properties
2662
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2400
2663
  */
2401
2664
  can_edit_site: boolean;
2402
2665
  /**
2403
- * Can create and edit models and plugins
2666
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2404
2667
  */
2405
2668
  can_edit_schema: boolean;
2406
2669
  /**
@@ -2408,11 +2671,11 @@ export type RoleAttributes = {
2408
2671
  */
2409
2672
  can_manage_menu: boolean;
2410
2673
  /**
2411
- * Can change locales, timezone and UI theme
2674
+ * Can edit per-environment settings of the environments this role has access to: locales, timezone, and UI theme. This is *not* about creating or switching environments — see `can_manage_environments` for that, and `environments_access` for which environments this role can enter at all.
2412
2675
  */
2413
2676
  can_edit_environment: boolean;
2414
2677
  /**
2415
- * Can promote environments to primary and manage maintenance mode
2678
+ * Can promote a sandbox environment to primary (atomic swap) and toggle the project's maintenance mode. Distinct from `can_manage_environments`, which covers creating/forking/deleting sandboxes.
2416
2679
  */
2417
2680
  can_promote_environments: boolean;
2418
2681
  /**
@@ -2444,7 +2707,7 @@ export type RoleAttributes = {
2444
2707
  */
2445
2708
  can_manage_webhooks: boolean;
2446
2709
  /**
2447
- * Can create and delete sandbox environments and promote them to primary environment
2710
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2448
2711
  */
2449
2712
  can_manage_environments: boolean;
2450
2713
  /**
@@ -2476,125 +2739,47 @@ export type RoleAttributes = {
2476
2739
  */
2477
2740
  can_access_search_index_events_log: boolean;
2478
2741
  /**
2479
- * Allowed actions on a model (or all) for a role
2742
+ * Allowed actions on a model (or all) for a role.
2743
+ *
2744
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2745
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2746
+ * - To grant a subset (e.g. create+read+update but not delete), prefer a single `action: "all"` entry plus `negative_item_type_permissions` entries for the actions to exclude — instead of listing each allowed action separately.
2480
2747
  */
2481
- positive_item_type_permissions: {
2482
- item_type?: ItemTypeIdentity | null;
2483
- workflow?: WorkflowIdentity | null;
2484
- on_stage?: null | string;
2485
- to_stage?: null | string;
2486
- environment: EnvironmentIdentity;
2487
- /**
2488
- * Permitted action
2489
- */
2490
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2491
- /**
2492
- * Permitted creator
2493
- */
2494
- on_creator?: 'anyone' | 'self' | 'role' | null;
2495
- /**
2496
- * Permitted content scope
2497
- */
2498
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2499
- /**
2500
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2501
- */
2502
- locale?: string | null;
2503
- }[];
2748
+ positive_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2504
2749
  /**
2505
- * Prohibited actions on a model (or all) for a role
2750
+ * Prohibited actions on a model (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions (e.g. forbid `delete`).
2506
2751
  */
2507
- negative_item_type_permissions: {
2508
- item_type?: ItemTypeIdentity | null;
2509
- workflow?: WorkflowIdentity | null;
2510
- on_stage?: null | string;
2511
- to_stage?: null | string;
2512
- environment: EnvironmentIdentity;
2513
- /**
2514
- * Permitted action
2515
- */
2516
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2517
- /**
2518
- * Permitted creator
2519
- */
2520
- on_creator?: 'anyone' | 'self' | 'role' | null;
2521
- /**
2522
- * Permitted content scope
2523
- */
2524
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2525
- /**
2526
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2527
- */
2528
- locale?: string | null;
2529
- }[];
2752
+ negative_item_type_permissions: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2530
2753
  /**
2531
- * Allowed actions on a model (or all) for a role
2754
+ * Allowed actions on uploads (or all) for a role.
2755
+ *
2756
+ * The shape of each entry depends on the `action` (discriminated union). To grant a subset, prefer a single `action: "all"` entry plus `negative_upload_permissions` entries for the actions to exclude.
2532
2757
  */
2533
- positive_upload_permissions: {
2534
- environment: EnvironmentIdentity;
2535
- /**
2536
- * Permitted action
2537
- */
2538
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2539
- /**
2540
- * Permitted creator
2541
- */
2542
- on_creator?: 'anyone' | 'self' | 'role' | null;
2543
- /**
2544
- * Permitted content scope
2545
- */
2546
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2547
- /**
2548
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2549
- */
2550
- locale?: string | null;
2551
- upload_collection?: UploadCollectionIdentity | null;
2552
- move_to_upload_collection?: UploadCollectionIdentity | null;
2553
- }[];
2758
+ positive_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2554
2759
  /**
2555
- * Prohibited actions on a model (or all) for a role
2760
+ * Prohibited actions on uploads (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions.
2556
2761
  */
2557
- negative_upload_permissions: {
2558
- environment: EnvironmentIdentity;
2559
- /**
2560
- * Permitted action
2561
- */
2562
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2563
- /**
2564
- * Permitted creator
2565
- */
2566
- on_creator?: 'anyone' | 'self' | 'role' | null;
2567
- /**
2568
- * Permitted content scope
2569
- */
2570
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2571
- /**
2572
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2573
- */
2574
- locale?: string | null;
2575
- upload_collection?: UploadCollectionIdentity | null;
2576
- move_to_upload_collection?: UploadCollectionIdentity | null;
2577
- }[];
2762
+ negative_upload_permissions: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2578
2763
  /**
2579
- * Allowed build triggers for a role
2764
+ * Build triggers this role is allowed to **manually fire**. An entry with `build_trigger: null` covers every build trigger. Note: this does not control creating/editing build triggers themselves that is gated by `can_manage_build_triggers`.
2580
2765
  */
2581
2766
  positive_build_trigger_permissions: {
2582
2767
  build_trigger?: BuildTriggerIdentity | null;
2583
2768
  }[];
2584
2769
  /**
2585
- * Prohibited build triggers for a role
2770
+ * Build triggers this role is **forbidden** from manually firing. Negative entries take precedence over positive ones; pair with a `build_trigger: null` positive entry to allow all-but-N.
2586
2771
  */
2587
2772
  negative_build_trigger_permissions: {
2588
2773
  build_trigger?: BuildTriggerIdentity | null;
2589
2774
  }[];
2590
2775
  /**
2591
- * Search indexes that can be triggered by a role
2776
+ * Search indexes this role is allowed to **manually re-index**. An entry with `search_index: null` covers every search index. Note: this does not control creating/editing search indexes themselves — that is gated by `can_manage_search_indexes`.
2592
2777
  */
2593
2778
  positive_search_index_permissions: {
2594
2779
  search_index?: SearchIndexIdentity | null;
2595
2780
  }[];
2596
2781
  /**
2597
- * Search indexes that can't be triggered by a role
2782
+ * Search indexes this role is **forbidden** from manually re-indexing. Negative entries take precedence over positive ones; pair with a `search_index: null` positive entry to allow all-but-N.
2598
2783
  */
2599
2784
  negative_search_index_permissions: {
2600
2785
  search_index?: SearchIndexIdentity | null;
@@ -2624,11 +2809,11 @@ export type RoleCreateSchema = {
2624
2809
  */
2625
2810
  can_edit_favicon?: boolean;
2626
2811
  /**
2627
- * Can change project global properties
2812
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2628
2813
  */
2629
2814
  can_edit_site?: boolean;
2630
2815
  /**
2631
- * Can create and edit models and plugins
2816
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2632
2817
  */
2633
2818
  can_edit_schema?: boolean;
2634
2819
  /**
@@ -2636,11 +2821,11 @@ export type RoleCreateSchema = {
2636
2821
  */
2637
2822
  can_manage_menu?: boolean;
2638
2823
  /**
2639
- * Can change locales, timezone and UI theme
2824
+ * Can edit per-environment settings of the environments this role has access to: locales, timezone, and UI theme. This is *not* about creating or switching environments — see `can_manage_environments` for that, and `environments_access` for which environments this role can enter at all.
2640
2825
  */
2641
2826
  can_edit_environment?: boolean;
2642
2827
  /**
2643
- * Can promote environments to primary and manage maintenance mode
2828
+ * Can promote a sandbox environment to primary (atomic swap) and toggle the project's maintenance mode. Distinct from `can_manage_environments`, which covers creating/forking/deleting sandboxes.
2644
2829
  */
2645
2830
  can_promote_environments?: boolean;
2646
2831
  /**
@@ -2672,7 +2857,7 @@ export type RoleCreateSchema = {
2672
2857
  */
2673
2858
  can_manage_webhooks?: boolean;
2674
2859
  /**
2675
- * Can create and delete sandbox environments and promote them to primary environment
2860
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2676
2861
  */
2677
2862
  can_manage_environments?: boolean;
2678
2863
  /**
@@ -2704,125 +2889,47 @@ export type RoleCreateSchema = {
2704
2889
  */
2705
2890
  can_access_search_index_events_log?: boolean;
2706
2891
  /**
2707
- * Allowed actions on a model (or all) for a role
2892
+ * Allowed actions on a model (or all) for a role.
2893
+ *
2894
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2895
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2896
+ * - To grant a subset (e.g. create+read+update but not delete), prefer a single `action: "all"` entry plus `negative_item_type_permissions` entries for the actions to exclude — instead of listing each allowed action separately.
2708
2897
  */
2709
- positive_item_type_permissions?: {
2710
- item_type?: ItemTypeIdentity | null;
2711
- workflow?: WorkflowIdentity | null;
2712
- on_stage?: null | string;
2713
- to_stage?: null | string;
2714
- environment: EnvironmentIdentity;
2715
- /**
2716
- * Permitted action
2717
- */
2718
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2719
- /**
2720
- * Permitted creator
2721
- */
2722
- on_creator?: 'anyone' | 'self' | 'role' | null;
2723
- /**
2724
- * Permitted content scope
2725
- */
2726
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2727
- /**
2728
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2729
- */
2730
- locale?: string | null;
2731
- }[];
2898
+ positive_item_type_permissions?: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2732
2899
  /**
2733
- * Prohibited actions on a model (or all) for a role
2900
+ * Prohibited actions on a model (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions (e.g. forbid `delete`).
2734
2901
  */
2735
- negative_item_type_permissions?: {
2736
- item_type?: ItemTypeIdentity | null;
2737
- workflow?: WorkflowIdentity | null;
2738
- on_stage?: null | string;
2739
- to_stage?: null | string;
2740
- environment: EnvironmentIdentity;
2741
- /**
2742
- * Permitted action
2743
- */
2744
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2745
- /**
2746
- * Permitted creator
2747
- */
2748
- on_creator?: 'anyone' | 'self' | 'role' | null;
2749
- /**
2750
- * Permitted content scope
2751
- */
2752
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2753
- /**
2754
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2755
- */
2756
- locale?: string | null;
2757
- }[];
2902
+ negative_item_type_permissions?: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2758
2903
  /**
2759
- * Allowed actions on a model (or all) for a role
2904
+ * Allowed actions on uploads (or all) for a role.
2905
+ *
2906
+ * The shape of each entry depends on the `action` (discriminated union). To grant a subset, prefer a single `action: "all"` entry plus `negative_upload_permissions` entries for the actions to exclude.
2760
2907
  */
2761
- positive_upload_permissions?: {
2762
- environment: EnvironmentIdentity;
2763
- /**
2764
- * Permitted action
2765
- */
2766
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2767
- /**
2768
- * Permitted creator
2769
- */
2770
- on_creator?: 'anyone' | 'self' | 'role' | null;
2771
- /**
2772
- * Permitted content scope
2773
- */
2774
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2775
- /**
2776
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2777
- */
2778
- locale?: string | null;
2779
- upload_collection?: UploadCollectionIdentity | null;
2780
- move_to_upload_collection?: UploadCollectionIdentity | null;
2781
- }[];
2908
+ positive_upload_permissions?: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2782
2909
  /**
2783
- * Prohibited actions on a model (or all) for a role
2910
+ * Prohibited actions on uploads (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions.
2784
2911
  */
2785
- negative_upload_permissions?: {
2786
- environment: EnvironmentIdentity;
2787
- /**
2788
- * Permitted action
2789
- */
2790
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2791
- /**
2792
- * Permitted creator
2793
- */
2794
- on_creator?: 'anyone' | 'self' | 'role' | null;
2795
- /**
2796
- * Permitted content scope
2797
- */
2798
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2799
- /**
2800
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2801
- */
2802
- locale?: string | null;
2803
- upload_collection?: UploadCollectionIdentity | null;
2804
- move_to_upload_collection?: UploadCollectionIdentity | null;
2805
- }[];
2912
+ negative_upload_permissions?: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
2806
2913
  /**
2807
- * Allowed build triggers for a role
2914
+ * Build triggers this role is allowed to **manually fire**. An entry with `build_trigger: null` covers every build trigger. Note: this does not control creating/editing build triggers themselves that is gated by `can_manage_build_triggers`.
2808
2915
  */
2809
2916
  positive_build_trigger_permissions?: {
2810
2917
  build_trigger?: BuildTriggerIdentity | null;
2811
2918
  }[];
2812
2919
  /**
2813
- * Prohibited build triggers for a role
2920
+ * Build triggers this role is **forbidden** from manually firing. Negative entries take precedence over positive ones; pair with a `build_trigger: null` positive entry to allow all-but-N.
2814
2921
  */
2815
2922
  negative_build_trigger_permissions?: {
2816
2923
  build_trigger?: BuildTriggerIdentity | null;
2817
2924
  }[];
2818
2925
  /**
2819
- * Search indexes that can be triggered by a role
2926
+ * Search indexes this role is allowed to **manually re-index**. An entry with `search_index: null` covers every search index. Note: this does not control creating/editing search indexes themselves — that is gated by `can_manage_search_indexes`.
2820
2927
  */
2821
2928
  positive_search_index_permissions?: {
2822
2929
  search_index?: SearchIndexIdentity | null;
2823
2930
  }[];
2824
2931
  /**
2825
- * Search indexes that can't be triggered by a role
2932
+ * Search indexes this role is **forbidden** from manually re-indexing. Negative entries take precedence over positive ones; pair with a `search_index: null` positive entry to allow all-but-N.
2826
2933
  */
2827
2934
  negative_search_index_permissions?: {
2828
2935
  search_index?: SearchIndexIdentity | null;
@@ -2846,11 +2953,11 @@ export type RoleUpdateSchema = {
2846
2953
  */
2847
2954
  can_edit_favicon?: boolean;
2848
2955
  /**
2849
- * Can change project global properties
2956
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2850
2957
  */
2851
2958
  can_edit_site?: boolean;
2852
2959
  /**
2853
- * Can create and edit models and plugins
2960
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2854
2961
  */
2855
2962
  can_edit_schema?: boolean;
2856
2963
  /**
@@ -2858,11 +2965,11 @@ export type RoleUpdateSchema = {
2858
2965
  */
2859
2966
  can_manage_menu?: boolean;
2860
2967
  /**
2861
- * Can change locales, timezone and UI theme
2968
+ * Can edit per-environment settings of the environments this role has access to: locales, timezone, and UI theme. This is *not* about creating or switching environments — see `can_manage_environments` for that, and `environments_access` for which environments this role can enter at all.
2862
2969
  */
2863
2970
  can_edit_environment?: boolean;
2864
2971
  /**
2865
- * Can promote environments to primary and manage maintenance mode
2972
+ * Can promote a sandbox environment to primary (atomic swap) and toggle the project's maintenance mode. Distinct from `can_manage_environments`, which covers creating/forking/deleting sandboxes.
2866
2973
  */
2867
2974
  can_promote_environments?: boolean;
2868
2975
  /**
@@ -2894,7 +3001,7 @@ export type RoleUpdateSchema = {
2894
3001
  */
2895
3002
  can_manage_webhooks?: boolean;
2896
3003
  /**
2897
- * Can create and delete sandbox environments and promote them to primary environment
3004
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2898
3005
  */
2899
3006
  can_manage_environments?: boolean;
2900
3007
  /**
@@ -2926,125 +3033,47 @@ export type RoleUpdateSchema = {
2926
3033
  */
2927
3034
  can_access_search_index_events_log?: boolean;
2928
3035
  /**
2929
- * Allowed actions on a model (or all) for a role
3036
+ * Allowed actions on a model (or all) for a role.
3037
+ *
3038
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
3039
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
3040
+ * - To grant a subset (e.g. create+read+update but not delete), prefer a single `action: "all"` entry plus `negative_item_type_permissions` entries for the actions to exclude — instead of listing each allowed action separately.
2930
3041
  */
2931
- positive_item_type_permissions?: {
2932
- item_type?: ItemTypeIdentity | null;
2933
- workflow?: WorkflowIdentity | null;
2934
- on_stage?: null | string;
2935
- to_stage?: null | string;
2936
- environment: EnvironmentIdentity;
2937
- /**
2938
- * Permitted action
2939
- */
2940
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2941
- /**
2942
- * Permitted creator
2943
- */
2944
- on_creator?: 'anyone' | 'self' | 'role' | null;
2945
- /**
2946
- * Permitted content scope
2947
- */
2948
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2949
- /**
2950
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2951
- */
2952
- locale?: string | null;
2953
- }[];
3042
+ positive_item_type_permissions?: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2954
3043
  /**
2955
- * Prohibited actions on a model (or all) for a role
3044
+ * Prohibited actions on a model (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions (e.g. forbid `delete`).
2956
3045
  */
2957
- negative_item_type_permissions?: {
2958
- item_type?: ItemTypeIdentity | null;
2959
- workflow?: WorkflowIdentity | null;
2960
- on_stage?: null | string;
2961
- to_stage?: null | string;
2962
- environment: EnvironmentIdentity;
2963
- /**
2964
- * Permitted action
2965
- */
2966
- action: 'all' | 'read' | 'update' | 'create' | 'duplicate' | 'delete' | 'publish' | 'edit_creator' | 'take_over' | 'move_to_stage';
2967
- /**
2968
- * Permitted creator
2969
- */
2970
- on_creator?: 'anyone' | 'self' | 'role' | null;
2971
- /**
2972
- * Permitted content scope
2973
- */
2974
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2975
- /**
2976
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2977
- */
2978
- locale?: string | null;
2979
- }[];
3046
+ negative_item_type_permissions?: (RoleItemTypePermissionAll | RoleItemTypePermissionRead | RoleItemTypePermissionCreate | RoleItemTypePermissionUpdateOrPublish | RoleItemTypePermissionDuplicate | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver | RoleItemTypePermissionMoveToStage)[];
2980
3047
  /**
2981
- * Allowed actions on a model (or all) for a role
3048
+ * Allowed actions on uploads (or all) for a role.
3049
+ *
3050
+ * The shape of each entry depends on the `action` (discriminated union). To grant a subset, prefer a single `action: "all"` entry plus `negative_upload_permissions` entries for the actions to exclude.
2982
3051
  */
2983
- positive_upload_permissions?: {
2984
- environment: EnvironmentIdentity;
2985
- /**
2986
- * Permitted action
2987
- */
2988
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
2989
- /**
2990
- * Permitted creator
2991
- */
2992
- on_creator?: 'anyone' | 'self' | 'role' | null;
2993
- /**
2994
- * Permitted content scope
2995
- */
2996
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2997
- /**
2998
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2999
- */
3000
- locale?: string | null;
3001
- upload_collection?: UploadCollectionIdentity | null;
3002
- move_to_upload_collection?: UploadCollectionIdentity | null;
3003
- }[];
3052
+ positive_upload_permissions?: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
3004
3053
  /**
3005
- * Prohibited actions on a model (or all) for a role
3054
+ * Prohibited actions on uploads (or all) for a role. Negative permissions take precedence and are typically paired with a broader positive `action: "all"` entry to subtract specific actions.
3006
3055
  */
3007
- negative_upload_permissions?: {
3008
- environment: EnvironmentIdentity;
3009
- /**
3010
- * Permitted action
3011
- */
3012
- action: 'all' | 'read' | 'update' | 'create' | 'delete' | 'edit_creator' | 'replace_asset' | 'move';
3013
- /**
3014
- * Permitted creator
3015
- */
3016
- on_creator?: 'anyone' | 'self' | 'role' | null;
3017
- /**
3018
- * Permitted content scope
3019
- */
3020
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
3021
- /**
3022
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
3023
- */
3024
- locale?: string | null;
3025
- upload_collection?: UploadCollectionIdentity | null;
3026
- move_to_upload_collection?: UploadCollectionIdentity | null;
3027
- }[];
3056
+ negative_upload_permissions?: (RoleUploadPermissionAll | RoleUploadPermissionUpdate | RoleUploadPermissionCreate | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset | RoleUploadPermissionMove)[];
3028
3057
  /**
3029
- * Allowed build triggers for a role
3058
+ * Build triggers this role is allowed to **manually fire**. An entry with `build_trigger: null` covers every build trigger. Note: this does not control creating/editing build triggers themselves that is gated by `can_manage_build_triggers`.
3030
3059
  */
3031
3060
  positive_build_trigger_permissions?: {
3032
3061
  build_trigger?: BuildTriggerIdentity | null;
3033
3062
  }[];
3034
3063
  /**
3035
- * Prohibited build triggers for a role
3064
+ * Build triggers this role is **forbidden** from manually firing. Negative entries take precedence over positive ones; pair with a `build_trigger: null` positive entry to allow all-but-N.
3036
3065
  */
3037
3066
  negative_build_trigger_permissions?: {
3038
3067
  build_trigger?: BuildTriggerIdentity | null;
3039
3068
  }[];
3040
3069
  /**
3041
- * Search indexes that can be triggered by a role
3070
+ * Search indexes this role is allowed to **manually re-index**. An entry with `search_index: null` covers every search index. Note: this does not control creating/editing search indexes themselves — that is gated by `can_manage_search_indexes`.
3042
3071
  */
3043
3072
  positive_search_index_permissions?: {
3044
3073
  search_index?: SearchIndexIdentity | null;
3045
3074
  }[];
3046
3075
  /**
3047
- * Search indexes that can't be triggered by a role
3076
+ * Search indexes this role is **forbidden** from manually re-indexing. Negative entries take precedence over positive ones; pair with a `search_index: null` positive entry to allow all-but-N.
3048
3077
  */
3049
3078
  negative_search_index_permissions?: {
3050
3079
  search_index?: SearchIndexIdentity | null;
@@ -3257,7 +3286,16 @@ export type SsoUserRelationships = {
3257
3286
  role: RoleData | null;
3258
3287
  };
3259
3288
  /**
3260
- * An API token allows access to our API. It is linked to a Role, which describes what actions can be performed.
3289
+ * An API token authenticates programmatic access to a project. Each token combines two layers of access control:
3290
+ *
3291
+ * 1. A **Role** that defines what actions are permitted (the same Role resource used for human collaborators).
3292
+ * 2. A set of **API surface flags** (`can_access_cda`, `can_access_cda_preview`, `can_access_cma`) that gate which APIs the token can hit at all.
3293
+ *
3294
+ * The token's effective capabilities are the *intersection* of the two.
3295
+ *
3296
+ * > [!PROTIP] 💡 A CDA-only token can safely reuse a write-capable Role
3297
+ * > A token with only `can_access_cda: true` is safe to attach to a Role that grants `update`/`publish`/`delete` — the Content Delivery API exposes no write endpoints, so those actions have no surface to act on. This makes it practical to share a single Role definition between an editor (acting via the dashboard / CMA) and a public read token (used by a frontend / CDA) for the same project.
3298
+ *
3261
3299
  *
3262
3300
  * This interface was referenced by `DatoApi`'s JSON-Schema
3263
3301
  * via the `definition` "access_token".
@@ -3270,21 +3308,24 @@ export type AccessToken = {
3270
3308
  */
3271
3309
  name: string;
3272
3310
  /**
3273
- * The actual API token (or null if the current user has no permission to read the token)
3311
+ * The secret value used as the `Authorization: Bearer <token>` credential. Returned on every endpoint (create, update, retrieve, list, rotate) to callers whose current role has `can_manage_access_tokens`; otherwise `null`.
3274
3312
  */
3275
3313
  token?: null | string;
3276
3314
  /**
3277
- * Whether this API token can access the Content Delivery API published content endpoint
3315
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3278
3316
  */
3279
3317
  can_access_cda: boolean;
3280
3318
  /**
3281
- * Whether this API token can access the Content Delivery API draft content endpoint
3319
+ * Whether this API token can call the Content Delivery API with the `X-Include-Drafts: true` header to fetch **draft** (current, unpublished) content. There is no separate endpoint — the CDA is a single GraphQL endpoint and this flag governs whether requesting drafts is allowed.
3282
3320
  */
3283
3321
  can_access_cda_preview: boolean;
3284
3322
  /**
3285
3323
  * Whether this API token can access the Content Management API
3286
3324
  */
3287
3325
  can_access_cma: boolean;
3326
+ /**
3327
+ * Internal marker for the project's built-in factory tokens (e.g. read-only API token), seeded by DatoCMS when the project is created. Read-only attribute. When non-null, attribute updates are rejected with `NON_EDITABLE_ACCESS_TOKEN`, but the token can still be deleted and regenerated. `null` for any token created via this API.
3328
+ */
3288
3329
  hardcoded_type: null | string;
3289
3330
  /**
3290
3331
  * When this API token was last used to access the Content Management API
@@ -3323,21 +3364,24 @@ export type AccessTokenAttributes = {
3323
3364
  */
3324
3365
  name: string;
3325
3366
  /**
3326
- * The actual API token (or null if the current user has no permission to read the token)
3367
+ * The secret value used as the `Authorization: Bearer <token>` credential. Returned on every endpoint (create, update, retrieve, list, rotate) to callers whose current role has `can_manage_access_tokens`; otherwise `null`.
3327
3368
  */
3328
3369
  token?: null | string;
3329
3370
  /**
3330
- * Whether this API token can access the Content Delivery API published content endpoint
3371
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3331
3372
  */
3332
3373
  can_access_cda: boolean;
3333
3374
  /**
3334
- * Whether this API token can access the Content Delivery API draft content endpoint
3375
+ * Whether this API token can call the Content Delivery API with the `X-Include-Drafts: true` header to fetch **draft** (current, unpublished) content. There is no separate endpoint — the CDA is a single GraphQL endpoint and this flag governs whether requesting drafts is allowed.
3335
3376
  */
3336
3377
  can_access_cda_preview: boolean;
3337
3378
  /**
3338
3379
  * Whether this API token can access the Content Management API
3339
3380
  */
3340
3381
  can_access_cma: boolean;
3382
+ /**
3383
+ * Internal marker for the project's built-in factory tokens (e.g. read-only API token), seeded by DatoCMS when the project is created. Read-only attribute. When non-null, attribute updates are rejected with `NON_EDITABLE_ACCESS_TOKEN`, but the token can still be deleted and regenerated. `null` for any token created via this API.
3384
+ */
3341
3385
  hardcoded_type: null | string;
3342
3386
  /**
3343
3387
  * When this API token was last used to access the Content Management API
@@ -3368,11 +3412,11 @@ export type AccessTokenCreateSchema = {
3368
3412
  */
3369
3413
  name: string;
3370
3414
  /**
3371
- * Whether this API token can access the Content Delivery API published content endpoint
3415
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3372
3416
  */
3373
3417
  can_access_cda: boolean;
3374
3418
  /**
3375
- * Whether this API token can access the Content Delivery API draft content endpoint
3419
+ * Whether this API token can call the Content Delivery API with the `X-Include-Drafts: true` header to fetch **draft** (current, unpublished) content. There is no separate endpoint — the CDA is a single GraphQL endpoint and this flag governs whether requesting drafts is allowed.
3376
3420
  */
3377
3421
  can_access_cda_preview: boolean;
3378
3422
  /**
@@ -3393,11 +3437,11 @@ export type AccessTokenUpdateSchema = {
3393
3437
  */
3394
3438
  name: string;
3395
3439
  /**
3396
- * Whether this API token can access the Content Delivery API published content endpoint
3440
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3397
3441
  */
3398
3442
  can_access_cda: boolean;
3399
3443
  /**
3400
- * Whether this API token can access the Content Delivery API draft content endpoint
3444
+ * Whether this API token can call the Content Delivery API with the `X-Include-Drafts: true` header to fetch **draft** (current, unpublished) content. There is no separate endpoint — the CDA is a single GraphQL endpoint and this flag governs whether requesting drafts is allowed.
3401
3445
  */
3402
3446
  can_access_cda_preview: boolean;
3403
3447
  /**