Authorization

ODD's RBAC model — permissions, policies, roles, owners, and user-owner association — centred on the user-identity / owner-identity bridge that resolves who-can-do-what.

Authorization in ODD Platform is RBAC over a fixed permission catalogue: the platform defines a set of permissions (one per state-changing action), operators bundle permissions into Roles, attach Roles to Owners or to authentication-mode-derived groups, and the runtime checks the caller's effective permissions on every request that touches a permission-gated endpoint. The model is documented in this section across five reading surfaces; the order below is the operator's mental-model build order.

The crucial distinction this section repeatedly returns to: user identity is separate from owner identity. A user is who signed in (an OIDC / LDAP / S2S principal); an Owner is a catalog-side row that a user binds to. Permissions can be granted through either side — Owner roles override the user's auth-mode-derived role once a binding is in place — and most of the operator-trust nuances on this page boil down to that bridge.

Three load-bearing operator-trust facts

Before reading the per-page deep dives, internalise these three platform-wide facts. They are not derivable from any single page if you don't know to look for them, and each shapes operator decisions across every page in this section.

  • Read access on Management catalogs is collaborative by design. Every GET /api/* Management endpoint (Owners, Datasources, Collectors, Namespaces, Titles, Owner-Association requests, Policies, Roles, IdP providers) falls through to the platform's "any authenticated user" rule. There is no OWNER_READ, NAMESPACE_READ, or equivalent permission to withhold — read-side authorization is enforced at the deployment perimeter, not by the platform's RBAC. See the warning admonition at the end of Permissions → Management permissions.

  • Token rotation is immediate. COLLECTOR_TOKEN_REGENERATE and DATA_SOURCE_TOKEN_REGENERATE invalidate the prior token at the moment the rotation call returns — there is no grace period. The collector process or push client must be redeployed with the new token before its existing ingestion stops. Holders of either permission are operationally privileged in a way the permission name does not communicate. See the operational caveats on the Permissions page.

  • DIRECT_OWNER_SYNC composes with the freeSolo Owner-name input. A user holding DIRECT_OWNER_SYNC who submits the home-page Owner-association form with an owner name that does not exist in the catalog mints a new Owner row and self-binds to it in a single POST — bypassing the request-then-approve workflow and the existing-name discipline. Grant DIRECT_OWNER_SYNC only to principals you also trust to mint Owner names (typically a service identity, not an end-user policy). See Permissions → DIRECT_OWNER_SYNC.

How the UI surfaces missing permissions

The UI's permission-aware components use a hide-not-disable convention: affordances the signed-in user does not have permission to use are removed from the DOM entirely, with no greyed-out button, no tooltip, no admin-contact CTA. A user who expects to see an action button or a Management tab but does not should ask their administrator which permission is missing — there is no platform-side signal that a button is hidden because of permission posture as opposed to feature absence.

This convention applies platform-wide to every permission-gated affordance (mutation buttons on data-entity headers, Policy / Role / Owner editors, Management tab visibility, ownership-relation create / delete, attachment upload, etc.). Operators introducing new users to the platform should mention the convention so users have the right mental model when something they expect is missing.

The pages below are listed in the order an operator builds the authorization model mentally — start at Permissions (the catalogue of operations), compose them into Roles (the bundles), assign them via Policies (the conditional rules), bind to Owners (the catalog identities), and finally close the loop with User-owner association (the workflow that ties signed-in users to Owners).

  • Permissions — the full enumeration of permission keys grouped by resource, the two-endpoint read surface, and the read-collaborative posture on Management catalogs.

  • Roles — how Roles bundle Permissions, the User-role vs Owner-role distinction, and the Owner-role-supersedes-User-role precedence.

  • Policies — the JSON-schema policy structure, the per-resource condition fields, the Title-vocabulary caveat for :owner:title conditions, and the authorization hot-path performance characteristics.

  • Owners — what an Owner is, the three creation paths, Owner-name accretion guidance, role attachment, and the lifecycle / API caveats (audit silence, GET ungated, three service-tier side-doors, destructive PUT semantic).

  • User-owner association — the three write-paths for binding a user to an Owner (user self-request, DIRECT_OWNER_SYNC auto-approve, admin direct-bind), the operator workflow on Management → Associations, and the cross-mode user-name collision caveat.

  • Admin promotion across providers — how each auth mode and OAuth provider determines which user becomes ADMIN.

  • Audit trail scope — what the platform audits and (importantly) what it does not, including the schema-rooted absence of an audit trail for Policy / Role / Owner / Term / Namespace / Datasource / Collector lifecycle changes.

Where to next

  • Enable security — the parent section covering the two authentication surfaces (UI + ingestion) and the deployment matrix.

  • Authentication — the auth-mode configuration (DISABLED / LOGIN_FORM / OAUTH2 / LDAP / S2S) that produces the user identity Authorization gates against.

  • Management → Associations — the operator surface where User-Owner associations are reviewed, approved, and directly created.

Last updated