feat: exclude AI Bridge usage from AI Governance seat counting (#27280)

Under the new `ai-gateway-seat-exclusion` experiment, AI Bridge usage
stops counting toward AI Governance seats.

## Seat recording

Under the experiment, `RecordInterception` no longer records
`ai_seat_state` usage for the initiator: AI Gateway access is licensed
by the AI Governance add-on rather than per seat. This experiment is
independent of `workspace-capable-licensing` (#27279) so the two
licensing behaviors can be enabled separately. Task workspace builds
still claim AI Governance seats.

## Manual verification

Verified live on a dev deployment (provider chained to dev.coder.com's
gateway, model `gpt-5.6-luna`): with the experiment off, the first
bridge request from each identity type (admin, plain member, service
account) wrote an `ai_seat_state` row (`aibridge` reason); with it on,
requests recorded interceptions but left seat state untouched — no new
rows, and existing rows' `last_used_at` did not advance.

Part of the gateway-accounts feature.

## Stack

Part 2 of the gateway-accounts stack:

1. **#27279**: permission-based license seat counting. Behind the
`workspace-capable-licensing` experiment and gated on the AI Governance
add-on, `user_limit` counts only users the RBAC engine authorizes to
create workspaces.
2. **This PR**: stops AI Bridge usage from claiming AI Governance seats
under the new `ai-gateway-seat-exclusion` experiment.
3. ~~**#27281**: adds a `use_shared` capability precondition for
workspace ACL grants, so workspace sharing is ineffective for (and
rejected toward) users without workspace capabilities, evaluated live on
every authorization.~~ This will be done in follow-up work when we have
time to look into the performance impact.

Related but independent: **#27278** hides the Workspaces page create
CTAs for users without workspace-create permission.
This commit is contained in:
J. Scott Miller
2026-07-27 21:05:37 -05:00
committed by GitHub
parent 6c102cc3f3
commit 1ab4ed8db5
7 changed files with 95 additions and 5 deletions
+4
View File
@@ -5260,6 +5260,7 @@ const (
ExperimentNATSPubsub Experiment = "nats_pubsub" // Enables embedded NATS pubsub.
ExperimentMinimumImplicitMember Experiment = "minimum-implicit-member" // Allows organizations to deviate from the default organization-member roles, in support of Gateway Accounts.
ExperimentWorkspaceCapableLicensing Experiment = "workspace-capable-licensing" // Counts only users holding the workspace-create permission toward the license seat limit.
ExperimentAIGatewaySeatExclusion Experiment = "ai-gateway-seat-exclusion" // Excludes AI Gateway (AI Bridge) usage from AI Governance seat consumption.
ExperimentAIGatewayCostControl Experiment = "ai-gateway-cost-control" // Enables AI Gateway cost control functionality.
ExperimentChatAdvisor Experiment = "chat-advisor" // Enables the advisor tool for root agent chats.
ExperimentChatVirtualDesktop Experiment = "chat-virtual-desktop" // Enables virtual desktop and computer use provider for agents.
@@ -5287,6 +5288,8 @@ func (e Experiment) DisplayName() string {
return "Gateway Accounts (minimum implicit member)"
case ExperimentWorkspaceCapableLicensing:
return "Workspace-Capable Licensing"
case ExperimentAIGatewaySeatExclusion:
return "AI Gateway Seat Exclusion"
case ExperimentAIGatewayCostControl:
return "AI Gateway Cost Control"
case ExperimentChatAdvisor:
@@ -5313,6 +5316,7 @@ var ExperimentsKnown = Experiments{
ExperimentWorkspaceBuildUpdates,
ExperimentMinimumImplicitMember,
ExperimentWorkspaceCapableLicensing,
ExperimentAIGatewaySeatExclusion,
ExperimentAIGatewayCostControl,
ExperimentChatAdvisor,
ExperimentChatVirtualDesktop,