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

# Authentication

> OAuth connect flow, API keys, per-tool scopes, admin vs. member surface, and reconnect behavior.

Two credential types reach the same server with identical semantics:

| Credential             | Created by                                                       | Sent as                         | Lifetime                                 |
| ---------------------- | ---------------------------------------------------------------- | ------------------------------- | ---------------------------------------- |
| **OAuth access token** | Automatic, when connecting Claude/ChatGPT via the connector flow | `Authorization: Bearer <token>` | 30 days (reconnect issues a fresh token) |
| **Personal API key**   | Manually, in the app (Settings → MCP Access)                     | `X-API-KEY: <key>`              | Until revoked (optional expiry)          |

Both are stored server-side as the same kind of record: a per-user key with a **per-tool allowlist (scopes)**. Every guarantee below applies to both equally.

## Identity model

* A credential belongs to exactly **one user in one tenant/workspace**. Every tool call executes as that user.
* Reads are filtered server-side to the user's visibility: tenant → workspace → department memberships → user layer. A Member and an Admin calling the same tool can legitimately get different row counts.
* If the user is deactivated or moved to another tenant, the credential stops working immediately.

## Roles

| Role label         | Meaning                            | API effect                                                                                                                     |
| ------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **Member**         | Regular user                       | Reads scoped to own departments/user layer; shared writes may become governance proposals instead of direct writes             |
| **Company-Admin**  | Tenant administrator               | Sees all rows in the tenant; may call admin-gated tools (`agent_create`, `agent_update`, `user_create`, `data_view_create`, …) |
| **Provider-Admin** | White-label provider administrator | May write to the provider (cross-company) layer where a tool offers `scope=provider`                                           |
| **Superadmin**     | Platform operator                  | Additionally may call platform-pricing tools (`pricing_config_*`, `provider_ledger_get`)                                       |

Role gates are enforced **per tool call, server-side** — having a tool on your allowlist does not bypass its role gate.

## OAuth 2.1 connect flow

The connector flow is standard OAuth 2.1: Authorization Code + PKCE (S256), public clients via Dynamic Client Registration. Discovery documents live at `/.well-known/oauth-protected-resource` and the authorization-server metadata endpoint; MCP clients handle all of this automatically.

Key behaviors:

* **Consent screen** shows whether the requested scope set is read-only or includes write/management tools.
* **Access tokens are keys.** Each issued token is a per-user key row with the same per-tool scopes, audit log and revocation as a manual API key.
* **Token TTL is 30 days.** Auth codes are single-use and expire after 10 minutes.
* **Redirect URIs** must be `https://` (plus `http://localhost` / `http://127.0.0.1` for local development).

### First connect: full tool surface

On a genuine first connect, the token receives the **full first-party tool surface** — all reads and writes (router meta-tools excluded, see [Conventions](/api/conventions)), plus:

* per-table data write grants (`insert_<table>` / `update_<table>`) for every registered data table in your tenant, and
* the federated vertical tools your account already has (e.g. `vertical__vertical_card`).

Tools that are on the allowlist but role-gated (e.g. Superadmin pricing tools) still reject non-authorized callers.

### Reconnect: scopes are inherited

Reconnecting the same user + same connector does **not** reset scopes. The new token:

1. **Inherits the scope set of the prior active key** for that user+connector — including a deliberately reduced (e.g. read-only) set. Writes are never silently re-added.
2. **Unions in the read-only baseline**: read-only tools shipped after your first connect are auto-added on reconnect, so your surface never goes stale. Write tools are never auto-added.
3. **Deactivates the prior token** for that user+connector — reconnects never accumulate active keys.

### Per-tool toggles

In the app (Settings → MCP Access) every key/connector has a per-tool on/off matrix. A tool switched **off** is recorded as an explicit opt-out (`denied_scopes`) on manual keys, so the auto-add baseline never re-enables it behind your back. Tools not on the allowlist are rejected with a clear error (see the error table in [Conventions](/api/conventions)).

## What never travels the API

* **Secrets.** No tool returns or accepts passwords, credentials, OAuth secrets or vault contents. `user_create` sends an invite link by email instead of returning a password; third-party integrations (Composio) are connected in the app UI only; agent credential assignments (`allowed_credentials`) are app-only.
* **Cross-tenant data.** There is no tool that reads another tenant.

## Audit

Every `tools/call` is logged (tool name, status `ok | error | denied`, duration, row count, argument **keys** — never values). Denied calls are audited before rate-limiting is applied.
