Connection scope
Where an AI integration connection lives - the project, organization and user levels, the flags that offer each, how visibility unions, and the allowedScopes narrowing.
Every integration connection is placed at one scope, which decides who can use it. A connection shared into a project or an organization is one credential the whole group's agents can act on; a user connection is private to the person who made it.
| Scope | Reaches |
|---|---|
project | Everyone working in that project. |
organization | Everyone in the organization, in every project. |
user | Only the person who connected it. |
Which scopes a deployment offers
The ladder comes from two feature flags, read server-side, so a level a buyer turned off never appears in any picker.
projects.enabled | tenancy.multiTenant | Scopes offered |
|---|---|---|
| on | on | project, organization, user |
| on | off | project, user |
| off | on | organization, user |
| off | off | user |
project needs only the projects feature, because it partitions rather than shares: in an SEO product each project is a different client site with its own connection, which is as useful to a solo user as to a team. user is the floor - every deployment can keep a credential to the person who connected it.
Visibility
What a caller sees is the union for the workspace they are in: the active project's connections, the active organization's shared ones, and their own. That same union is what the agents get, so a shared connection is a shared tool.
- Losing context narrows, never widens. A request outside a project simply sees no project connections, never every project's.
- Scope is fixed at creation. To move a connection, disconnect and reconnect it.
maxInstancescounts per scope context, so a cap of1allows one in each project, one shared with the organization, and one of the user's own. The count runs inside the write, so a double-click cannot slip a second past the cap.- A sign-in scopes like any other entry. An
oauthconnection carries its scope through the authorization flow, so it can be shared with a project or an organization exactly as a pasted key can.
A shared connection still refreshes with the connector's token, and its card names them. Its own connector may remove it, and so may an organization admin - otherwise a credential whose owner has left the company could never be revoked.
Restricting an entry with allowedScopes
A catalog entry can keep itself off the levels it does not belong on. ["user"] makes an entry private however the request is shaped; ["project"] files each connection under one project. The list is intersected with the deployment's ladder, so it narrows and never widens.
An allowedScopes list that overlaps nothing this deployment offers - ["organization"] on a single-tenant app - leaves the entry connectable nowhere. The catalog logs a loud warning at boot naming the entry and the fix, and hides it from the picker rather than offering something nobody could connect.
Catalog entries
How to declare one AI integration - the AiIntegrationSpec fields, the auth axis of none, api key, OAuth sign-in and MCP headers, and a worked Google Search Console entry.
Integrations
Wire third-party analytics, support chat, and affiliate trackers in @repo/config behind a GDPR-aware cookie banner.