@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.
@@ -83,6 +83,16 @@ export type RoleType = 'role';
83
83
  * via the `definition` "id".
84
84
  */
85
85
  export type RoleIdentity = string;
86
+ /**
87
+ * ID of environment. Can only contain lowercase letters, numbers and dashes
88
+ *
89
+ * This interface was referenced by `Environment`'s JSON-Schema
90
+ * via the `definition` "identity".
91
+ *
92
+ * This interface was referenced by `Environment`'s JSON-Schema
93
+ * via the `definition` "id".
94
+ */
95
+ export type EnvironmentIdentity = string;
86
96
  /**
87
97
  * RFC 4122 UUID of item type expressed in URL-safe base64 format
88
98
  *
@@ -103,16 +113,6 @@ export type ItemTypeIdentity = string;
103
113
  * via the `definition` "id".
104
114
  */
105
115
  export type WorkflowIdentity = string;
106
- /**
107
- * ID of environment. Can only contain lowercase letters, numbers and dashes
108
- *
109
- * This interface was referenced by `Environment`'s JSON-Schema
110
- * via the `definition` "identity".
111
- *
112
- * This interface was referenced by `Environment`'s JSON-Schema
113
- * via the `definition` "id".
114
- */
115
- export type EnvironmentIdentity = string;
116
116
  /**
117
117
  * RFC 4122 UUID of upload collection expressed in URL-safe base64 format
118
118
  *
@@ -235,9 +235,14 @@ export type AccessTokenIdentity = string;
235
235
  */
236
236
  export type AccessTokenDestroyHrefSchema = {
237
237
  /**
238
- * New owner for resources previously owned by the deleted access token. This argument specifies the new owner type.
238
+ * 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.
239
239
  */
240
- destination_user_type?: 'account' | 'user' | 'access_token' | 'sso_user';
240
+ destination_user_type?:
241
+ | 'account'
242
+ | 'organization'
243
+ | 'user'
244
+ | 'access_token'
245
+ | 'sso_user';
241
246
  /**
242
247
  * New owner for resources previously owned by the deleted access token. This argument specifies the new owner ID.
243
248
  */
@@ -1663,7 +1668,82 @@ export type SiteSelfHrefSchema = {
1663
1668
  [k: string]: unknown;
1664
1669
  };
1665
1670
  /**
1666
- * A Role represents a specific set of actions an editor (or an API token) can perform on your administrative area.
1671
+ * 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.
1672
+ *
1673
+ * > [!PROTIP] 📘 Same role, different identities
1674
+ * > 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.
1675
+ *
1676
+ * ## How permissions are computed
1677
+ *
1678
+ * 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:
1679
+ *
1680
+ * > Effective permissions = `(inherited ∪ positive_*) − negative_*`
1681
+ *
1682
+ * 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.
1683
+ *
1684
+ * > [!WARNING] ⚠️ Send `positive_*` and `negative_*` together
1685
+ * > 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.
1686
+ *
1687
+ * 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.
1688
+ *
1689
+ * ## Project-level permissions
1690
+ *
1691
+ * 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).
1692
+ *
1693
+ * - **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.
1694
+ * - **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.
1695
+ * - **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`.
1696
+ * - **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`.
1697
+ *
1698
+ * ## Per-environment content permissions
1699
+ *
1700
+ * 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.
1701
+ *
1702
+ * ###### Records
1703
+ *
1704
+ * Permission entries live in `positive_item_type_permissions` (and the `negative_*` counterpart). Each entry is a discriminated union keyed by `action`:
1705
+ *
1706
+ * - `all` — every action below
1707
+ * - `read` — read records
1708
+ * - `create` — create new records
1709
+ * - `update` — edit existing records
1710
+ * - `publish` — publish/unpublish records
1711
+ * - `duplicate` — duplicate records
1712
+ * - `delete` — destroy records
1713
+ * - `edit_creator` — change a record's `creator` relationship
1714
+ * - `take_over` — wrest a record from another user currently editing it
1715
+ * - `move_to_stage` — move a record between workflow stages
1716
+ *
1717
+ * Per entry you can also restrict by:
1718
+ *
1719
+ * - `item_type` — restrict to a specific model (`null` = all models)
1720
+ * - `workflow` — restrict to records associated with a workflow (mutually exclusive with `item_type`)
1721
+ * - `on_creator` — `anyone`, `self` (records the credential created), or `role` (records created by anyone with this role)
1722
+ * - `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"`)
1723
+ * - `on_stage` / `to_stage` — for workflow-aware actions: restrict to records currently on a stage, or to moves towards a stage
1724
+ *
1725
+ * The shape of each entry depends on the `action` — see the property tables on each endpoint for which sub-fields are valid per branch.
1726
+ *
1727
+ * > [!WARNING] ⚠️ Some restrictors require an Enterprise plan
1728
+ * > 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.
1729
+ *
1730
+ * ###### Uploads
1731
+ *
1732
+ * 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.
1733
+ *
1734
+ * ## Inheriting from other roles
1735
+ *
1736
+ * `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.
1737
+ *
1738
+ * ## Effective vs declared permissions
1739
+ *
1740
+ * Two views of a role's permissions are surfaced on the response:
1741
+ *
1742
+ * - **`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`.
1743
+ * - **`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.
1744
+ *
1745
+ * When debugging "why can't this user do X?", read `meta.final_permissions`, not `attributes`.
1746
+ *
1667
1747
  *
1668
1748
  * This interface was referenced by `DatoApi`'s JSON-Schema
1669
1749
  * via the `definition` "role".
@@ -1691,11 +1771,11 @@ export type RoleAttributes = {
1691
1771
  */
1692
1772
  can_edit_favicon: boolean;
1693
1773
  /**
1694
- * Can change project global properties
1774
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
1695
1775
  */
1696
1776
  can_edit_site: boolean;
1697
1777
  /**
1698
- * Can create and edit models and plugins
1778
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
1699
1779
  */
1700
1780
  can_edit_schema: boolean;
1701
1781
  /**
@@ -1703,11 +1783,11 @@ export type RoleAttributes = {
1703
1783
  */
1704
1784
  can_manage_menu: boolean;
1705
1785
  /**
1706
- * Can change locales, timezone and UI theme
1786
+ * 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.
1707
1787
  */
1708
1788
  can_edit_environment: boolean;
1709
1789
  /**
1710
- * Can promote environments to primary and manage maintenance mode
1790
+ * 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.
1711
1791
  */
1712
1792
  can_promote_environments: boolean;
1713
1793
  /**
@@ -1739,7 +1819,7 @@ export type RoleAttributes = {
1739
1819
  */
1740
1820
  can_manage_webhooks: boolean;
1741
1821
  /**
1742
- * Can create and delete sandbox environments and promote them to primary environment
1822
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
1743
1823
  */
1744
1824
  can_manage_environments: boolean;
1745
1825
  /**
@@ -1771,166 +1851,424 @@ export type RoleAttributes = {
1771
1851
  */
1772
1852
  can_access_search_index_events_log: boolean;
1773
1853
  /**
1774
- * Allowed actions on a model (or all) for a role
1775
- */
1776
- positive_item_type_permissions: {
1777
- item_type?: ItemTypeIdentity | null;
1778
- workflow?: WorkflowIdentity | null;
1779
- on_stage?: null | string;
1780
- to_stage?: null | string;
1781
- environment: EnvironmentIdentity;
1782
- /**
1783
- * Permitted action
1784
- */
1785
- action:
1786
- | 'all'
1787
- | 'read'
1788
- | 'update'
1789
- | 'create'
1790
- | 'duplicate'
1791
- | 'delete'
1792
- | 'publish'
1793
- | 'edit_creator'
1794
- | 'take_over'
1795
- | 'move_to_stage';
1796
- /**
1797
- * Permitted creator
1798
- */
1799
- on_creator?: 'anyone' | 'self' | 'role' | null;
1800
- /**
1801
- * Permitted content scope
1802
- */
1803
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
1804
- /**
1805
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
1806
- */
1807
- locale?: string | null;
1808
- }[];
1854
+ * Allowed actions on a model (or all) for a role.
1855
+ *
1856
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
1857
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
1858
+ * - 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.
1859
+ */
1860
+ positive_item_type_permissions: (
1861
+ | RoleItemTypePermissionAll
1862
+ | RoleItemTypePermissionRead
1863
+ | RoleItemTypePermissionCreate
1864
+ | RoleItemTypePermissionUpdateOrPublish
1865
+ | RoleItemTypePermissionDuplicate
1866
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
1867
+ | RoleItemTypePermissionMoveToStage
1868
+ )[];
1809
1869
  /**
1810
- * Prohibited actions on a model (or all) for a role
1870
+ * 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`).
1811
1871
  */
1812
- negative_item_type_permissions: {
1813
- item_type?: ItemTypeIdentity | null;
1814
- workflow?: WorkflowIdentity | null;
1815
- on_stage?: null | string;
1816
- to_stage?: null | string;
1817
- environment: EnvironmentIdentity;
1818
- /**
1819
- * Permitted action
1820
- */
1821
- action:
1822
- | 'all'
1823
- | 'read'
1824
- | 'update'
1825
- | 'create'
1826
- | 'duplicate'
1827
- | 'delete'
1828
- | 'publish'
1829
- | 'edit_creator'
1830
- | 'take_over'
1831
- | 'move_to_stage';
1832
- /**
1833
- * Permitted creator
1834
- */
1835
- on_creator?: 'anyone' | 'self' | 'role' | null;
1836
- /**
1837
- * Permitted content scope
1838
- */
1839
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
1840
- /**
1841
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
1842
- */
1843
- locale?: string | null;
1844
- }[];
1872
+ negative_item_type_permissions: (
1873
+ | RoleItemTypePermissionAll
1874
+ | RoleItemTypePermissionRead
1875
+ | RoleItemTypePermissionCreate
1876
+ | RoleItemTypePermissionUpdateOrPublish
1877
+ | RoleItemTypePermissionDuplicate
1878
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
1879
+ | RoleItemTypePermissionMoveToStage
1880
+ )[];
1845
1881
  /**
1846
- * Allowed actions on a model (or all) for a role
1882
+ * Allowed actions on uploads (or all) for a role.
1883
+ *
1884
+ * 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.
1847
1885
  */
1848
- positive_upload_permissions: {
1849
- environment: EnvironmentIdentity;
1850
- /**
1851
- * Permitted action
1852
- */
1853
- action:
1854
- | 'all'
1855
- | 'read'
1856
- | 'update'
1857
- | 'create'
1858
- | 'delete'
1859
- | 'edit_creator'
1860
- | 'replace_asset'
1861
- | 'move';
1862
- /**
1863
- * Permitted creator
1864
- */
1865
- on_creator?: 'anyone' | 'self' | 'role' | null;
1866
- /**
1867
- * Permitted content scope
1868
- */
1869
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
1870
- /**
1871
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
1872
- */
1873
- locale?: string | null;
1874
- upload_collection?: UploadCollectionIdentity | null;
1875
- move_to_upload_collection?: UploadCollectionIdentity | null;
1876
- }[];
1886
+ positive_upload_permissions: (
1887
+ | RoleUploadPermissionAll
1888
+ | RoleUploadPermissionUpdate
1889
+ | RoleUploadPermissionCreate
1890
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
1891
+ | RoleUploadPermissionMove
1892
+ )[];
1877
1893
  /**
1878
- * Prohibited actions on a model (or all) for a role
1894
+ * 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.
1879
1895
  */
1880
- negative_upload_permissions: {
1881
- environment: EnvironmentIdentity;
1882
- /**
1883
- * Permitted action
1884
- */
1885
- action:
1886
- | 'all'
1887
- | 'read'
1888
- | 'update'
1889
- | 'create'
1890
- | 'delete'
1891
- | 'edit_creator'
1892
- | 'replace_asset'
1893
- | 'move';
1894
- /**
1895
- * Permitted creator
1896
- */
1897
- on_creator?: 'anyone' | 'self' | 'role' | null;
1898
- /**
1899
- * Permitted content scope
1900
- */
1901
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
1902
- /**
1903
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
1904
- */
1905
- locale?: string | null;
1906
- upload_collection?: UploadCollectionIdentity | null;
1907
- move_to_upload_collection?: UploadCollectionIdentity | null;
1908
- }[];
1896
+ negative_upload_permissions: (
1897
+ | RoleUploadPermissionAll
1898
+ | RoleUploadPermissionUpdate
1899
+ | RoleUploadPermissionCreate
1900
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
1901
+ | RoleUploadPermissionMove
1902
+ )[];
1909
1903
  /**
1910
- * Allowed build triggers for a role
1904
+ * 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`.
1911
1905
  */
1912
1906
  positive_build_trigger_permissions: {
1913
1907
  build_trigger?: BuildTriggerIdentity | null;
1914
1908
  }[];
1915
1909
  /**
1916
- * Prohibited build triggers for a role
1910
+ * 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.
1917
1911
  */
1918
1912
  negative_build_trigger_permissions: {
1919
1913
  build_trigger?: BuildTriggerIdentity | null;
1920
1914
  }[];
1921
1915
  /**
1922
- * Search indexes that can be triggered by a role
1916
+ * 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`.
1923
1917
  */
1924
1918
  positive_search_index_permissions: {
1925
1919
  search_index?: SearchIndexIdentity | null;
1926
1920
  }[];
1927
1921
  /**
1928
- * Search indexes that can't be triggered by a role
1922
+ * 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.
1929
1923
  */
1930
1924
  negative_search_index_permissions: {
1931
1925
  search_index?: SearchIndexIdentity | null;
1932
1926
  }[];
1933
1927
  };
1928
+ /**
1929
+ * Item-type permission entry granting all actions on a model. Requires `localization_scope: "all"`.
1930
+ *
1931
+ * This interface was referenced by `Role`'s JSON-Schema
1932
+ * via the `definition` "item_type_permission_all".
1933
+ */
1934
+ export type RoleItemTypePermissionAll = {
1935
+ /**
1936
+ * Permitted action
1937
+ */
1938
+ action: 'all';
1939
+ environment: EnvironmentIdentity;
1940
+ /**
1941
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
1942
+ */
1943
+ item_type?: ItemTypeIdentity | null;
1944
+ /**
1945
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
1946
+ */
1947
+ workflow?: WorkflowIdentity | null;
1948
+ /**
1949
+ * Restrict to records currently on a workflow stage.
1950
+ */
1951
+ on_stage?: string | null;
1952
+ /**
1953
+ * Restrict to moves towards a specific workflow stage.
1954
+ */
1955
+ to_stage?: string | null;
1956
+ /**
1957
+ * Permitted creator
1958
+ */
1959
+ on_creator: 'anyone' | 'self' | 'role';
1960
+ /**
1961
+ * For `action: "all"` this must be `"all"`.
1962
+ */
1963
+ localization_scope: 'all';
1964
+ [k: string]: unknown;
1965
+ };
1966
+ /**
1967
+ * Item-type permission entry granting `read` on records. `localization_scope` and `locale` must be omitted (or null).
1968
+ *
1969
+ * This interface was referenced by `Role`'s JSON-Schema
1970
+ * via the `definition` "item_type_permission_read".
1971
+ */
1972
+ export type RoleItemTypePermissionRead = {
1973
+ /**
1974
+ * Permitted action
1975
+ */
1976
+ action: 'read';
1977
+ environment: EnvironmentIdentity;
1978
+ /**
1979
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
1980
+ */
1981
+ item_type?: ItemTypeIdentity | null;
1982
+ /**
1983
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
1984
+ */
1985
+ workflow?: WorkflowIdentity | null;
1986
+ /**
1987
+ * Permitted creator
1988
+ */
1989
+ on_creator: 'anyone' | 'self' | 'role';
1990
+ [k: string]: unknown;
1991
+ };
1992
+ /**
1993
+ * 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).
1994
+ *
1995
+ * This interface was referenced by `Role`'s JSON-Schema
1996
+ * via the `definition` "item_type_permission_create".
1997
+ */
1998
+ export type RoleItemTypePermissionCreate = {
1999
+ /**
2000
+ * Permitted action
2001
+ */
2002
+ action: 'create';
2003
+ environment: EnvironmentIdentity;
2004
+ /**
2005
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2006
+ */
2007
+ item_type?: ItemTypeIdentity | null;
2008
+ /**
2009
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2010
+ */
2011
+ workflow?: WorkflowIdentity | null;
2012
+ /**
2013
+ * Permitted content scope
2014
+ */
2015
+ localization_scope: 'all' | 'localized' | 'not_localized';
2016
+ /**
2017
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2018
+ */
2019
+ locale?: string | null;
2020
+ [k: string]: unknown;
2021
+ };
2022
+ /**
2023
+ * Item-type permission entry granting `update` or `publish` on records. Requires `localization_scope`; if `localization_scope: "localized"`, `locale` is also required.
2024
+ *
2025
+ * This interface was referenced by `Role`'s JSON-Schema
2026
+ * via the `definition` "item_type_permission_update_or_publish".
2027
+ */
2028
+ export type RoleItemTypePermissionUpdateOrPublish = {
2029
+ /**
2030
+ * Permitted action
2031
+ */
2032
+ action: 'update' | 'publish';
2033
+ environment: EnvironmentIdentity;
2034
+ /**
2035
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2036
+ */
2037
+ item_type?: ItemTypeIdentity | null;
2038
+ /**
2039
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2040
+ */
2041
+ workflow?: WorkflowIdentity | null;
2042
+ /**
2043
+ * Restrict to records currently on a workflow stage.
2044
+ */
2045
+ on_stage?: string | null;
2046
+ /**
2047
+ * Permitted creator
2048
+ */
2049
+ on_creator: 'anyone' | 'self' | 'role';
2050
+ /**
2051
+ * Permitted content scope
2052
+ */
2053
+ localization_scope: 'all' | 'localized' | 'not_localized';
2054
+ /**
2055
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2056
+ */
2057
+ locale?: string | null;
2058
+ [k: string]: unknown;
2059
+ };
2060
+ /**
2061
+ * Item-type permission entry granting `duplicate` on records. `on_creator`, `localization_scope` and `locale` are not applicable and must be omitted (or null).
2062
+ *
2063
+ * This interface was referenced by `Role`'s JSON-Schema
2064
+ * via the `definition` "item_type_permission_duplicate".
2065
+ */
2066
+ export type RoleItemTypePermissionDuplicate = {
2067
+ /**
2068
+ * Permitted action
2069
+ */
2070
+ action: 'duplicate';
2071
+ environment: EnvironmentIdentity;
2072
+ /**
2073
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2074
+ */
2075
+ item_type?: ItemTypeIdentity | null;
2076
+ /**
2077
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2078
+ */
2079
+ workflow?: WorkflowIdentity | null;
2080
+ /**
2081
+ * Restrict to records currently on a workflow stage.
2082
+ */
2083
+ on_stage?: string | null;
2084
+ [k: string]: unknown;
2085
+ };
2086
+ /**
2087
+ * Item-type permission entry granting `delete`, `edit_creator`, or `take_over` on records. `localization_scope` and `locale` must be omitted (or null).
2088
+ *
2089
+ * This interface was referenced by `Role`'s JSON-Schema
2090
+ * via the `definition` "item_type_permission_delete_or_edit_creator_or_take_over".
2091
+ */
2092
+ export type RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver = {
2093
+ /**
2094
+ * Permitted action
2095
+ */
2096
+ action: 'delete' | 'edit_creator' | 'take_over';
2097
+ environment: EnvironmentIdentity;
2098
+ /**
2099
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2100
+ */
2101
+ item_type?: ItemTypeIdentity | null;
2102
+ /**
2103
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2104
+ */
2105
+ workflow?: WorkflowIdentity | null;
2106
+ /**
2107
+ * Restrict to records currently on a workflow stage.
2108
+ */
2109
+ on_stage?: string | null;
2110
+ /**
2111
+ * Permitted creator
2112
+ */
2113
+ on_creator: 'anyone' | 'self' | 'role';
2114
+ [k: string]: unknown;
2115
+ };
2116
+ /**
2117
+ * Item-type permission entry granting `move_to_stage` on records. `localization_scope` and `locale` must be omitted (or null).
2118
+ *
2119
+ * This interface was referenced by `Role`'s JSON-Schema
2120
+ * via the `definition` "item_type_permission_move_to_stage".
2121
+ */
2122
+ export type RoleItemTypePermissionMoveToStage = {
2123
+ /**
2124
+ * Permitted action
2125
+ */
2126
+ action: 'move_to_stage';
2127
+ environment: EnvironmentIdentity;
2128
+ /**
2129
+ * Restricts the permission to a specific model. When `null`, the permission applies to all models.
2130
+ */
2131
+ item_type?: ItemTypeIdentity | null;
2132
+ /**
2133
+ * Restricts the permission to records associated with a specific workflow. Mutually exclusive with `item_type`.
2134
+ */
2135
+ workflow?: WorkflowIdentity | null;
2136
+ /**
2137
+ * Restrict to records currently on a workflow stage.
2138
+ */
2139
+ on_stage?: string | null;
2140
+ /**
2141
+ * Restrict to moves towards a specific workflow stage.
2142
+ */
2143
+ to_stage?: string | null;
2144
+ /**
2145
+ * Permitted creator
2146
+ */
2147
+ on_creator: 'anyone' | 'self' | 'role';
2148
+ [k: string]: unknown;
2149
+ };
2150
+ /**
2151
+ * Upload permission entry granting all actions on uploads. Requires `localization_scope: "all"`.
2152
+ *
2153
+ * This interface was referenced by `Role`'s JSON-Schema
2154
+ * via the `definition` "upload_permission_all".
2155
+ */
2156
+ export type RoleUploadPermissionAll = {
2157
+ /**
2158
+ * Permitted action
2159
+ */
2160
+ action: 'all';
2161
+ environment: EnvironmentIdentity;
2162
+ /**
2163
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2164
+ */
2165
+ upload_collection?: UploadCollectionIdentity | null;
2166
+ /**
2167
+ * Permitted creator
2168
+ */
2169
+ on_creator: 'anyone' | 'self' | 'role';
2170
+ /**
2171
+ * For `action: "all"` this must be `"all"`.
2172
+ */
2173
+ localization_scope: 'all';
2174
+ [k: string]: unknown;
2175
+ };
2176
+ /**
2177
+ * Upload permission entry granting `update` on uploads. Requires `localization_scope`; if `localization_scope: "localized"`, `locale` is also required.
2178
+ *
2179
+ * This interface was referenced by `Role`'s JSON-Schema
2180
+ * via the `definition` "upload_permission_update".
2181
+ */
2182
+ export type RoleUploadPermissionUpdate = {
2183
+ /**
2184
+ * Permitted action
2185
+ */
2186
+ action: 'update';
2187
+ environment: EnvironmentIdentity;
2188
+ /**
2189
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2190
+ */
2191
+ upload_collection?: UploadCollectionIdentity | null;
2192
+ /**
2193
+ * Permitted creator
2194
+ */
2195
+ on_creator: 'anyone' | 'self' | 'role';
2196
+ /**
2197
+ * Permitted content scope
2198
+ */
2199
+ localization_scope: 'all' | 'localized' | 'not_localized';
2200
+ /**
2201
+ * Required (non-null) when `localization_scope` is `"localized"`; must be omitted otherwise.
2202
+ */
2203
+ locale?: string | null;
2204
+ [k: string]: unknown;
2205
+ };
2206
+ /**
2207
+ * Upload permission entry granting `create` on uploads. `on_creator`, `localization_scope` and `locale` are not applicable and must be omitted (or null).
2208
+ *
2209
+ * This interface was referenced by `Role`'s JSON-Schema
2210
+ * via the `definition` "upload_permission_create".
2211
+ */
2212
+ export type RoleUploadPermissionCreate = {
2213
+ /**
2214
+ * Permitted action
2215
+ */
2216
+ action: 'create';
2217
+ environment: EnvironmentIdentity;
2218
+ /**
2219
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2220
+ */
2221
+ upload_collection?: UploadCollectionIdentity | null;
2222
+ [k: string]: unknown;
2223
+ };
2224
+ /**
2225
+ * Upload permission entry granting `read`, `delete`, `edit_creator`, or `replace_asset` on uploads. `localization_scope` and `locale` must be omitted (or null).
2226
+ *
2227
+ * This interface was referenced by `Role`'s JSON-Schema
2228
+ * via the `definition` "upload_permission_read_or_delete_or_edit_creator_or_replace_asset".
2229
+ */
2230
+ export type RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset = {
2231
+ /**
2232
+ * Permitted action
2233
+ */
2234
+ action: 'read' | 'delete' | 'edit_creator' | 'replace_asset';
2235
+ environment: EnvironmentIdentity;
2236
+ /**
2237
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2238
+ */
2239
+ upload_collection?: UploadCollectionIdentity | null;
2240
+ /**
2241
+ * Permitted creator
2242
+ */
2243
+ on_creator: 'anyone' | 'self' | 'role';
2244
+ [k: string]: unknown;
2245
+ };
2246
+ /**
2247
+ * Upload permission entry granting `move` on uploads. `localization_scope` and `locale` must be omitted (or null). `move_to_upload_collection` is only valid here.
2248
+ *
2249
+ * This interface was referenced by `Role`'s JSON-Schema
2250
+ * via the `definition` "upload_permission_move".
2251
+ */
2252
+ export type RoleUploadPermissionMove = {
2253
+ /**
2254
+ * Permitted action
2255
+ */
2256
+ action: 'move';
2257
+ environment: EnvironmentIdentity;
2258
+ /**
2259
+ * Restricts the permission to a specific upload collection. When `null`, the permission applies to all collections.
2260
+ */
2261
+ upload_collection?: UploadCollectionIdentity | null;
2262
+ /**
2263
+ * Restricts the destination upload collection of the move action. When `null`, any destination is allowed.
2264
+ */
2265
+ move_to_upload_collection?: UploadCollectionIdentity | null;
2266
+ /**
2267
+ * Permitted creator
2268
+ */
2269
+ on_creator: 'anyone' | 'self' | 'role';
2270
+ [k: string]: unknown;
2271
+ };
1934
2272
  /**
1935
2273
  * JSON API links
1936
2274
  *
@@ -1971,11 +2309,11 @@ export type RoleMeta = {
1971
2309
  */
1972
2310
  can_edit_favicon: boolean;
1973
2311
  /**
1974
- * Can change project global properties
2312
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
1975
2313
  */
1976
2314
  can_edit_site: boolean;
1977
2315
  /**
1978
- * Can create and edit models and plugins
2316
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
1979
2317
  */
1980
2318
  can_edit_schema: boolean;
1981
2319
  /**
@@ -1983,11 +2321,11 @@ export type RoleMeta = {
1983
2321
  */
1984
2322
  can_manage_menu: boolean;
1985
2323
  /**
1986
- * Can change locales, timezone and UI theme
2324
+ * 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.
1987
2325
  */
1988
2326
  can_edit_environment: boolean;
1989
2327
  /**
1990
- * Can promote environments to primary and manage maintenance mode
2328
+ * 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.
1991
2329
  */
1992
2330
  can_promote_environments: boolean;
1993
2331
  /**
@@ -2019,7 +2357,7 @@ export type RoleMeta = {
2019
2357
  */
2020
2358
  can_manage_webhooks: boolean;
2021
2359
  /**
2022
- * Can create and delete sandbox environments and promote them to primary environment
2360
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2023
2361
  */
2024
2362
  can_manage_environments: boolean;
2025
2363
  /**
@@ -2051,161 +2389,75 @@ export type RoleMeta = {
2051
2389
  */
2052
2390
  can_access_search_index_events_log: boolean;
2053
2391
  /**
2054
- * Allowed actions on a model (or all) for a role
2055
- */
2056
- positive_item_type_permissions: {
2057
- item_type?: ItemTypeIdentity | null;
2058
- workflow?: WorkflowIdentity | null;
2059
- on_stage?: null | string;
2060
- to_stage?: null | string;
2061
- environment: EnvironmentIdentity;
2062
- /**
2063
- * Permitted action
2064
- */
2065
- action:
2066
- | 'all'
2067
- | 'read'
2068
- | 'update'
2069
- | 'create'
2070
- | 'duplicate'
2071
- | 'delete'
2072
- | 'publish'
2073
- | 'edit_creator'
2074
- | 'take_over'
2075
- | 'move_to_stage';
2076
- /**
2077
- * Permitted creator
2078
- */
2079
- on_creator?: 'anyone' | 'self' | 'role' | null;
2080
- /**
2081
- * Permitted content scope
2082
- */
2083
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2084
- /**
2085
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2086
- */
2087
- locale?: string | null;
2088
- }[];
2392
+ * Allowed actions on a model (or all) for a role.
2393
+ *
2394
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2395
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2396
+ * - 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.
2397
+ */
2398
+ positive_item_type_permissions: (
2399
+ | RoleItemTypePermissionAll
2400
+ | RoleItemTypePermissionRead
2401
+ | RoleItemTypePermissionCreate
2402
+ | RoleItemTypePermissionUpdateOrPublish
2403
+ | RoleItemTypePermissionDuplicate
2404
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2405
+ | RoleItemTypePermissionMoveToStage
2406
+ )[];
2089
2407
  /**
2090
- * Prohibited actions on a model (or all) for a role
2408
+ * 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`).
2091
2409
  */
2092
- negative_item_type_permissions: {
2093
- item_type?: ItemTypeIdentity | null;
2094
- workflow?: WorkflowIdentity | null;
2095
- on_stage?: null | string;
2096
- to_stage?: null | string;
2097
- environment: EnvironmentIdentity;
2098
- /**
2099
- * Permitted action
2100
- */
2101
- action:
2102
- | 'all'
2103
- | 'read'
2104
- | 'update'
2105
- | 'create'
2106
- | 'duplicate'
2107
- | 'delete'
2108
- | 'publish'
2109
- | 'edit_creator'
2110
- | 'take_over'
2111
- | 'move_to_stage';
2112
- /**
2113
- * Permitted creator
2114
- */
2115
- on_creator?: 'anyone' | 'self' | 'role' | null;
2116
- /**
2117
- * Permitted content scope
2118
- */
2119
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2120
- /**
2121
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2122
- */
2123
- locale?: string | null;
2124
- }[];
2410
+ negative_item_type_permissions: (
2411
+ | RoleItemTypePermissionAll
2412
+ | RoleItemTypePermissionRead
2413
+ | RoleItemTypePermissionCreate
2414
+ | RoleItemTypePermissionUpdateOrPublish
2415
+ | RoleItemTypePermissionDuplicate
2416
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2417
+ | RoleItemTypePermissionMoveToStage
2418
+ )[];
2125
2419
  /**
2126
- * Allowed actions on a model (or all) for a role
2420
+ * Allowed actions on uploads (or all) for a role.
2421
+ *
2422
+ * 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.
2127
2423
  */
2128
- positive_upload_permissions: {
2129
- environment: EnvironmentIdentity;
2130
- /**
2131
- * Permitted action
2132
- */
2133
- action:
2134
- | 'all'
2135
- | 'read'
2136
- | 'update'
2137
- | 'create'
2138
- | 'delete'
2139
- | 'edit_creator'
2140
- | 'replace_asset'
2141
- | 'move';
2142
- /**
2143
- * Permitted creator
2144
- */
2145
- on_creator?: 'anyone' | 'self' | 'role' | null;
2146
- /**
2147
- * Permitted content scope
2148
- */
2149
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2150
- /**
2151
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2152
- */
2153
- locale?: string | null;
2154
- upload_collection?: UploadCollectionIdentity | null;
2155
- move_to_upload_collection?: UploadCollectionIdentity | null;
2156
- }[];
2424
+ positive_upload_permissions: (
2425
+ | RoleUploadPermissionAll
2426
+ | RoleUploadPermissionUpdate
2427
+ | RoleUploadPermissionCreate
2428
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2429
+ | RoleUploadPermissionMove
2430
+ )[];
2157
2431
  /**
2158
- * Prohibited actions on a model (or all) for a role
2432
+ * 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.
2159
2433
  */
2160
- negative_upload_permissions: {
2161
- environment: EnvironmentIdentity;
2162
- /**
2163
- * Permitted action
2164
- */
2165
- action:
2166
- | 'all'
2167
- | 'read'
2168
- | 'update'
2169
- | 'create'
2170
- | 'delete'
2171
- | 'edit_creator'
2172
- | 'replace_asset'
2173
- | 'move';
2174
- /**
2175
- * Permitted creator
2176
- */
2177
- on_creator?: 'anyone' | 'self' | 'role' | null;
2178
- /**
2179
- * Permitted content scope
2180
- */
2181
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2182
- /**
2183
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2184
- */
2185
- locale?: string | null;
2186
- upload_collection?: UploadCollectionIdentity | null;
2187
- move_to_upload_collection?: UploadCollectionIdentity | null;
2188
- }[];
2434
+ negative_upload_permissions: (
2435
+ | RoleUploadPermissionAll
2436
+ | RoleUploadPermissionUpdate
2437
+ | RoleUploadPermissionCreate
2438
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2439
+ | RoleUploadPermissionMove
2440
+ )[];
2189
2441
  /**
2190
- * Allowed build triggers for a role
2442
+ * 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`.
2191
2443
  */
2192
2444
  positive_build_trigger_permissions: {
2193
2445
  build_trigger?: BuildTriggerIdentity | null;
2194
2446
  }[];
2195
2447
  /**
2196
- * Prohibited build triggers for a role
2448
+ * 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.
2197
2449
  */
2198
2450
  negative_build_trigger_permissions: {
2199
2451
  build_trigger?: BuildTriggerIdentity | null;
2200
2452
  }[];
2201
2453
  /**
2202
- * Search indexes that can be triggered by a role
2454
+ * 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`.
2203
2455
  */
2204
2456
  positive_search_index_permissions: {
2205
2457
  search_index?: SearchIndexIdentity | null;
2206
2458
  }[];
2207
2459
  /**
2208
- * Search indexes that can't be triggered by a role
2460
+ * 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.
2209
2461
  */
2210
2462
  negative_search_index_permissions: {
2211
2463
  search_index?: SearchIndexIdentity | null;
@@ -2232,11 +2484,11 @@ export type RoleCreateSchema = {
2232
2484
  */
2233
2485
  can_edit_favicon?: boolean;
2234
2486
  /**
2235
- * Can change project global properties
2487
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2236
2488
  */
2237
2489
  can_edit_site?: boolean;
2238
2490
  /**
2239
- * Can create and edit models and plugins
2491
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2240
2492
  */
2241
2493
  can_edit_schema?: boolean;
2242
2494
  /**
@@ -2244,11 +2496,11 @@ export type RoleCreateSchema = {
2244
2496
  */
2245
2497
  can_manage_menu?: boolean;
2246
2498
  /**
2247
- * Can change locales, timezone and UI theme
2499
+ * 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.
2248
2500
  */
2249
2501
  can_edit_environment?: boolean;
2250
2502
  /**
2251
- * Can promote environments to primary and manage maintenance mode
2503
+ * 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.
2252
2504
  */
2253
2505
  can_promote_environments?: boolean;
2254
2506
  /**
@@ -2280,7 +2532,7 @@ export type RoleCreateSchema = {
2280
2532
  */
2281
2533
  can_manage_webhooks?: boolean;
2282
2534
  /**
2283
- * Can create and delete sandbox environments and promote them to primary environment
2535
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2284
2536
  */
2285
2537
  can_manage_environments?: boolean;
2286
2538
  /**
@@ -2312,161 +2564,75 @@ export type RoleCreateSchema = {
2312
2564
  */
2313
2565
  can_access_search_index_events_log?: boolean;
2314
2566
  /**
2315
- * Allowed actions on a model (or all) for a role
2316
- */
2317
- positive_item_type_permissions?: {
2318
- item_type?: ItemTypeIdentity | null;
2319
- workflow?: WorkflowIdentity | null;
2320
- on_stage?: null | string;
2321
- to_stage?: null | string;
2322
- environment: EnvironmentIdentity;
2323
- /**
2324
- * Permitted action
2325
- */
2326
- action:
2327
- | 'all'
2328
- | 'read'
2329
- | 'update'
2330
- | 'create'
2331
- | 'duplicate'
2332
- | 'delete'
2333
- | 'publish'
2334
- | 'edit_creator'
2335
- | 'take_over'
2336
- | 'move_to_stage';
2337
- /**
2338
- * Permitted creator
2339
- */
2340
- on_creator?: 'anyone' | 'self' | 'role' | null;
2341
- /**
2342
- * Permitted content scope
2343
- */
2344
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2345
- /**
2346
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2347
- */
2348
- locale?: string | null;
2349
- }[];
2567
+ * Allowed actions on a model (or all) for a role.
2568
+ *
2569
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2570
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2571
+ * - 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.
2572
+ */
2573
+ positive_item_type_permissions?: (
2574
+ | RoleItemTypePermissionAll
2575
+ | RoleItemTypePermissionRead
2576
+ | RoleItemTypePermissionCreate
2577
+ | RoleItemTypePermissionUpdateOrPublish
2578
+ | RoleItemTypePermissionDuplicate
2579
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2580
+ | RoleItemTypePermissionMoveToStage
2581
+ )[];
2350
2582
  /**
2351
- * Prohibited actions on a model (or all) for a role
2583
+ * 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`).
2352
2584
  */
2353
- negative_item_type_permissions?: {
2354
- item_type?: ItemTypeIdentity | null;
2355
- workflow?: WorkflowIdentity | null;
2356
- on_stage?: null | string;
2357
- to_stage?: null | string;
2358
- environment: EnvironmentIdentity;
2359
- /**
2360
- * Permitted action
2361
- */
2362
- action:
2363
- | 'all'
2364
- | 'read'
2365
- | 'update'
2366
- | 'create'
2367
- | 'duplicate'
2368
- | 'delete'
2369
- | 'publish'
2370
- | 'edit_creator'
2371
- | 'take_over'
2372
- | 'move_to_stage';
2373
- /**
2374
- * Permitted creator
2375
- */
2376
- on_creator?: 'anyone' | 'self' | 'role' | null;
2377
- /**
2378
- * Permitted content scope
2379
- */
2380
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2381
- /**
2382
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2383
- */
2384
- locale?: string | null;
2385
- }[];
2585
+ negative_item_type_permissions?: (
2586
+ | RoleItemTypePermissionAll
2587
+ | RoleItemTypePermissionRead
2588
+ | RoleItemTypePermissionCreate
2589
+ | RoleItemTypePermissionUpdateOrPublish
2590
+ | RoleItemTypePermissionDuplicate
2591
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2592
+ | RoleItemTypePermissionMoveToStage
2593
+ )[];
2386
2594
  /**
2387
- * Allowed actions on a model (or all) for a role
2595
+ * Allowed actions on uploads (or all) for a role.
2596
+ *
2597
+ * 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.
2388
2598
  */
2389
- positive_upload_permissions?: {
2390
- environment: EnvironmentIdentity;
2391
- /**
2392
- * Permitted action
2393
- */
2394
- action:
2395
- | 'all'
2396
- | 'read'
2397
- | 'update'
2398
- | 'create'
2399
- | 'delete'
2400
- | 'edit_creator'
2401
- | 'replace_asset'
2402
- | 'move';
2403
- /**
2404
- * Permitted creator
2405
- */
2406
- on_creator?: 'anyone' | 'self' | 'role' | null;
2407
- /**
2408
- * Permitted content scope
2409
- */
2410
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2411
- /**
2412
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2413
- */
2414
- locale?: string | null;
2415
- upload_collection?: UploadCollectionIdentity | null;
2416
- move_to_upload_collection?: UploadCollectionIdentity | null;
2417
- }[];
2599
+ positive_upload_permissions?: (
2600
+ | RoleUploadPermissionAll
2601
+ | RoleUploadPermissionUpdate
2602
+ | RoleUploadPermissionCreate
2603
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2604
+ | RoleUploadPermissionMove
2605
+ )[];
2418
2606
  /**
2419
- * Prohibited actions on a model (or all) for a role
2607
+ * 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.
2420
2608
  */
2421
- negative_upload_permissions?: {
2422
- environment: EnvironmentIdentity;
2423
- /**
2424
- * Permitted action
2425
- */
2426
- action:
2427
- | 'all'
2428
- | 'read'
2429
- | 'update'
2430
- | 'create'
2431
- | 'delete'
2432
- | 'edit_creator'
2433
- | 'replace_asset'
2434
- | 'move';
2435
- /**
2436
- * Permitted creator
2437
- */
2438
- on_creator?: 'anyone' | 'self' | 'role' | null;
2439
- /**
2440
- * Permitted content scope
2441
- */
2442
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2443
- /**
2444
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2445
- */
2446
- locale?: string | null;
2447
- upload_collection?: UploadCollectionIdentity | null;
2448
- move_to_upload_collection?: UploadCollectionIdentity | null;
2449
- }[];
2609
+ negative_upload_permissions?: (
2610
+ | RoleUploadPermissionAll
2611
+ | RoleUploadPermissionUpdate
2612
+ | RoleUploadPermissionCreate
2613
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2614
+ | RoleUploadPermissionMove
2615
+ )[];
2450
2616
  /**
2451
- * Allowed build triggers for a role
2617
+ * 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`.
2452
2618
  */
2453
2619
  positive_build_trigger_permissions?: {
2454
2620
  build_trigger?: BuildTriggerIdentity | null;
2455
2621
  }[];
2456
2622
  /**
2457
- * Prohibited build triggers for a role
2623
+ * 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.
2458
2624
  */
2459
2625
  negative_build_trigger_permissions?: {
2460
2626
  build_trigger?: BuildTriggerIdentity | null;
2461
2627
  }[];
2462
2628
  /**
2463
- * Search indexes that can be triggered by a role
2629
+ * 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`.
2464
2630
  */
2465
2631
  positive_search_index_permissions?: {
2466
2632
  search_index?: SearchIndexIdentity | null;
2467
2633
  }[];
2468
2634
  /**
2469
- * Search indexes that can't be triggered by a role
2635
+ * 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.
2470
2636
  */
2471
2637
  negative_search_index_permissions?: {
2472
2638
  search_index?: SearchIndexIdentity | null;
@@ -2514,11 +2680,11 @@ export type RoleUpdateSchema = {
2514
2680
  */
2515
2681
  can_edit_favicon?: boolean;
2516
2682
  /**
2517
- * Can change project global properties
2683
+ * Can change project-wide settings (project name, internal subdomain, frontend preview URL, deployment settings)
2518
2684
  */
2519
2685
  can_edit_site?: boolean;
2520
2686
  /**
2521
- * Can create and edit models and plugins
2687
+ * Can create and edit the project schema: models, block models, fields, fieldsets, validators, and plugins
2522
2688
  */
2523
2689
  can_edit_schema?: boolean;
2524
2690
  /**
@@ -2526,11 +2692,11 @@ export type RoleUpdateSchema = {
2526
2692
  */
2527
2693
  can_manage_menu?: boolean;
2528
2694
  /**
2529
- * Can change locales, timezone and UI theme
2695
+ * 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.
2530
2696
  */
2531
2697
  can_edit_environment?: boolean;
2532
2698
  /**
2533
- * Can promote environments to primary and manage maintenance mode
2699
+ * 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.
2534
2700
  */
2535
2701
  can_promote_environments?: boolean;
2536
2702
  /**
@@ -2562,7 +2728,7 @@ export type RoleUpdateSchema = {
2562
2728
  */
2563
2729
  can_manage_webhooks?: boolean;
2564
2730
  /**
2565
- * Can create and delete sandbox environments and promote them to primary environment
2731
+ * Can create, fork, and delete sandbox environments. Promotion to primary is gated separately by `can_promote_environments`.
2566
2732
  */
2567
2733
  can_manage_environments?: boolean;
2568
2734
  /**
@@ -2594,161 +2760,75 @@ export type RoleUpdateSchema = {
2594
2760
  */
2595
2761
  can_access_search_index_events_log?: boolean;
2596
2762
  /**
2597
- * Allowed actions on a model (or all) for a role
2598
- */
2599
- positive_item_type_permissions?: {
2600
- item_type?: ItemTypeIdentity | null;
2601
- workflow?: WorkflowIdentity | null;
2602
- on_stage?: null | string;
2603
- to_stage?: null | string;
2604
- environment: EnvironmentIdentity;
2605
- /**
2606
- * Permitted action
2607
- */
2608
- action:
2609
- | 'all'
2610
- | 'read'
2611
- | 'update'
2612
- | 'create'
2613
- | 'duplicate'
2614
- | 'delete'
2615
- | 'publish'
2616
- | 'edit_creator'
2617
- | 'take_over'
2618
- | 'move_to_stage';
2619
- /**
2620
- * Permitted creator
2621
- */
2622
- on_creator?: 'anyone' | 'self' | 'role' | null;
2623
- /**
2624
- * Permitted content scope
2625
- */
2626
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2627
- /**
2628
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2629
- */
2630
- locale?: string | null;
2631
- }[];
2763
+ * Allowed actions on a model (or all) for a role.
2764
+ *
2765
+ * The shape of each entry depends on the `action` (discriminated union). Idiomatic recipes:
2766
+ * - To grant every action, use a single `action: "all"` entry with `localization_scope: "all"`.
2767
+ * - 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.
2768
+ */
2769
+ positive_item_type_permissions?: (
2770
+ | RoleItemTypePermissionAll
2771
+ | RoleItemTypePermissionRead
2772
+ | RoleItemTypePermissionCreate
2773
+ | RoleItemTypePermissionUpdateOrPublish
2774
+ | RoleItemTypePermissionDuplicate
2775
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2776
+ | RoleItemTypePermissionMoveToStage
2777
+ )[];
2632
2778
  /**
2633
- * Prohibited actions on a model (or all) for a role
2779
+ * 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`).
2634
2780
  */
2635
- negative_item_type_permissions?: {
2636
- item_type?: ItemTypeIdentity | null;
2637
- workflow?: WorkflowIdentity | null;
2638
- on_stage?: null | string;
2639
- to_stage?: null | string;
2640
- environment: EnvironmentIdentity;
2641
- /**
2642
- * Permitted action
2643
- */
2644
- action:
2645
- | 'all'
2646
- | 'read'
2647
- | 'update'
2648
- | 'create'
2649
- | 'duplicate'
2650
- | 'delete'
2651
- | 'publish'
2652
- | 'edit_creator'
2653
- | 'take_over'
2654
- | 'move_to_stage';
2655
- /**
2656
- * Permitted creator
2657
- */
2658
- on_creator?: 'anyone' | 'self' | 'role' | null;
2659
- /**
2660
- * Permitted content scope
2661
- */
2662
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2663
- /**
2664
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2665
- */
2666
- locale?: string | null;
2667
- }[];
2781
+ negative_item_type_permissions?: (
2782
+ | RoleItemTypePermissionAll
2783
+ | RoleItemTypePermissionRead
2784
+ | RoleItemTypePermissionCreate
2785
+ | RoleItemTypePermissionUpdateOrPublish
2786
+ | RoleItemTypePermissionDuplicate
2787
+ | RoleItemTypePermissionDeleteOrEditCreatorOrTakeOver
2788
+ | RoleItemTypePermissionMoveToStage
2789
+ )[];
2668
2790
  /**
2669
- * Allowed actions on a model (or all) for a role
2791
+ * Allowed actions on uploads (or all) for a role.
2792
+ *
2793
+ * 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.
2670
2794
  */
2671
- positive_upload_permissions?: {
2672
- environment: EnvironmentIdentity;
2673
- /**
2674
- * Permitted action
2675
- */
2676
- action:
2677
- | 'all'
2678
- | 'read'
2679
- | 'update'
2680
- | 'create'
2681
- | 'delete'
2682
- | 'edit_creator'
2683
- | 'replace_asset'
2684
- | 'move';
2685
- /**
2686
- * Permitted creator
2687
- */
2688
- on_creator?: 'anyone' | 'self' | 'role' | null;
2689
- /**
2690
- * Permitted content scope
2691
- */
2692
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2693
- /**
2694
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2695
- */
2696
- locale?: string | null;
2697
- upload_collection?: UploadCollectionIdentity | null;
2698
- move_to_upload_collection?: UploadCollectionIdentity | null;
2699
- }[];
2795
+ positive_upload_permissions?: (
2796
+ | RoleUploadPermissionAll
2797
+ | RoleUploadPermissionUpdate
2798
+ | RoleUploadPermissionCreate
2799
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2800
+ | RoleUploadPermissionMove
2801
+ )[];
2700
2802
  /**
2701
- * Prohibited actions on a model (or all) for a role
2803
+ * 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.
2702
2804
  */
2703
- negative_upload_permissions?: {
2704
- environment: EnvironmentIdentity;
2705
- /**
2706
- * Permitted action
2707
- */
2708
- action:
2709
- | 'all'
2710
- | 'read'
2711
- | 'update'
2712
- | 'create'
2713
- | 'delete'
2714
- | 'edit_creator'
2715
- | 'replace_asset'
2716
- | 'move';
2717
- /**
2718
- * Permitted creator
2719
- */
2720
- on_creator?: 'anyone' | 'self' | 'role' | null;
2721
- /**
2722
- * Permitted content scope
2723
- */
2724
- localization_scope?: 'all' | 'localized' | 'not_localized' | null;
2725
- /**
2726
- * Permitted localized content in this locale. Required when `localization_scope` is `localized`
2727
- */
2728
- locale?: string | null;
2729
- upload_collection?: UploadCollectionIdentity | null;
2730
- move_to_upload_collection?: UploadCollectionIdentity | null;
2731
- }[];
2805
+ negative_upload_permissions?: (
2806
+ | RoleUploadPermissionAll
2807
+ | RoleUploadPermissionUpdate
2808
+ | RoleUploadPermissionCreate
2809
+ | RoleUploadPermissionReadOrDeleteOrEditCreatorOrReplaceAsset
2810
+ | RoleUploadPermissionMove
2811
+ )[];
2732
2812
  /**
2733
- * Allowed build triggers for a role
2813
+ * 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`.
2734
2814
  */
2735
2815
  positive_build_trigger_permissions?: {
2736
2816
  build_trigger?: BuildTriggerIdentity | null;
2737
2817
  }[];
2738
2818
  /**
2739
- * Prohibited build triggers for a role
2819
+ * 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.
2740
2820
  */
2741
2821
  negative_build_trigger_permissions?: {
2742
2822
  build_trigger?: BuildTriggerIdentity | null;
2743
2823
  }[];
2744
2824
  /**
2745
- * Search indexes that can be triggered by a role
2825
+ * 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`.
2746
2826
  */
2747
2827
  positive_search_index_permissions?: {
2748
2828
  search_index?: SearchIndexIdentity | null;
2749
2829
  }[];
2750
2830
  /**
2751
- * Search indexes that can't be triggered by a role
2831
+ * 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.
2752
2832
  */
2753
2833
  negative_search_index_permissions?: {
2754
2834
  search_index?: SearchIndexIdentity | null;
@@ -3052,7 +3132,16 @@ export type SsoUserDestroyTargetSchema = {
3052
3132
  data: SsoUser;
3053
3133
  };
3054
3134
  /**
3055
- * An API token allows access to our API. It is linked to a Role, which describes what actions can be performed.
3135
+ * An API token authenticates programmatic access to a project. Each token combines two layers of access control:
3136
+ *
3137
+ * 1. A **Role** that defines what actions are permitted (the same Role resource used for human collaborators).
3138
+ * 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.
3139
+ *
3140
+ * The token's effective capabilities are the *intersection* of the two.
3141
+ *
3142
+ * > [!PROTIP] 💡 A CDA-only token can safely reuse a write-capable Role
3143
+ * > 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.
3144
+ *
3056
3145
  *
3057
3146
  * This interface was referenced by `DatoApi`'s JSON-Schema
3058
3147
  * via the `definition` "access_token".
@@ -3075,21 +3164,24 @@ export type AccessTokenAttributes = {
3075
3164
  */
3076
3165
  name: string;
3077
3166
  /**
3078
- * The actual API token (or null if the current user has no permission to read the token)
3167
+ * 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`.
3079
3168
  */
3080
3169
  token?: null | string;
3081
3170
  /**
3082
- * Whether this API token can access the Content Delivery API published content endpoint
3171
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3083
3172
  */
3084
3173
  can_access_cda: boolean;
3085
3174
  /**
3086
- * Whether this API token can access the Content Delivery API draft content endpoint
3175
+ * 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.
3087
3176
  */
3088
3177
  can_access_cda_preview: boolean;
3089
3178
  /**
3090
3179
  * Whether this API token can access the Content Management API
3091
3180
  */
3092
3181
  can_access_cma: boolean;
3182
+ /**
3183
+ * 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.
3184
+ */
3093
3185
  hardcoded_type: null | string;
3094
3186
  /**
3095
3187
  * When this API token was last used to access the Content Management API
@@ -3151,11 +3243,11 @@ export type AccessTokenCreateSchema = {
3151
3243
  */
3152
3244
  name: string;
3153
3245
  /**
3154
- * Whether this API token can access the Content Delivery API published content endpoint
3246
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3155
3247
  */
3156
3248
  can_access_cda: boolean;
3157
3249
  /**
3158
- * Whether this API token can access the Content Delivery API draft content endpoint
3250
+ * 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.
3159
3251
  */
3160
3252
  can_access_cda_preview: boolean;
3161
3253
  /**
@@ -3194,11 +3286,11 @@ export type AccessTokenUpdateSchema = {
3194
3286
  */
3195
3287
  name: string;
3196
3288
  /**
3197
- * Whether this API token can access the Content Delivery API published content endpoint
3289
+ * Whether this API token can call the Content Delivery API (`graphql.datocms.com`) to fetch **published** content.
3198
3290
  */
3199
3291
  can_access_cda: boolean;
3200
3292
  /**
3201
- * Whether this API token can access the Content Delivery API draft content endpoint
3293
+ * 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.
3202
3294
  */
3203
3295
  can_access_cda_preview: boolean;
3204
3296
  /**