Skip to content

feat: add ai_gateway_coderd_keys table and related RBAC#25563

Merged
pawbana merged 12 commits into
mainfrom
pb/gateway-multi-replica-key-auth-db
Jun 2, 2026
Merged

feat: add ai_gateway_coderd_keys table and related RBAC#25563
pawbana merged 12 commits into
mainfrom
pb/gateway-multi-replica-key-auth-db

Conversation

@pawbana
Copy link
Copy Markdown
Contributor

@pawbana pawbana commented May 21, 2026

Adds table to store keys that AI Gateway standalone replicas will use for authenticating into Coderd.
Also adds RBAC and audit boilerplate.

@github-actions
Copy link
Copy Markdown

Docs preview

📖 View docs preview for docs/admin/security/audit-logs.md

Copy link
Copy Markdown
Contributor Author

pawbana commented May 21, 2026

@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 2 times, most recently from 3248cc3 to 056ea4d Compare May 21, 2026 13:30
@pawbana
Copy link
Copy Markdown
Contributor Author

pawbana commented May 21, 2026

/coder-agents-review

Copy link
Copy Markdown
Contributor

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

Well-scoped boilerplate: table schema, RBAC, audit wiring, and nothing extra. The RBAC test is comprehensive (owner-only, all three actions, explicit denials for 12 other role subjects). Audit field tracking is deliberate (ActionSecret for hashed_secret, ActionIgnore for timestamps). Migration follows established patterns.

Severity count: 1 P2, 2 P3, 3 Nit, 1 Note.

The P2 is a schema gap: key_prefix has no UNIQUE constraint. Every other prefix-based lookup column in the codebase (oauth2_provider_app_secrets.secret_prefix, oauth2_provider_app_codes.secret_prefix) enforces uniqueness because the auth flow does WHERE prefix = $1 and expects exactly one row. The future handler will either assume uniqueness (bug if duplicates exist) or iterate candidates (timing side-channel). Free to fix now on an empty table.

The PR title says "aibridge_coderd_keys" but the table is ai_gateway_coderd_keys. Every code artifact uses the latter. git log --grep=ai_gateway_coderd_keys will miss this commit.

"Boring code gets silence, and most of this earned it." (Hisoka)

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/database/migrations/000503_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000510_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000503_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000510_ai_gateway_coderd_keys.down.sql Outdated
Comment thread coderd/database/migrations/000510_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000503_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000510_ai_gateway_coderd_keys.up.sql Outdated
Comment thread coderd/database/migrations/000510_ai_gateway_coderd_keys.up.sql Outdated
@pawbana pawbana changed the title feat: add aibridge_coderd_keys table and related RBAC feat: add ai_gateway_coderd_keys table and related RBAC May 21, 2026
@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 2 times, most recently from ea066e6 to 3c2624b Compare May 21, 2026 15:57
@pawbana
Copy link
Copy Markdown
Contributor Author

pawbana commented May 21, 2026

/coder-agents-review

Copy link
Copy Markdown
Contributor

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

6 of 8 findings addressed (3c2624b), 1 acknowledged. DEREM-1 (P4) is unaddressed: the table, model, RBAC object, and audit config still have zero runtime callers. No query file, no handlers, no dbauthz integration.

This is a scaffolding PR and the finding was posted as "expected for scaffolding, noting for completeness." A brief acknowledgment (e.g., "follow-up PRs add handlers") unblocks the next review round.

🤖 This review was automatically generated with Coder Agents.

@pawbana
Copy link
Copy Markdown
Contributor Author

pawbana commented May 21, 2026

6 of 8 findings addressed (3c2624b), 1 acknowledged. DEREM-1 (P4) is unaddressed: the table, model, RBAC object, and audit config still have zero runtime callers. No query file, no handlers, no dbauthz integration.

This is a scaffolding PR and the finding was posted as "expected for scaffolding, noting for completeness." A brief acknowledgment (e.g., "follow-up PRs add handlers") unblocks the next review round.

🤖 This review was automatically generated with Coder Agents.

follow-up PRs add handlers, see WIP PRs #25564 and #25565

/coder-agents-review

Copy link
Copy Markdown
Contributor

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

All six R1 fixes verified clean by 9 reviewers. DEREM-1 deferred with linked follow-up PRs. Schema, RBAC, and audit wiring are consistent across all layers.

One new P3: the name column lacks a CHECK constraint, the same class of gap that DEREM-4 flagged on secret_prefix (and was fixed). An empty name produces an empty audit target string.

"This is the same class as DEREM-4 (empty-string acceptance on identifying column in this table). The fix for DEREM-4 hardened secret_prefix but left name unprotected." (Mafuuu)

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/database/migrations/000506_ai_gateway_coderd_keys.up.sql Outdated
@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch from 3c2624b to ca08383 Compare May 21, 2026 16:47
@pawbana
Copy link
Copy Markdown
Contributor Author

pawbana commented May 21, 2026

/coder-agents-review

Copy link
Copy Markdown
Contributor

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

All 9 findings resolved across 4 rounds. 7 fixed by the author (DEREM-2 through -7, DEREM-9), 1 accepted (DEREM-8, no expires_at, follows provisioner_keys pattern), 1 deferred with linked follow-up PRs (DEREM-1, #25564 and #25565 add handlers).

The schema is tight: three unique indexes (name, secret_prefix, hashed_secret), two CHECK constraints (secret_prefix exact length, name slug regex), COMMENT ON TABLE/COLUMN, and a down migration that documents its intentional enum retention. RBAC is owner-only for create/read/delete. Audit boilerplate marks hashed_secret as ActionSecret. All fixes addressed root causes, not symptoms.

"I tried to build a case against this and could not." (Pariston)

🤖 This review was automatically generated with Coder Agents.

@pawbana pawbana requested a review from ssncferreira May 21, 2026 17:38
@pawbana pawbana marked this pull request as ready for review May 21, 2026 17:38
@pawbana pawbana requested a review from Emyrk as a code owner May 21, 2026 17:38
@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 4 times, most recently from 79e7499 to 35bc8d3 Compare May 22, 2026 22:17
Copy link
Copy Markdown
Contributor

@ssncferreira ssncferreira left a comment

Choose a reason for hiding this comment

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

Overall LGTM 👍 just a few questions/nits.

Comment thread coderd/audit/request.go Outdated
return typed.Name
case database.AIProviderKey:
return typed.ID.String()
case database.AiGatewayCoderdKey:
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.

nit: to match other types like AIProviderKey

Suggested change
case database.AiGatewayCoderdKey:
case database.AIGatewayCoderdKey:

name text NOT NULL,
secret_prefix varchar(11) NOT NULL,
hashed_secret bytea NOT NULL,
last_used_at timestamptz NULL,
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.

Would it make sense to add a created_by column with the user that created the key? Since this is deployment scoped, it might be useful.

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 can see it bringing some value but also I see this potentially causing some PII issues.
Key creation / deletion is audit logged so this information should be available (just not for everyone).

id uuid PRIMARY KEY,
created_at timestamptz NOT NULL,
name text NOT NULL,
secret_prefix varchar(11) NOT NULL,
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.

Do we have any safeguards at the application level in case the secret length is less than 11? Because in that case, we could be storing the full secret at the database.
Actually, do we need a secret_prefix? 🤔 Isn't the (id, name) enough for identifying a key?

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.

Yes, name could be enough but secret prefix provides way to make sure that given secret is used in standalone deployment anyway, or in general check which key is used by which deployment.
In hindsight maybe name is redundant here. It provides human readable description but maybe it is overcomplicating key management process more then it improves it.

Comment thread codersdk/audit.go Outdated
ResourceTypeAISeat ResourceType = "ai_seat"
ResourceTypeAIProvider ResourceType = "ai_provider"
ResourceTypeAIProviderKey ResourceType = "ai_provider_key"
ResourceTypeAIGatewayCoderdKey ResourceType = "ai_gateway_coderd_key"
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.

nit: remove coderd to be easier to read and consistent with provider key?

Suggested change
ResourceTypeAIGatewayCoderdKey ResourceType = "ai_gateway_coderd_key"
ResourceTypeAIGatewayKey ResourceType = "ai_gateway_key"

Copy link
Copy Markdown
Contributor Author

@pawbana pawbana May 26, 2026

Choose a reason for hiding this comment

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

Naming is not the best but I don't have good idea.

Problem is that Keyis very overloaded word in AI Gateway context. When I read KeyI first think about provider keys or BYOK.
Maybe this is far fetched since provider keys have descriptive name ResourceTypeAIProviderKey.
Specifying Coderdat least notes that this is related to Coderd. Still it doesn't explain well what it is used for. JustAuthKeywould also be confusing. Auth to what?
AIGatewayCoderdAuthKey seems too long? Or maybe not and would be better?
Credentials have similar issue as Key and doens't match naming used by provisioners.

Copy link
Copy Markdown
Member

@Emyrk Emyrk left a comment

Choose a reason for hiding this comment

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

Gateway keys are deployment wide, correct?

@pawbana
Copy link
Copy Markdown
Contributor Author

pawbana commented May 27, 2026

Gateway keys are deployment wide, correct?

Yes. There may be organization scoped keys in the future but no plans right now.

@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 3 times, most recently from a73fcbc to 8239275 Compare May 28, 2026 20:20
@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 4 times, most recently from 13dd6ae to 1bfe3cc Compare June 1, 2026 14:47
Copy link
Copy Markdown
Contributor

@ssncferreira ssncferreira left a comment

Choose a reason for hiding this comment

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

LGTM :shipit:

@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch 2 times, most recently from 37daa9f to 318ebc9 Compare June 1, 2026 18:48
@pawbana pawbana force-pushed the pb/gateway-multi-replica-key-auth-db branch from 318ebc9 to 06ad9f0 Compare June 2, 2026 07:06
@pawbana pawbana merged commit f22d4e2 into main Jun 2, 2026
29 of 31 checks passed
@pawbana pawbana deleted the pb/gateway-multi-replica-key-auth-db branch June 2, 2026 07:28
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants