Permissions

The five permission classes in ODD Platform — data entity, term, query example, lookup table, and management — with the full enumeration of permission keys and the surfaces each one gates.

There are 5 types of permissions in ODD Platform:

  • Data entity permissions: Actions related to specific data assets, such as tables, data streams, or dashboards.

  • Term permissions: Actions concerning the management of the Business Glossary, e.g. terms and their definitions.

  • Query Example permissions: Actions for creating and managing SQL query examples linked to datasets and terms.

  • Lookup table permissions: Actions for creating and maintaining operator-managed reference tables — both the table schema and the rows stored in it.

  • Management permissions: High-level administrative actions for managing the platform's infrastructure and configuration, such as creating data sources, managing users, or defining access control rules.

This list is generated from the Permission enum in the Platform's OpenAPI spec (odd-platform-specification/components.yaml). If a new permission appears in the API but is missing from this page, or vice versa, it is a bug — please open an issue or PR.

This is the full list of permissions divided by types:

Data entity permissions

  • DATA_ENTITY_ADD_TERM. Allows adding a term to a data entity.

  • DATA_ENTITY_ADD_TO_GROUP. Allows adding a data entity to a manually created group. Operator caveat: the permission is scoped against the child entity in the URL, not the parent group — a caller with this permission against entity X can place X into any manually-created DEG in the catalog, including DEGs owned by other teams. There is no per-DEG authorisation today, and the mutation emits no Activity Feed event. See Data Entity Groups & Domains → Managing DEG Membership.

  • DATA_ENTITY_ALERT_CONFIG_UPDATE. Allows configuring alert settings for a data entity (e.g., backwards-incompatible schema change alert, failed data quality test, failed job, distribution anomaly) and the time period to disable notifications.

  • DATA_ENTITY_ALERT_RESOLVE. Allows resolving alerts for a data entity.

  • DATA_ENTITY_ATTACHMENT_MANAGE. Allows adding, deleting, and managing file attachments and links for a data entity. (See Attachments and links.)

  • DATA_ENTITY_CUSTOM_METADATA_CREATE. Allows creating custom metadata field values on a data entity, and minting new INTERNAL field rows in the deployment-wide field catalogue as a side effect of the create path. Operator caveat: the auto-create-on-miss side-channel makes this an indirect grant of catalogue-write — a caller can mint new field names visible to every other authenticated user on their next autocomplete keystroke. See Custom metadata → Known limitations.

  • DATA_ENTITY_CUSTOM_METADATA_DELETE. Allows deleting a custom metadata field value from a data entity. The catalogue row is not affected by this operation (the field remains visible in the autocomplete picker on other entities). See Custom metadata.

  • DATA_ENTITY_CUSTOM_METADATA_UPDATE. Allows editing an existing custom metadata field value on a data entity. Operator caveat: the platform's update endpoint is declared upsert* in the API spec but the underlying SQL is a pure UPDATE — issuing a PUT for a field that has not previously been assigned on the target entity silently no-ops (HTTP 200 OK, empty body, "Metadata successfully updated." toast). Pre-flight with a GET, or switch to the Create endpoint on miss. See Custom metadata → Known limitations.

  • DATA_ENTITY_DELETE_FROM_GROUP. Allows removing a data entity from a manually created group. Operator caveat: same write-collaborative posture as DATA_ENTITY_ADD_TO_GROUP — the permission is bound to the child entity in the URL, not the parent group; DELETE is silently idempotent (returns 204 on no-op without an Activity Feed event). See Data Entity Groups & Domains → Managing DEG Membership.

  • DATA_ENTITY_DELETE_TERM. Allows removing a term from a data entity.

  • DATA_ENTITY_DESCRIPTION_UPDATE. Allows editing and deleting a data entity's custom description. Operator caveat: description text is persisted verbatim with no write-time HTML sanitisation, and the Markdown renderer is configured with rehype-raw and no rehype-sanitize — raw HTML embedded in the description renders as live markup for every catalog reader. The same write-collaborative posture applies to five sibling Markdown surfaces (per-column description, term definition, Query Example body, Lookup Table cell values, Slack notification body). See Entity description → Security caveat for the operator-trust framing.

  • DATA_ENTITY_GROUP_UPDATE. Allows editing a manually created data entity group.

  • DATA_ENTITY_INTERNAL_NAME_UPDATE. Allows editing and deleting a data entity's business name. (See Business names.)

  • DATA_ENTITY_OWNERSHIP_CREATE. Allows creating ownership for a data entity.

  • DATA_ENTITY_OWNERSHIP_DELETE. Allows deleting ownership from a data entity.

  • DATA_ENTITY_OWNERSHIP_UPDATE. Allows editing the title of a data entity ownership.

  • DATA_ENTITY_STATUS_UPDATE. Allows changing the lifecycle status of a data entity (e.g., stable, deprecated, deleted, draft, unassigned). (See Data entity statuses.)

  • DATA_ENTITY_TAGS_UPDATE. Allows editing a data entity's tags. Operator caveat: this is one of four permissions through which novel tag names mint new rows in the global tag directory — granting it to rank-and-file users widens vocabulary governance beyond TAG_CREATE. See Manual Object Tagging → Known limitations and operator caveats.

  • DATASET_FIELD_ADD_TERM. Documented as: allows linking a business glossary term to a specific field within a dataset. Operator caveat — silently-misgated endpoint pair: the platform's authorization wiring crosses two endpoints at adjacent lines today. The dataset-field term-add endpoint (POST /api/datasetfields/{dataset_field_id}/terms) is enforced against DATA_ENTITY_ADD_TERM at runtime, not DATASET_FIELD_ADD_TERM — UI gates on the documented permission, so the Add-term button is enabled for DATASET_FIELD_ADD_TERM holders but the server returns 403 silently. Separately, the alert-status PUT (PUT /api/alerts/{alert_id}/status) is enforced against DATASET_FIELD_ADD_TERM rather than DATA_ENTITY_ALERT_RESOLVE — granting this permission also grants alert-resolution on any entity. See Per-column annotation → Known limitations for the wiring-bug pair and the workaround.

  • DATASET_FIELD_DELETE_TERM. Allows removing a linked business glossary term from a specific field within a dataset. See Per-column annotation.

  • DATASET_FIELD_DESCRIPTION_UPDATE. Allows editing the description of an individual dataset field. The description is rendered through the same Markdown pipeline as the entity-level description and inherits the same security caveat — see Entity description → Security caveat and Per-column annotation.

  • DATASET_FIELD_ENUMS_UPDATE. Allows editing a dataset field's enum values. Operator caveat: the endpoint behind this permission is operationally bulk-replace (despite its createEnumValue operationId) — a partial submission soft-deletes every pre-existing enum row not present in the body. See Per-column annotation → Known limitations.

  • DATASET_FIELD_INTERNAL_NAME_UPDATE. Allows editing the business name of an individual dataset field. (See Business names and Per-column annotation.)

  • DATASET_FIELD_TAGS_UPDATE. Allows adding or removing tags from an individual dataset field. Operator caveat: novel tag names mint new rows in the global tag directory through this path; submitting an empty tag list silently clears every operator-curated (INTERNAL-origin) tag on the column. The audit feed event for column-level tag changes is DATASET_FIELD_TAGS_UPDATED (full before/after payload). See Manual Object Tagging → Known limitations and operator caveats and Per-column annotation → Known limitations.

  • DATASET_TEST_RUN_SET_SEVERITY. Allows setting severity for a dataset's quality tests.

Term permissions

  • TERM_CREATE. Allows creating a new term in the business glossary.

  • TERM_DELETE. Allows deleting a term from the business glossary.

  • TERM_OWNERSHIP_CREATE. Allows creating ownership for a term.

  • TERM_OWNERSHIP_DELETE. Allows deleting ownership from a term.

  • TERM_OWNERSHIP_UPDATE. Allows editing the title of a term ownership.

  • TERM_TAGS_UPDATE. Allows editing tags for a term. Operator caveat: novel tag names mint new rows in the global tag directory through this path. No activity-feed event is emitted today when term tags change — compliance / audit workflows depending on tag-change history must instrument this path externally. See Manual Object Tagging → Known limitations and operator caveats.

  • TERM_UPDATE. Allows editing the name, namespace, and definition of a term.

Query Example permissions

  • QUERY_EXAMPLE_CREATE. Allows creating a query example.

  • QUERY_EXAMPLE_DATASET_CREATE. Allows linking a query example to a dataset.

  • QUERY_EXAMPLE_DATASET_DELETE. Allows unlinking a query example from a dataset.

  • QUERY_EXAMPLE_DELETE. Allows deleting a query example.

  • QUERY_EXAMPLE_TERM_CREATE. Allows linking a query example to a term.

  • QUERY_EXAMPLE_TERM_DELETE. Allows unlinking a query example from a term.

  • QUERY_EXAMPLE_UPDATE. Allows editing a query example.

Lookup table permissions

  • LOOKUP_TABLE_CREATE. Allows creating a lookup table.

  • LOOKUP_TABLE_DATA_CREATE. Allows adding data rows to a lookup table.

  • LOOKUP_TABLE_DATA_DELETE. Allows deleting data rows from a lookup table.

  • LOOKUP_TABLE_DATA_UPDATE. Allows editing data rows in a lookup table.

  • LOOKUP_TABLE_DEFINITION_CREATE. Allows defining the structure (columns) of a lookup table.

  • LOOKUP_TABLE_DEFINITION_DELETE. Allows deleting the structure (columns) of a lookup table.

  • LOOKUP_TABLE_DEFINITION_UPDATE. Allows modifying the structure (columns) of a lookup table.

  • LOOKUP_TABLE_DELETE. Allows deleting a lookup table.

  • LOOKUP_TABLE_UPDATE. Allows editing the name and description of a lookup table.

Management permissions

  • COLLECTOR_CREATE. Allows registering a new metadata collector.

  • COLLECTOR_DELETE. Allows deleting a collector.

  • COLLECTOR_TOKEN_REGENERATE. Allows regenerating the security token for a collector. Operational caveat: regeneration invalidates the prior token immediately — there is no grace period. The Collector process must be redeployed with the new token before existing ingestion stops.

  • COLLECTOR_UPDATE. Allows editing a collector's configuration.

  • DATA_ENTITY_GROUP_CREATE. Allows creating a new data entity group.

  • DATA_SOURCE_CREATE. Allows creating a new data source connection.

  • DATA_SOURCE_DELETE. Allows deleting a data source.

  • DATA_SOURCE_TOKEN_REGENERATE. Allows regenerating the security token for a data source. Operational caveat: regeneration invalidates the prior token immediately — there is no grace period. The push-client must be redeployed with the new token before existing ingestion stops.

  • DATA_SOURCE_UPDATE. Allows editing an existing data source's configuration.

  • DIRECT_OWNER_SYNC. Allows associating a user with an owner without an approval request. Composition caveat: when the holder submits the home-page form with an owner name that does not exist in the catalog, the platform creates the owner on the requester's behalf and immediately binds them to it — in a single POST. Grant this permission only to principals you also trust to mint owner names (typically a service identity, not an end-user policy). See User-owner association → How DIRECT_OWNER_SYNC changes the user-side flow.

  • NAMESPACE_CREATE. Allows creating a new namespace via POST /api/namespaces. Operator caveat — four sister-service side-doors: four other parent permissions (DATA_SOURCE_CREATE, DATA_SOURCE_UPDATE, TERM_CREATE, COLLECTOR_CREATE, DATA_ENTITY_GROUP_CREATE) silently mint namespace rows through their namespace_name form field. Granting any of those parent permissions is an indirect grant of namespace-creation rights. See Namespaces → Auto-create side-door for the four-vertex cluster and the operator-side mitigation.

  • NAMESPACE_DELETE. Allows soft-deleting a namespace. Operator caveat — cascade-block: the delete is blocked with CascadeDeleteException (HTTP 400, error code USR004) when any of four referent tables (live data sources, live collectors, live terms, non-deleted data entities) still references the namespace. See Namespaces → Cascade-on-delete guard for the operator workflow and the partial-unique-index reincarnation behaviour after a successful soft-delete.

  • NAMESPACE_UPDATE. Allows editing an existing namespace.

  • OWNER_ASSOCIATION_MANAGE. Allows approving or denying user-owner association requests on the Management → Associations → New requests sub-tab. Also gates visibility of the Associations Management tab itself. Does not grant the admin direct-bind affordance — that requires OWNER_RELATION_MANAGE (see below). See User-owner association → Approving incoming requests.

  • OWNER_CREATE. Allows creating a new owner entity via POST /api/owners. Note: three other service-tier code paths also mint Owner rows without consulting this permission — see Owners → Three service-tier side-doors.

  • OWNER_DELETE. Allows deleting an owner via DELETE /api/owners/{id}. The delete is gated on no remaining ownership relations, term-ownership relations, or user-Owner bindings — operators see a CascadeDeleteException if any of those are still attached.

  • OWNER_RELATION_MANAGE. Allows directly creating or removing the binding between a user and an owner — the Create association button in the Management → Associations header, and the per-row Remove on the Active associations sub-tab. Operators with this permission bypass the user-self-request and admin-approve workflow entirely. See User-owner association → Creating a binding directly and Removing an existing binding. Downstream-impact note: the binding this permission creates is the single load-bearing anchor for the /api/dataentities/my[/upstream|/downstream] lineage triplet — every regression at the binding-resolution step has cross-owner blast radius on the lineage neighbourhood; see Data Lineage → My-objects triplet for the architecture.

  • OWNER_UPDATE. Allows editing an existing owner via PUT /api/owners/{id}. Destructive-API caveat: PUT with an empty (or absent) roles array silently removes every existing role binding from the Owner — see Owners → PUT with empty roles destroys all role bindings for the safe-pattern fetch-modify-write workflow.

There is no OWNER_READ permission. GET /api/owners is reachable to any authenticated user (and anonymous under auth.type=DISABLED) — it is part of the read-collaborative posture on Management catalogs documented in the warning admonition at the bottom of this section.

  • POLICY_CREATE. Allows creating a new access policy.

  • POLICY_DELETE. Allows deleting an access policy.

  • POLICY_UPDATE. Allows editing an existing access policy.

  • ROLE_CREATE. Allows creating a new user role.

  • ROLE_DELETE. Allows deleting a user role.

  • ROLE_UPDATE. Allows editing an existing user role.

  • TAG_CREATE. Allows creating a new tag. Operator caveat: TAG_CREATE is not the only path that mints new tags — four *_TAGS_UPDATE permissions (data entity, dataset field, term) plus collector ingestion all silently create tag rows for novel names. See Manual Object Tagging → Known limitations and operator caveats.

  • TAG_DELETE. Allows deleting a tag.

  • TAG_UPDATE. Allows editing an existing tag.

Comprehensive permissions

  • ALL. Includes all permissions above.

Permission read surface (two-endpoint orchestration)

Integrators consuming the platform's permission catalogue via the API need both of the endpoints below — the two scopes are orthogonal and the API does not unify them into a single call.

Endpoint
Scope
What it returns
Example resource types

GET /api/resource/{type}/{id}/permissions

Contextual / resource-scoped

The permissions the caller holds in the named resource's context (per-entity, per-term, per-query-example).

DATA_ENTITY, TERM, QUERY_EXAMPLE

GET /api/identity/whoamiIdentity.permissions

Non-contextual / management-scope

The permissions the caller holds globally for management operations — Policy / Role / Owner / Datasource / Collector / Namespace / Tag / Lookup Table / Query Example CRUD.

(returned as a flat permission list, no resource ID)

Five categories versus four resource types

The five permission groupings on this page (Data entity / Term / Query Example / Lookup table / Management) are an operator-readable taxonomy — they correspond to where permissions appear in the Management UI and how the runtime services consume them. The PermissionResourceType enum in the OpenAPI spec has four values because LOOKUP_TABLE_* permissions are stored within the Management bucket on the read surface (the runtime treats them as non-contextual / management-scope and returns them from /api/identity/whoami, not from GET /api/resource/LOOKUP_TABLE/... — there is no LOOKUP_TABLE resource type at the API contract).

An integrator dispatching from the four-value enum gets every permission the caller holds; the five-category page taxonomy is the framing operators use when reading the catalogue.

Surfaces without per-resource permission gating today

Some read surfaces that an operator might assume are gated by a per-resource permission are reachable to any authenticated caller. The Management catalogs above (GET /api/owners, GET /api/namespaces, GET /api/datasources, …) are one such cluster — documented in the read-collaborative-posture warning above. The other cluster operators routinely meet is dataset structure / version reads:

  • GET /api/datasets/{data_entity_id}/structure — the latest schema of any dataset.

  • GET /api/datasets/{data_entity_id}/structure/{version_id} — any historical schema revision.

  • GET /api/datasets/{data_entity_id}/structure/diff?first_version_id=…&second_version_id=… — the side-by-side diff between any two revisions.

The path component {data_entity_id} is consumed by the controller but not used by the underlying query — the query filters on version_id alone. Any authenticated caller enumerating version_id integers reads any dataset's schema; under auth.type=DISABLED, anonymously. The page-side detail (and the multi-tenant operator-mitigation table) lives on Dataset schema diff → Known limitations.

Last updated