Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(coderd/database): add AI Gateway key auth lookup and last-used queries - #26505

Merged
pawbana merged 2 commits into
mainfrom
pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1
Jun 26, 2026
Merged

feat(coderd/database): add AI Gateway key auth lookup and last-used queries#26505
pawbana merged 2 commits into
mainfrom
pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1

Conversation

@pawbana

@pawbana pawbana commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Adds DB methodsGetAIGatewayKeyIDByHashedSecret and UpdateAIGatewayKeyLastUsedAt.
GetAIGatewayKeyIDByHashedSecret - returns AI Gateway key ID by hashed secret value.
UpdateAIGatewayKeyLastUsedAt - updates last used timestamp for given AI Gateway key.
Used by standalone AI Gateway for authentication and keeping track of currently used keys.

@linear-code

linear-code Bot commented Jun 18, 2026

Copy link
Copy Markdown

AIGOV-308

pawbana commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from aaa5bce to 00065d0 Compare June 23, 2026 10:48
@pawbana
pawbana marked this pull request as ready for review June 23, 2026 12:36
Comment thread coderd/database/dbauthz/dbauthz.go Outdated
}

// Authenticates a standalone AI Gateway replica by its hashed key secret, returning the key ID used to record liveness.
func (q *querier) GetAIGatewayKeyIDByHashedSecret(ctx context.Context, hashedSecret []byte) (uuid.UUID, error) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have 1 question about this function. Should it return just ID or more info (eg. prefix)?
This is used later in logger, eg WIP:

logger = logger.With(slog.F("gateway_key_id", keyID))

Maybe logging prefix would be ok? At the same time prefix could be extracted from header but maybe returning it here would be cleaner.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could return the whole row, that'd be consistent with GetProvisionerKeyByHashedSecret, no? We can also add an RBACObject() to AIGatewayKey (returning ResourceAIGatewayKey.WithID(k.ID)) and switch this to fetch(). That'd also align with the existing CRUD on this table, which already authorizes against ResourceAIGatewayKey.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRUD is a bit separate. CRUD is for managing keys by user while GetByHash + UpdateLastSeen is for system to auth and keep track of key usage.

I'm not sure why fetch() would be better here. If I understand correctly it queries object from DB then checks if caller has access to it. In Gateway keys case there is no per object check (and probably won't ever be) that could be made, either subject can access all or none.

Changed getter to GetAIGatewayKeyByHashedSecret that returns full key, kept current check format.

@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from 00065d0 to 3a82a8f Compare June 23, 2026 13:46
Comment thread coderd/database/dbauthz/dbauthz.go Outdated
Comment thread coderd/database/dbauthz/dbauthz.go Outdated
}

// Authenticates a standalone AI Gateway replica by its hashed key secret, returning the key ID used to record liveness.
func (q *querier) GetAIGatewayKeyIDByHashedSecret(ctx context.Context, hashedSecret []byte) (uuid.UUID, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could return the whole row, that'd be consistent with GetProvisionerKeyByHashedSecret, no? We can also add an RBACObject() to AIGatewayKey (returning ResourceAIGatewayKey.WithID(k.ID)) and switch this to fetch(). That'd also align with the existing CRUD on this table, which already authorizes against ResourceAIGatewayKey.

Comment thread coderd/database/dbauthz/dbauthz.go Outdated
// Records liveness for an active DRPC sessions between coderd and standalone AI Gateway.
func (q *querier) UpdateAIGatewayKeyLastUsedAt(ctx context.Context, id uuid.UUID) error {
// Standalone AI Gateway has no Coder identity. DRPC connection liveness update is a system operation.
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use ResourceAIGatewayKey?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was that Gateway keys are immutable. This kind of can be done by not adding ActionUpdate to ResourceAIGatewayKey. Then even if some subject gets full access to that resource it can't update it.
At the same time there are no API methods to update it so maybe it is a bit too much.

Changed to rbac.ResourceAIGatewayKey and updated subject permissions.

@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch 2 times, most recently from 70b1fea to 65dff84 Compare June 24, 2026 17:44
@pawbana
pawbana requested a review from Emyrk as a code owner June 25, 2026 12:16
@github-actions

Copy link
Copy Markdown
Contributor

Docs preview

📖 View docs preview for docs/reference/api/schemas.md

@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from 154ccfc to 156894e Compare June 25, 2026 12:22
@pawbana
pawbana requested a review from ssncferreira June 25, 2026 13:35
@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from 156894e to a3269ec Compare June 26, 2026 09:21

@dannykopping dannykopping left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except for the use of the system subject.

Comment thread coderd/database/dbauthz/dbauthz.go
@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from a3269ec to 4fd9fb0 Compare June 26, 2026 14:31
pawbana added 2 commits June 26, 2026 15:12
…ueries

Part of AIGOV-308.

Generated with Coder Agents.
@pawbana
pawbana force-pushed the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch from 4fd9fb0 to 36e5b2a Compare June 26, 2026 15:15

pawbana commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jun 26, 4:15 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 26, 4:16 PM UTC: @pawbana merged this pull request with Graphite.

@pawbana
pawbana merged commit 0f1e792 into main Jun 26, 2026
31 of 34 checks passed
@pawbana
pawbana deleted the pawel/aigov-308-implement-apiv2aibridgeserve-endpoint-1 branch June 26, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants