# Authentication > Bearer tokens, per-tenant isolation enforced in the database, and what the server does not do. ## Bearer tokens Every request carries a bearer token: ``` Authorization: Bearer qmcp_... ``` Keys are stored as SHA-256 digests. The server never holds a key in a form it could show you, so a lost key is replaced, not recovered. An unauthenticated call to `/mcp` returns `401`. There is no anonymous read path to tenant data. ## Isolation is enforced by the database, not by queries Every tenant-scoped table carries an `owner_id` and is protected by Postgres row-level security, **ENABLED and FORCED**. The application sets `app.principal_id` on the connection; the policy does the rest. This is a deliberate choice about failure modes. If isolation lived in query filters, a tool that forgot its `WHERE owner_id = ...` would return *another tenant's rows*. Under row-level security the same bug returns *nothing*. One of those is a data breach and the other is a visible malfunction. Some consequences worth knowing: - `holdout_one_shot` is unique on `(owner_id, strategy_id)`. Scoped to `strategy_id` alone, one tenant could have spent another tenant's only holdout attempt. - Family names, spec hashes and `client_request_id`s are per-tenant. Your family `btc-ma` and someone else's are unrelated. - Your trial count N is yours. It is never aggregated across tenants, and no document — including this one — can tell you what it is. Call `experiment_ledger` for your own number. ## Market data is deliberately shared Bars are the expensive resource, and OHLCV for BTC-USD is the same fact for everyone. The catalog is shared across tenants on purpose. What is *not* shared is what you did with it. A split freezes the gap policy in force when it was registered, so shared data cannot retroactively change what your registered backtest saw. ## Scopes and plan limits A key carries its principal's plan. Quotas — trials per month, universe size, holdout evaluations — are enforced server-side on every call, not in the client. See [Limits](/docs/limits). Check yours with: ``` account_status() ``` ## What the server does not implement The MCP authorization specification (revision 2026-07-28) makes OAuth **optional**: implementations using an HTTP transport *SHOULD* conform, not *MUST*. This server serves a static bearer token and has deliberately opted out of MCP authorization. That is permitted, and it is a considered choice rather than an unfinished one. Two things follow if that ever changes: - RFC 9728 Protected Resource Metadata becomes a **MUST** on the server, and clients **MUST** use it for authorization-server discovery. - The target would be **Client ID Metadata Documents**, not Dynamic Client Registration. RFC 7591 DCR is deprecated in the current revision and retained only for backwards compatibility. Adopting OAuth later would not invalidate any key already issued. ## Rotating a key ``` account_status() # shows key metadata, never the key ``` Contact support to rotate. A rotated key takes effect immediately — there is no positive cache, so a revoked key stops working on the next request rather than at the end of a TTL.