> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genesiscomputing.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RBAC in Genesis: A Practical Guide

> How Role-Based Access Control works in Genesis—agents, users, tools, secrets, and connections

This guide explains how Role-Based Access Control (RBAC) works in Genesis. Everything described here is done through the **Web UI** (Config, chat) or through **actions and tool use** in agent chats. It is written from the foundational mental model that **agents like Eve or Adam are engineers**: they use tools, create and use connections and secrets, and act on behalf of (or alongside) human users. Understanding who can do what—and how agents fit in—makes it easier to configure access and troubleshoot permission issues.

## Foundational Mental Model: Agents as Engineers

In Genesis:

* **Agents** (Eve, Adam, etc.) are first-class in RBAC. Each agent has an identity (agent ID) and can be assigned **roles**, just like human users.
* **Users** are people who log in (e.g. via Azure AD, OAuth). They also have roles.
* **Tools** are the capabilities agents use when you chat with them (e.g. querying a database, running Git operations, managing access). Which tools an agent can use can be restricted by role.
* **Secrets** store sensitive values (passwords, API keys). Access is determined by ownership, admin status, or role-based policies. You manage them in **Config → Secrets** (if you have access).
* **Connections** are named configurations for external systems (GitHub, Snowflake, Postgres, etc.). You create and edit them in **Config → Connections**. Credentials in connections are stored as secrets; who can *use* a connection depends on who has access to those secrets (and, for database connections added in chat, on an explicit allowed-agent list).

When you chat with an agent, **you** are the requester and the **agent** is the one performing actions. Genesis checks both identities, but by default it is permissive about how they combine: a capability runs when **either** your role or the agent's role allows it. Deployments that need both to allow it set `security.tool_auth_mode` to `intersection` — see [Capability authorization modes](#capability-authorization-modes). When an agent uses a connection's credentials, that is checked against the agent's identity and roles, and against yours as well when the connection requires a double key.

Deployment-level staff access gates are separate from RBAC roles and permissions; configure them in [Advanced Settings — Genesis Staff resolution](/docs/Setup/Advanced-Settings#genesis-staff-resolution).

## Hosted identity links

Hosted authentication separates **assertion verification** from **application
authorization**. A valid signed assertion identifies a subject, but hosted
access is admitted only when that subject has an active explicit identity link
for the configured tenant and installation. A subject from another tenant or
installation, or a subject whose link was revoked, cannot use the assertion to
bypass Genesis authorization.

The hosted identity lifecycle has three API operations:

* `POST /api/hosted-identities/initial-admin` creates the sole initial admin and
  requires the `hosted.identity.bootstrap` management capability.
* `POST /api/hosted-identities/invitations` creates an ordinary hosted user and
  requires the caller's `manage_users` permission.
* `POST /api/hosted-identities/{binding_id}/revoke` revokes one exact link;
  ordinary callers need `manage_users`, while emergency management callers need
  `hosted.identity.emergency_revoke`.

The resulting Genesis user receives the role associated with the binding kind:
the initial-admin binding receives `admin`, and an invitation receives `user`.
Hosted users are excluded from startup's default-role backfill, so roles remain
owned by the identity-link lifecycle rather than by a separate startup grant.
Revocation therefore removes the active hosted access path without leaving an
unowned role behind. See the [hosted identity lifecycle
API](/docs/Genesis-API/API-Reference#hosted-identity-lifecycle) for request
fields and response states.

## Establishing or recovering an administrator

Genesis has no shared admin key: a signed-in user cannot make themselves an
administrator. Administrators come from one of these paths.

* **Default roles for new users.** A brand-new user receives the roles in
  `rbac.default_roles`, or the list saved under **Default Roles for New Users**.
  The shipped default is `admin` and `user`, so on an unconfigured install the
  first person to sign in is an administrator. If the saved list cannot be read
  when a user is created, that user receives no roles rather than the shipped
  default.
* **An existing administrator** grants the `admin` role in **Config → Users**.
* **Hosted installs** create their first administrator with
  `POST /api/hosted-identities/initial-admin`, described above.
* **Operator recovery**, when no administrator can sign in. This needs access to
  the deployment's infrastructure, not to Genesis:

  * *Self-hosted (Kubernetes, Docker, Railway):* the person signs in once, then an
    operator runs
    `python -m genesis_bots.apps.cli grant-admin --email <person> --actor-email <operator>`
    inside the Genesis container, from the app directory (`/app` in the standard
    image), and restarts the service. The grant is recorded in the admin audit
    log with source `cli`. If several users share the email, the command lists
    them; rerun it with `--user-id`. It refuses a user whose roles SCIM manages:
    grant admin through the identity provider's group mapping instead, because
    the next SCIM sync resets that user's roles to what the provider grants.
  * *Snowflake (SPCS):* insert the user's `admin` row into the deployment's
    `CASBIN_RULE` table, then suspend and resume the service. The restart briefly
    interrupts every user, and a direct table write records no Genesis audit
    event.
  * *Databricks Apps:* there is no shell into the App. With verified sign-in
    (`PROXY_AUTH_DATABRICKS_VERIFY_TOKEN=true`), its first administrator is seated
    at sign-in; see [first administrator for Databricks Apps](/docs/deployments/Databricks/Genesis-On-Databricks#first-administrator).
    You can also map a workspace group to `admin` in `GENESIS_GROUP_ROLE_MAPPING`;
    members receive the role when they sign in.
    Service principals are admitted as users only through the administrator-configured
    test-identity exception; see [Databricks App test identities](/docs/deployments/Databricks/Genesis-On-Databricks#automated-test-identities).

  Running servers hold role assignments in memory, so only the restart
  guarantees that the self-hosted or Snowflake grant takes effect.

## Admin vs User: What Each Can Do

Genesis has two built-in roles: **admin** and **user**. Admins can create custom roles (with a subset of permissions) in **Config → Users** (Roles tab) or by asking an agent in chat.

### Admin

Admins have full access. They can:

* **Access every agent** (including Eve). No per-agent configuration is required.
* **Manage users and roles** in **Config → Users**: assign and revoke roles, create custom roles, set default roles for new users, and configure which roles can access which agents and which capabilities (tools).
* **Manage agents** in **Config → Agents**: create, update, and delete agents.
* **Create agents without global edit access** with `create_agents`. The creator
  can then maintain the agents they create or import, but cannot edit unrelated
  agents unless a role grants management for those specific agent IDs.
* **Review agent learning candidates** in **Pulse** when granted `manage_agent_learning`: accept or dismiss lessons proposed for agents. Reading the learning queue, adoption history, and improvement report only requires `access_pulse_panel`.
* **Manage managed artifacts** when granted `manage_skills`, `manage_flows`, or `manage_apps`: register Git sources, sync Skills/Flows/Apps, and open workspace MR/PR flows from each library page. Binding logical dependencies after sync uses `manage_git`.
* **Manage unified Git sources** when granted `manage_repos`: register one repository with multiple `scan_types_enabled` values (including `documents` for Knowledge Base feeds), sync, and delete multi-type sources from **Config → Managed Sources**, **Document Indexes → Sync from Git**, or `GET`/`POST`/`PATCH`/`DELETE` `/api/managed-sources`. Holders of `manage_repos` can also use the legacy per-type repository routes; multi-type deletes must go through the unified API. On upgrade, Genesis backfills `manage_repos` once for the built-in `admin` role and for custom roles that already have all of `manage_skills`, `manage_flows`, `manage_apps`, and `manage_git`.
* **Manage connections** in **Config → Connections**: create, update, and delete connections and their credentials.
* **Manage secrets** in **Config → Secrets**: create, update, delete, and view all secrets. Only admins can update system-owned secrets.
* **Edit the global Context Graph token cap** in **Digital Twin → Spend** or through the `SET_USAGE_BUDGET` lineage action. This requires `access_config_panel`; the built-in `admin` role has it, and a custom role must be granted it explicitly.
* **Use the scheduler** and the **Pulse** (monitoring) panel.
* **View all chat threads** and **view all secrets** for auditing.

Admins typically configure the system and retain full access for troubleshooting and governance.

### Environment snapshot export

Admins and custom roles can download the scrubbed environment snapshot from
**Config → Support and Enhancements → Other diagnostics** only when the role has
all four permissions required by the export endpoint: `access_config_panel`,
`view_agents`, `view_users`, and `view_connections`. The UI hides the export
control unless all four are present, and the API enforces the same AND gate, so
having only one or some of these permissions is not sufficient.

The export is diagnostic inventory, not a backup. It contains no credentials or
customer records, but it can contain operator-chosen names and non-secret
deployment values such as hostnames and account identifiers. See the [API
Reference](/docs/Genesis-API/API-Reference#post-apiadminenvironment-snapshotexport)
for the archive file set and redaction contract.

Each attempt is recorded in the admin audit log with target type
`environment_snapshot`. Successful attempts use action
`environment_snapshot.exported`; failed collection attempts use
`environment_snapshot.export_failed`. The event includes the export ID and
coarse status/count metadata, not the archive contents.

### Access Preview

Admins can use **Access Preview** on **Config → Users & Roles** to evaluate the
product as one or more non-admin roles (or as another user's role set) without
changing persisted role assignments. Preview is request-scoped: API permission
checks, connection visibility, and sidebar access follow the selected preview
roles, but your real user ID remains the actor for audit and administration.
The built-in `admin` role cannot be included in a preview.

From the UI, open the **Access Preview** tab or, on the **Users** tab, open a
row's actions menu (⋮) and choose **Preview Access** to load that user's roles
into the selection (`admin` is excluded). Select roles (or a user to copy roles
from), then click **Start Preview**. Use **Exit Preview** on the tab or the
header control to return to your normal admin permissions. For programmatic
checks, an admin may send
`X-Genesis-Access-Preview-Roles` (JSON array of role names, or comma-separated)
and optional `X-Genesis-Access-Preview-Label` on authenticated requests; the
server ignores preview headers from non-admin callers and drops invalid or
`admin` roles.

While preview is active, `GET /api/rbac/me/permissions` and **Config → Users
& Roles → Current User Info** reflect the preview role set: `roles` and
`permissions` match the selected preview roles, and `is_admin` is `false`
(because the built-in `admin` role cannot be previewed). Your persisted
`user_id` is unchanged.

<Tip>
  In **Config → Users & Roles → Roles**, the **Default Roles for New Users**
  list accepts only roles that currently exist and excludes the built-in
  `admin` role. That UI restriction does not affect the built-in fallback:
  unless an admin UI override or `rbac.default_roles` sets another list, new
  users receive `admin` and `user` by default. See
  [Users and Roles](/docs/Setup/Users-And-Roles) for fallback order and
  configuration details. If an older saved
  configuration still references a deleted role, Genesis ignores that stale
  entry. To delete a role that is still configured as a default for new users,
  first remove it from the default-role list.
</Tip>

### User (regular user)

The built-in `user` role is not blank. It starts with a set of common
workspace and creation permissions, and then still depends on **agent
access** and **tool access** for sensitive actions:

* **Built-in `user` role defaults**: `view_apps`, `view_context_graph`, `view_deployments`, `view_flows`, `create_app`, `import_app`, `view_git`, `view_agents`, `view_skills`, `view_connections`, `view_scheduler`, `view_all_missions`, `view_sandboxes`, `use_cli_terminal`, and `ratify_source_contract`

* `ratify_source_contract` lets user-role operators seal source contracts and grade Prover
  comparisons against them; this is not an admin-only task.

* **Built-in `user` PAT permissions**: `access_pat_connections_databases`, `access_pat_connections_git`, `access_pat_connections_cloud`, `access_pat_connections_pipelines`, and `access_pat_connections_tools`

* **`use_cli_terminal`**: Allows the user to attach a real terminal to their own private Claude Code workspace from the GUI or a laptop client. It is separate from `view_sandboxes` and `manage_sandboxes`; neither sandbox permission implies it. The feature also requires the `cli_terminal.enabled` deployment setting. Because the workspace is a genuine shell and Claude Code runs without permission prompts, grant this permission deliberately.

* **Team Wiki commentary**: Users with `view_git` can list, post, and soft-delete their own Markdown comments on any Team Wiki page through the dashboard commentary API (`GET`/`POST`/`DELETE` `/api/wiki/v1/pages/{qualified_name}/commentary`). Agent-, Flow-, and Librarian-driven learnings still follow `wiki.write_enabled` in AppConfig; background Librarian extraction also requires `wiki.librarian_enabled` (see [Advanced Settings → Team Wiki / Librarian settings](/docs/Setup/Advanced-Settings#team-wiki--librarian-settings)).

* **`wiki_author` (non-default)**: Optional permission retained for legacy role grants. It is not included in built-in role defaults and is no longer required for dashboard wiki commentary.

* **Agent access** is not automatic. An admin (in **Config → Users**) assigns the user to a role and configures that role to have access to specific agents (e.g. the Data Agent and Report Agent). If nothing is configured, non-Eve agents may still be accessible by default in some setups; **Eve is admin-only** by design.

* If an existing built-in `user` role already has agent grants from before Adam was seeded, startup adds access to Adam once. An administrator can revoke that grant afterward; later startups do not restore it.

* **Tool access**: by default, a role can use all capabilities except those an admin has globally disabled (for example, the high-risk or coding-agent tool families). An admin can restrict a role so it can use only the capabilities explicitly granted to that role.

* **Secrets**: a user can create secrets they **own** (e.g. in Config → Secrets, if they have access). They can **use** a secret if they own it, or if it's system/shared, or if they're admin, or if their role has been granted access to that secret. They **cannot** update or delete system-owned secrets; only admins can.

* **Connections**: creating or editing shared connections in the UI requires the **manage\_all\_connections** permission (admins or a custom role with that permission). PAT-class saved connection modes (`pat`, `api_token`, `api_key`) also require the matching `access_pat_connections_<category>` permission for the connector category (`databases`, `git`, `cloud`, `pipelines`, `tools`) when you create, update, or test them. Roles without a category's PAT permission can still use OAuth-based connection modes where available; token-only connectors in that category stay unavailable until an admin enables the capability. *Using* a connection is governed by secret access and, for database connections created in chat, by the allowed-agent list.

<Tip>
  Genesis currently includes all five category-scoped PAT permissions in the
  built-in `user` role. For brand-new custom roles, the Create Role modal
  seeds those permissions from
  `rbac.default_pat_capability_for_new_roles.databases`, `.git`, `.cloud`,
  `.pipelines`, and `.tools` in
  [Advanced Settings](/docs/Setup/Advanced-Settings).
</Tip>

So: **admin** = full control via the UI and any agent; **user** = default access to common workspaces plus only the agents, capabilities, and secrets that have been granted through roles and policies.

### SCIM-provisioned users

If your deployment uses inbound SCIM, Genesis treats the identity provider as
the source of truth for role membership on SCIM-managed human users. In
**Config -> Users**, those rows are labeled `Managed by SCIM`; inactive
provisioned users show `Managed by SCIM (inactive)`. Manage their Genesis roles
by updating the IdP group membership or the SCIM group-role mapping, not by
editing the role chips in the UI.

Outside a Databricks App, when `GENESIS_SCIM_REQUIRE_PROVISIONED_USERS=true`,
Genesis also limits sign-in to active SCIM-provisioned users and blocks manual
role edits for SCIM-managed accounts. When the same person later signs in via
OIDC, Genesis can promote the pre-provisioned SCIM placeholder row to the real
login identity by matching email so the user keeps one canonical Genesis
account. On Databricks Apps, SCIM admission is ignored and access is controlled
by the App's `CAN_USE` permission. See the [API reference](/docs/Genesis-API/API-Reference#scim-admin-configuration-endpoints) for details.

### OIDC group-to-role mapping (Helm-driven)

For native OIDC deployments (without SCIM), you can map identity-provider group
identifiers to Genesis roles using Helm or environment configuration. This is
the recommended pattern for Entra ID on Kubernetes when group membership should
drive Genesis roles on every login.

**Configuration options (in priority order for the mapping file):**

1. Helm `groupRoleMapping.content` — mounted at
   `/app/.genesis/config/group-role-mapping.yaml` with
   `GENESIS_GROUP_ROLE_MAPPING_FILE`
2. `GENESIS_GROUP_ROLE_MAPPING` — JSON object with the same group-id → role
   name shape (non-Helm fallback)

**Sync behavior:**

* On each login, Genesis reads group claims from the authenticated user (JWT
  `groups` for OIDC) and assigns mapped roles.
* Roles are removed when group membership is lost — but only for roles that
  appear as values in the mapping. Manually assigned roles outside the mapping
  are never removed.

**RBAC seed file:** Helm `rbacSeedPolicy.content` (or `GENESIS_RBAC_SEED_FILE`)
applies Casbin CSV policies at startup — custom roles, permissions (`p` rules),
and hierarchy (`g` rules). Use this together with group mapping when you need
custom roles (for example `abacus_user`) that inherit from built-in roles and
grant per-agent access.

With a PostgreSQL metadata database, Genesis stores RBAC policies in that
database. A fresh database gets the `casbin_rule` table during startup; concurrent
starts serialize table creation, so they can initialize against the same new
database without conflicting. Existing tables are left in place, and a migrated
database role does not need schema-creation privileges just to start. SQLite and
Snowflake metadata modes do not use the metadata database for RBAC.

See [Deploying Genesis - Azure AKS with OIDC Authentication](/docs/deployments/Azure/Genesis-On-Azure-AKS-OIDC#helm-driven-rbac) for Helm examples.

### QA Fleet service identity (automated testing)

When `GENESIS_QA_FLEET_CLIENT_ID` is set, Genesis maps verified
machine-to-machine tokens from Auth0 or the proxy auth path (matching `azp` or
`appid` on an app-only token) to a fixed service user:

| Field | Value |
| - | - |
| Subject (`sub`) | `qa-fleet` |
| Email | `qa-fleet@genesiscomputing.io` |
| Display name | `QA Fleet` |
| Role | `qa_fleet` only |

The `qa-fleet` user never receives the built-in `admin` or `user` roles and is
excluded from **Default Roles for New Users** backfill — Genesis assigns exactly
the `qa_fleet` role on create and on every subsequent login.

This identity supports the LLM config matrix QA harness and fleet probing.
Deployments that use the role seed a restricted `qa_fleet` Casbin policy. On
upgrade, an existing `config_panel` grant is replaced with `model_config` view
access so the service identity can read active chat and embedding model
configuration without configuration-panel administration; `tool:file` remains
available for blueprint artifact writes. Map the Entra or Auth0 app registration
client id to `GENESIS_QA_FLEET_CLIENT_ID` so only that M2M application can
authenticate as `qa-fleet`.

### Top-level workspace visibility

When authentication is enabled, Genesis uses dedicated top-level view
permissions to decide whether a primary workspace appears in the sidebar and
whether its route can be opened. Common examples are `view_apps`,
`view_context_graph`, `view_deployments`, `view_flows`, and
`view_scheduler`.

Scheduler is the main exception with a broader allowlist: users can open the
workspace if they have any of `access_config_panel`, `view_scheduler`, or
`manage_scheduler`.

Genesis also keeps these sidebar permissions aligned with object-scoped
access. Granting dashboard or microapp access implies `view_apps`, granting
Flow access implies `view_flows`, and existing custom roles are backfilled
with the new sidebar view permissions during rollout so previously visible
workspaces do not disappear unexpectedly.

## Agents, Tools, Secrets, and Connections

For the affected agent, connection, configuration, and Prover operations, a
permission refusal names the required permission with its admin-console label
and tells the caller to ask an administrator for it. When the refusal lists
permissions joined by “or”, any one is sufficient. A permission without an
admin-console label is shown by its ID. Relevant admin-console labels and IDs
are **Open every Configuration page, including admin-only settings**
(`access_config_panel`), **Create, edit, and delete every agent**
(`manage_agents`), and **Add, edit, and remove every data connection, including
ones other users created** (`manage_all_connections`). The source-contract
permission label and ID are listed below.

### Agents

* Agents are set up in **Config → Agents**. `manage_agents` allows creating,
  updating, and deleting every agent. `create_agents` allows creating or
  importing new agents without editing existing ones; the creator receives a
  manage grant on each agent they create or import.
* A role can receive per-agent management grants without global
  `manage_agents`. Configure the complete list through the role's agent-manage
  grants; those grants control editing, deletion, instruction reset, settings,
  skills, and knowledge-base assignments for the listed agents.
* If a creator grant is missing after creation or import, an administrator with
  `manage_users` can restore it from the agent's creator grants in the RBAC
  administration surface. Creator grants are separate from chat-access grants.
* Each agent has an **agent ID**. Agents are assigned **roles** (e.g. Eve often has the admin role so she can manage users and access).
* When an agent does something in a chat, it acts under its own identity. Access to secrets and connections is checked for that agent (and, when you're in the chat, for you). Capability (tool) access is checked for both you and the agent, and the two results are combined according to `security.tool_auth_mode` — see [Capability authorization modes](#capability-authorization-modes).
* At least one **active** agent must always hold **manage\_agents**, otherwise no agent could administer agents from chat anymore. Genesis refuses the change that would leave none — deactivating or deleting that agent, revoking the role carrying the permission, removing the permission from that role, or deleting the role. Grant **manage\_agents** to another active agent first, then repeat the change.

### Tools (agent capabilities)

* Agents only use capabilities they're allowed to use. Access is checked when a capability is used:
  * **High-risk capabilities** can be **globally disabled** by an admin; the current list includes `dbt_action`, `execute_python_code`, and `_run_sqlite_cli_commands`.
  * **Coding-agent capabilities** can also be **globally disabled** by an admin; this blocks delegated work through Claude Code, Codex, and Cortex Code until an admin re-enables those tools.
  * **Per-role tool access**: by default, a role can use all capabilities (except globally disabled ones). An admin can make a role **restricted** so it can use only the capabilities explicitly granted to that role.
  * **Fail-closed when auth is enabled**: if the tool-access check cannot complete—RBAC is unavailable, the check raises an error, or there is no user or agent principal on the request—Genesis denies the tool rather than running it. Users see an access-denied message; transient check failures suggest retrying shortly. With authentication disabled (typical local dev), the same conditions fail open so tools keep working.
* Admins configure role–agent and role–tool mappings in **Config → Users**, or by asking Eve in chat to assign roles and grant access to agents or capabilities.

#### Capability authorization modes

When a user is present, Genesis evaluates the capability against the user's role
and against the agent's role, then combines the two results according to
`security.tool_auth_mode`:

* **`union`** (the default): the capability runs if **either** role allows it. A
  user whose role does not grant a capability can therefore still reach it
  through an agent whose role does.
* **`intersection`**: the capability runs only if **both** roles allow it.

A separate setting, `security.force_double_key_on_connections`, makes every saved
connection behave as though `require_double_key` were on. It governs connections
only and does not change capability authorization, so the two settings never
override each other. `require_double_key` by itself controls access to a
connection — both its credentials and whether it is visible — and defaults to
off. A request carrying only an agent and no user is treated
differently by the connection boundaries — see [What double key means when only
one principal is
present](/docs/Security-Controls/Genesis-Agent-Security-Controls#what-double-key-means-when-only-one-principal-is-present).

A run with no user context — a scheduled job, a webhook — is authorized against
the agent's role alone in both modes, and the log line for the call records that
no user context was present.

Every decision is logged with the mode in force, the principal or principals that
satisfied the check, and what decided the outcome. These records are kept whatever
`LOG_LEVEL` the deployment runs at — raising the level does not thin the audit
trail.

### Secrets

* **Who can create**: In **Config → Secrets**, any user or agent with access can create a secret; they become the **owner** unless it's created as a system secret. System secrets are readable by those with access; only admins can update or delete them.
* **Who can use**: A user or agent can use a secret if: they are the **owner**; or it's **system** or **shared**; or they have the **admin** role; or they have a permission that grants broad secret access; or their **role** has been granted access to that specific secret (configured in Config → Users).
* **Who can update/delete**: The owner can update or delete their own secrets. Admins can update or delete any secret (including system). Shared secrets can be updated by any authenticated user. Non-owners cannot update or delete someone else's personal secrets unless they are admin.

So: **creating** a secret is possible for anyone with access to the Secrets UI; **using** it is limited by ownership, admin, permissions, or role-based access; **updating/deleting** is owner or admin (with special rules for system and shared).

### Connections

* **Saved connections (Config → Connections)**: Credentials are stored in Genesis Secrets. Who can **use** a connection is determined by secret access (ownership, admin, role grants on the connection's secrets, and double-key rules when enabled). Shared connections can list **Roles with Access** so only members of those roles see and resolve the connection.
* **Per-agent connection profiles**: Admins assign **connection profile** roles to agents from **Agents → \[agent] → Data Access** (requires `manage_users`). A profile is a reusable custom role whose **Roles with Access** bindings on saved connections define what that profile grants. An agent can hold multiple profiles; its reachable connections are the union. With no profile, the agent inherits each connection type's default. Built-in roles such as `user` cannot be profile roles. Agents with broad secret permissions (admin or view-all-secrets) can still reach connections beyond any profile until those broad roles are removed.
* **Database connections created in chat**: When an agent (e.g. Eve) adds a database connection during a conversation, that agent becomes the **owner** and specifies which other agents can use it (allowed-agent list, or all agents). Only the owner and agents on that list can use that connection.
* **Access intent (database connections)**: Saved database connections can carry `access_intent` (`unspecified`, `read_only`, or `read_modify`). This is an awareness label for agents and the Agent Center badge — it does not replace database-role or RBAC enforcement.
* **What users see in browsing APIs**: `/api/config/db-connections` and the Data Explorer connection lists only return database connections visible to the current user. Direct calls to `/api/data/...` for a connection the user cannot use return `403 Forbidden` instead of exposing metadata.
* **Pipeline source access**: Launchpad pipeline inspection and pipeline evidence use the selected repository's normal `view_git` permission and repository-level read access. Selecting a repository does not grant access to it; a user who cannot read the repository cannot inspect its files or open pinned pipeline evidence.

### Transition-contract verification and approval

Governed migration verification (compiled transition contracts) uses two RBAC permissions:

* **`view_connections`** — browse the **Migration verification** page under Data (`/data/verify/`), list correspondence rules and verification requests, compile objectives, execute contracts, and read run reports. Also browse and run the **Estate** source-contract characterization surface (`/api/estate/...`): characterize snapshots, mine candidates, compile and verify contracts, run jitter campaigns, and read ledgers and attestations. This is the same permission family as Data Explorer connection access. The built-in `user` role includes it.
* **`ratify_transition_contract`** — approve (ratify) a qualified correspondence rule: the server signs a binding as the authenticated human approver. Included in the built-in `admin` role only; grant it explicitly to custom roles when operators other than admins must sign. Chat and agent tools can propose and qualify rules but **never** ratify — the in-app approval modal and `POST /api/transition_contract/rules/{rule_hash}/ratify` are the only signing surfaces.

Ratification additionally fails closed when `auth.enabled` is `false` (every caller reads as admin, so approvals are refused), when the caller is a system or delegated identity rather than a genuinely authenticated human, or when `transition_contract.ratifier_private_key` is not configured.

### Source-contract characterization and approval

Source-estate characterization (estatechar) uses two RBAC permissions:

* **`view_connections`** — browse and run the Estate API surface: characterize estates and non-data planes, mine rule candidates, compile draft contracts, verify against fresh characterization, run jitter and clone-jitter campaigns, and read snapshots, ledgers, deviations, and attestations. The Estate nav is shown by default; it is hidden only when a deployment set `features.show_estate` to `false` (`show_estate` is then `false` on `GET /api/config/frontend`). The built-in `user` role includes `view_connections`.
* **`ratify_source_contract`** — adjudicate mined rule candidates (`accept_fact`, `endorse_policy`, or `reject`), seal draft source contracts, and change ruling-library authority (settle, ratify provisional directions, unsettle, or answer build-time ruling questions). Prover review approvals, including disposition packages, bundles, correspondence rules, consult rulings, and Action Review requests, require ordinary Prover access (`view_connections`) but not this permission: any signed-in person may approve, including their own proposals. The admin console labels this permission **Approve source contracts and manage estates**. Included in the built-in `admin` role only; grant it explicitly to custom roles when operators need the authority-changing operations above. Agents can propose and trigger characterization workflows but **never** adjudicate, seal, or settle rulings — `POST /api/estate/candidates/{candidate_id}/adjudicate`, `POST /api/estate/contracts/{contract_id}/seal`, and the ruling-library write routes under `/api/estate/rulings/...` and `/api/estate/ruling-questions/{question_id}/answer` are the human authority-changing surfaces. Browse the library with `view_connections` (`GET /api/estate/rulings`, `GET /api/estate/ruling-questions`). For Prover approval identity and audit details, see [Roles and Approvals](/docs/Genesis-Prover/Roles-And-Approvals).

Adjudication and sealing additionally fail closed when `auth.enabled` is `false` (every caller reads as admin, so approvals are refused) or when the caller is a system or delegated identity rather than a genuinely authenticated human.

### Agent action approval (CRM merges and beyond)

Irreversible actions that agents can stage but cannot authorize for themselves use one RBAC permission:

* **`approve_agent_action`** — sign off on an action an agent has staged but cannot authorize for itself, such as an irreversible CRM record merge. Required for all `/api/salesforce/merge/...`, `/api/crm/.../merge/...`, and cross-provider `/api/crm/merge/approvals` routes (preview, list, approve, and execute). Included in the built-in `admin` role only; grant it explicitly to custom roles when operators other than admins must review merges without also holding `manage_all_connections`. Grant this only to roles held by people — both approving and executing require a genuinely authenticated human, and this permission decides who that can be. List and approve operations are scoped to connections the caller can access; holding `approve_agent_action` does not grant visibility into every connection. Agents can preview and request approval through connector tools but cannot approve on behalf of a human.

Approvals additionally fail closed when `auth.enabled` is `false` or when the caller is a system or delegated identity rather than a genuinely authenticated human.

### Blueprints

* **Who owns a blueprint**: Genesis resolves blueprint ownership from `blueprint_manifest.yaml`. It checks the top-level `created_by` field first, then falls back to legacy `blueprint.created_by`.
* **Who can use it by default**: When authentication is enabled, the owner automatically passes Blueprint RBAC checks. Newly created and copied blueprints are owner-only by default until you grant additional access.
* **How access is granted**: Blueprint access is role-based and uses the Blueprint actions `view`, `edit`, `manage`, and `execute`. Grants apply only to **configured RBAC roles**—the built-in roles and any custom roles defined in **Config → Users**. Genesis rejects grant requests for unknown role names.
* **Blueprint-wide role permissions**: In addition to per-blueprint grants on `blueprint:<name>`, admins can grant a custom role `view_all_blueprints` or `manage_all_blueprints` so members get every existing and future blueprint in one action. `view_all_blueprints` grants the usable read level (`view` and `execute`) on all blueprints — matching the default per-blueprint grant on the built-in `user` role. `manage_all_blueprints` grants full control (`view`, `edit`, `manage`, and `execute`), including sharing and access management. Genesis checks ownership and per-blueprint grants first, then falls back to these role permissions — the same pattern as `view_all_missions` / `manage_all_missions`. The built-in `admin` role includes both permissions; the built-in `user` role does not include either by default.
* **Granting from the UI**: On a blueprint's access panel, choose a role from the searchable **Select a configured role** list. The **Grant** button stays disabled until you pick a matching configured role; typed search text cannot become a grant on its own.
* **What happens on rename**: Renaming a custom or remote-backed blueprint requires Blueprint `manage` access. When a rename succeeds, Genesis migrates stored Blueprint role grants from the old resource name to the new one so existing `view`, `edit`, `manage`, and `execute` access continues to apply.
* **What appears in the library**: The Blueprint Library and related listing APIs return only blueprints the caller can `view`. For visible blueprints, Genesis separately evaluates whether the caller can `manage`, `edit`, or `execute`.

### Apps, missions, and shared-role visibility

* Without explicit grants, apps stay owner-scoped by default and mission visibility follows the underlying thread access rules.
* For team-style sharing, admins can grant a custom role the `view_shared_role_resources` permission. When two users share that same role, Genesis lets them see each other's apps and mission-backed threads without adding per-app grants or thread invitations one by one.
* This is a view-only widening. It does **not** grant app `refresh`, `edit`, or `manage`, and it does **not** let teammates hide, delete, or change access on each other's threads.
* Built-in roles do **not** include `view_shared_role_resources` by default.

## Practical Flows

### Who creates a connection, and how can an agent use it?

* **Connections in Config → Connections**
  * **Creation**: An admin (or a user with **manage\_all\_connections**) creates the connection in the UI. Credentials are stored as secrets. For database connections, optionally set **Access intent** (`unspecified`, `read_only`, or `read_modify`) as an awareness label.
  * **Use by an agent**: When an agent uses that connection (e.g. to access GitHub or Snowflake), Genesis checks whether the agent (and your role, if relevant) can access the connection's secrets. Typical setup: create the connection, bind **Roles with Access** on the connection (or grant secret access on a custom role), create a **connection profile** role if you want a reusable bundle, then assign that profile to the agent on **Data Access**. Double-key and user OAuth rules still apply at runtime.

* **Database connections created in chat**
  * **Creation**: In a chat, you (or an admin) ask an agent (e.g. Eve) to add a database connection. The agent that creates it becomes the **owner** and specifies which agents are allowed to use it.
  * **Use**: Only the **owner** and agents on the allowed list (or all agents, if configured that way) can use that connection.

Genesis initializes the RBAC/user subsystem deliberately when the server
starts. If that initialization fails, user-scoped connection checks continue
with the per-connection allowed-user lists and fail closed for admins: the
admin-wide connection-access bypass is not applied. The server reports the
startup failure, and user-scoped [`search_data_context`](/docs/Genbot-Toolkit/Context-Tools#search_data_context)
responses include a warning so the fallback is distinguishable from a healthy
RBAC result.

### Who can create and use a secret?

* **Create**: Anyone with access to **Config → Secrets** can create a secret; they become the owner unless it's created as a system secret. Creating secrets in the UI may require the **manage\_secrets** permission if your administrator has restricted access.
* **Use**: As above—owner, system/shared, admin, or a role with access to that secret. When an agent uses a connection whose credentials are in secrets, that agent's identity is used for the check.
* **Update/delete**: Owner or admin; system secrets only by admin; shared by any authenticated user.

On Snowflake native apps, the Launchpad encryption-key checklist item is shown
only to users who can manage secrets. See [Launchpad setup checklist](/docs/Setup/Advanced-Settings#launchpad-setup-checklist)
for the deployment conditions.

### How are users given access to interact with an agent?

* **Agent access** is controlled by **role → agent** policies, not by a single "user" permission.
  1. **Assign the user to a role**: An admin goes to **Config → Users**, finds the user, and assigns a role (e.g. **user** or a custom role).
  2. **Give that role access to specific agents**: In **Config → Users**, the admin configures which agents each role can access (e.g. "user role can access the Data Agent and Report Agent"). Eve is special: the **admin** role can always access all agents; other roles need explicit access to Eve, and typically only admins are given access to Eve.
  3. If no agent-access policies are configured for the **user** role, Genesis may allow access to non-Eve agents by default (to avoid locking everyone out); Eve remains admin-only.
* So: **user gets a role → that role is granted access to specific agents → the user can open chats with those agents.** Admins do this in **Config → Users** (roles and agent access). An admin can also ask Eve in chat to assign a role to a user or to grant a role access to an agent. For chat-based user targeting, see [`rbac_action` guidance](/docs/Genbot-Toolkit/Additional-Tool-Groups#rbac-action-tools).

<Tip>
  RBAC read APIs and chat-based RBAC tooling validate identifiers before returning data. If you mistype a role or bot ID, Genesis returns a not-found error instead of an empty result, and lookups can include `Did you mean: ...?` suggestions to speed up troubleshooting. Agent-keyed RBAC routes require the exact, case-sensitive `bot_id` as returned by `GET /api/bots` — display names and case variants are not accepted.
</Tip>

## Admin audit log

Genesis persists administrative mutations in the `ADMIN_AUDIT_LOG` metadata
table (Snowflake metadata schema or local SQLite, depending on deployment).
Each row is a best-effort insert: a failed audit write is logged as a warning
but does not roll back the underlying admin action.

| Column | Description |
| - | - |
| `audit_id` | Unique event identifier. |
| `action` | Event type (see below). |
| `actor_user_id` | Principal that performed the change (user ID, bot ID, or system marker). |
| `actor_email` | Email of the acting human admin when available. |
| `target_type` | Resource class (`user`, `role`, `bot`, `connection`, `workspace_policy`, `advanced_config`, `managed_skill_source`). |
| `target_id` | Primary identifier for the target (user ID, role name, policy key, config path, and so on). |
| `details` | JSON metadata for the event (never includes secret or advanced-config values). |
| `source` | How the change was initiated (`api`, `auth`, `bot`, `cli`, `managed_sources_api`, `scim`, `slack`, or `system`). |
| `timestamp` | When the event was recorded. |

Common `action` values for RBAC and workspace policy work:

| `action` | When it is written |
| - | - |
| `role.granted` / `role.revoked` | A role is assigned to or removed from a user. |
| `role.created` / `role.updated` / `role.deleted` | Custom role lifecycle changes. |
| `role.agents_updated`, `role.agents_manage_updated`, `role.blueprints_updated`, `role.dashboards_updated`, `role.flows_updated`, `role.microapps_updated`, `role.secrets_updated`, `role.tools_updated`, `role.restricted_tools_updated` | Role assignment matrices change (agent access or management, blueprint, app, flow, secret, or tool access). |
| `bot.role_granted` / `bot.role_revoked` | A role is assigned to or removed from an agent/bot principal. |
| `user.deleted` | An admin deletes a user. |
| `workspace_policy.updated` | Workspace-wide defaults change (for example default roles for new users, default thread visibility, or global high-risk / coding-agent tool toggles). |
| `advanced_config.updated` / `advanced_config.reset` | An admin changes or resets Advanced Settings paths (path and value type only; values are not stored). |
| `connection.credential_bound` | A user's personal principal or OAuth credential is bound or rebound to a shared connection. |
| `connection.credential_revoked` | A user's personal principal or OAuth credential is explicitly revoked from a shared connection. |
| `managed_skill_source_governance_change` | An admin creates or changes a managed skill source's release or revision policy. The event targets the source ID and records the reason, old and new release refs, release modes, agent-ref policies, and resolved commit and ref details. |

Connection credential events use `target_type=connection` and set `target_id` to
`connection_type.connection_name`. Their `details` payload includes the target
user ID and `credential_kind` (`principal` or `oauth`); it never includes secret
values. The `actor_user_id` identifies the user who performed the bind or
revoke, which may differ from the target user for an administrator action.

UI and REST RBAC mutations record `source=api` with the signed-in admin as
`actor_user_id`. Chat-based [`rbac_action`](/docs/Genbot-Toolkit/Additional-Tool-Groups#rbac-action-tools)
write operations record `source=bot` with the acting bot ID as
`actor_user_id`. SCIM-provisioned changes continue to use the separate
`SCIM_AUDIT_LOG` table; they are not duplicated here. Operator grants made with
`genesis grant-admin` record `source=cli`.

Applying a role definition from a managed Git source records the role changes
with `source=managed_source`; scheduled applies use actor
`system:managed_source_auto_sync`.

Managed skill release and revision-policy changes record
`target_type=managed_skill_source` and `source=managed_sources_api`. The managed
sources panel links to the audit-log view filtered to that source.

Example query (adjust schema/database names for your environment):

```sql theme={null}
SELECT action,
       actor_user_id,
       actor_email,
       target_type,
       target_id,
       source,
       timestamp
FROM   ADMIN_AUDIT_LOG
WHERE  action LIKE 'role.%'
ORDER  BY timestamp DESC
LIMIT  100;
```

Admins can browse these rows without direct metadata-table access:

* **Dashboard:** the **Config → Admin Audit Log** page lists events with date,
  action, actor, target, and source filters, a row-detail view of the `details`
  JSON, and CSV export.
* **REST API:** `GET /api/admin/audit-log` returns a cursor-paginated list and
  accepts `since`, `until`, `action` (exact match), `action_prefix` (prefix
  match), `actor_user_id`, `target_type`, `target_id`, and `source` filters;
  `GET /api/admin/audit-log/{audit_id}` returns a single event.

Both the page and the API require the `access_config_panel` permission, held by
the built-in **admin** role. The endpoints are read-only — audit rows cannot be
created, edited, or deleted through the API. To feed an external SIEM, poll the
list endpoint with a personal access token or query the metadata table directly.

## Summary Table

| What | Admin | User (typical) |
| - | - | - |
| Access all agents | Yes | No (only agents granted to their roles) |
| Manage users/roles | Yes | No |
| Manage all agents | Yes | No |
| Create and manage owned agents | Yes | Only with `create_agents` |
| Review agent learning candidates | Yes (`manage_agent_learning`) | No (unless explicitly granted) |
| Manage connections | Yes | No (unless given a role with that permission) |
| Manage secrets | Yes | No (unless given that permission or role) |
| Create secret (owner=me) | Yes | Yes (if they have access to Config → Secrets) |
| Use secret | Any | Only if owner, or role has access, or broad secret permission |
| Use connection | Any | Only if they or their agent can access the connection's secrets (or the DB allowed-agent list) |
| Migration verification (browse/run) | Yes (`view_connections`) | Yes when role includes `view_connections` |
| Approve transition correspondence rules | Yes (`ratify_transition_contract`) | No unless explicitly granted |
| Estate source-contract (browse/run) | Yes (`view_connections`) | Yes when role includes `view_connections` |
| Adjudicate, seal, or settle rulings | Yes (`ratify_source_contract`) | No unless explicitly granted |
| Approve or execute agent-staged CRM merges | Yes (`approve_agent_action`) | No unless explicitly granted |
| Tool/capability access | All (unless high-risk or coding-agent tools are globally disabled) | All by default; can be restricted per role |
| Eve access | Yes | No (admin-only by design) |

## FAQ: Connections and credentials (Git, Databricks, Snowflake, etc.)

### Whose credentials are used when I chat with an agent (e.g. clone a repo, create a pull request (PR))?

The **effective default** connection for that tool type for the current user or role (My default, then Role default), or an **explicit** connection id when one is passed. There is no workspace-wide system default fallback. Your credentials are used when your connection is the resolved default or when you (or the agent) explicitly choose your connection (e.g. "use my GitHub" or "use connection github.alice").

### When would my (the user's) Personal Access Token (PAT) or connection be used?

When your connection is the resolved user default, when a role default you hold points at your connection, or when your connection is explicitly selected. Genesis does not silently pick "the current user's" connection when no scoped default is set.

### What's the best way to summarize how PATs work for agents?

Agents use the **scoped default** connection (user or role default) for that tool type when `connection_id` is omitted. They use a specific user's PAT only when that connection is the resolved default or when **explicitly told** to use that connection.

### We want all work in an external tool (e.g. GitHub, Jira) to show up as "Genesis." What do we do?

Create one Genesis identity (account) per tool (e.g. "Genesis" or "genesis-bot" in GitHub, Jira, the database). In Genesis, create one shared connection per tool using those credentials and set a **role default** (or instruct agents to pass the connection id explicitly). Then usage uses the Genesis PAT when that connection is the resolved default.

### In a mission or blueprint (e.g. automations), whose PAT is used—the agent's or the user who started it?

The connection the agent resolves for that tool type — typically a **role default** or an explicit connection id on the agent profile, not an implicit system-wide default. Missions run as the chosen agent; the user who started the mission is in context for ownership and access checks, but the credentials used for Git, Databricks, Snowflake, etc. are those of the connection the agent uses.

### Can we declare the connection once at mission setup (e.g. "use my Databricks" or "use my Snowflake") and have it used for the whole mission without asking again?

Yes. You declare it through the **UI and the blueprint**: when you start the mission you (or the start modal) choose which Databricks or Snowflake connection to use, or an early phase asks you and the agent saves that choice for the mission. The agent then uses that saved connection for every later step (notebooks, jobs, catalog, etc.) without asking again. Your administrator may need to enable "saving a connection choice" for that mission type so the agent can remember and reuse it.
