Skip to content

refactor(coderd): stop storing chat gateway key IDs and drop the columns - #27171

Merged
ibetitsmike merged 4 commits into
mainfrom
mike/chat-synthetic-keys/stop-legacy-storage
Jul 20, 2026
Merged

refactor(coderd): stop storing chat gateway key IDs and drop the columns#27171
ibetitsmike merged 4 commits into
mainfrom
mike/chat-synthetic-keys/stop-legacy-storage

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Mux is working on behalf of Mike.

Summary

Stop reading and writing the legacy api_key_id columns on chat messages and queued messages, and drop the columns in the same PR. Runtime AI Gateway attribution continues to use the per-user synthetic key introduced by #27170.

With the columns gone, sqlc generates database.ChatMessage and database.ChatQueuedMessage without api_key_id, so no transitional query scaffolding is needed.

Migration 000548 drops the api_key_id columns. #27170 already removed their foreign keys, so the down migration re-adds nullable text columns without constraints. Previous column values cannot be restored.

Also moves the model config validation in CreateChat above the message-building work so a disabled or invalid model fails fast. On main this mattered more: the old ordering minted a synthetic API key before rejecting the request.

Deploy note: replicas still running the previous release write api_key_id on insert, so chat message inserts on old replicas fail during the rolling window after the column drop. This was previously split across two PRs to avoid that window; per review feedback the split added more churn than it was worth for an experimental surface.

Depends on #27170 (merged).

ibetitsmike commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

Mux is working on behalf of Mike.

Dogfood migration UAT passed.

The preserved database was then migrated to #27172 successfully.

@ibetitsmike ibetitsmike changed the title refactor(coderd/x/chatd): stop storing gateway key IDs refactor: stop storing gateway key IDs Jul 10, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 6635cd273b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/synthetic-keys branch from dbede83 to edea7df Compare July 10, 2026 18:21
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from 6635cd2 to 7557de2 Compare July 10, 2026 18:21
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 7557de2cfd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/synthetic-keys branch from edea7df to ab1009d Compare July 10, 2026 19:01
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch 2 times, most recently from 2a464a3 to e6a9d4f Compare July 10, 2026 19:23
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/synthetic-keys branch from ab1009d to 500b588 Compare July 10, 2026 19:37
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from e6a9d4f to 21f7269 Compare July 10, 2026 19:37
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 21f726957a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

Mux is working on behalf of Mike.

Final-stack targeted dogfood passed after the FK-decoupling fix.

  • PR1 head 500b588185: both legacy API-key FKs were absent. Deleting the mapped synthetic key during an active generation left history_version, queue_version, and generation_attempt unchanged at deletion time. The generation completed normally, compatibility text IDs remained, and the next turn reminted a new synthetic key.
  • PR2 head 21f726957a: the preserved PR1 chat loaded, a new FINAL-PR2 chat completed, legacy columns remained nullable and unwritten, and the FKs remained absent.
  • PR3 head 2de350aa78: preserved PR1 and PR2 chats loaded, a new FINAL-PR3 chat completed, and the legacy columns and FKs were absent.

This supplements the earlier full UI/API/database UAT and validates the final rewritten stack heads.

@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from 21f7269 to a2c5a8f Compare July 13, 2026 19:13

@johnstcn johnstcn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we need the new Raw queries and the extra querier interface? Why not just remove the field entirely?

@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from a2c5a8f to f3a8581 Compare July 14, 2026 08:28
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/synthetic-keys branch from 98e94a7 to d7e123e Compare July 14, 2026 08:28
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: f3a85814a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

Mux, on Mike's behalf.

The scaffolding is transitional, needed only while the columns still exist:

  • We cannot remove the field from the model in this PR: sqlc generates database.ChatMessage from the live schema, and the columns are only dropped in chore: drop chat gateway key columns #27172. This PR must be fully deployed before that drop, so replicas running this code never reference api_key_id in any query.
  • That forces explicit column projections (a bare SELECT * or sqlc's full-model scan would break with "column does not exist" mid-rolling-deploy once chore: drop chat gateway key columns #27172's migration runs). sqlc emits distinct row structs for those projections, hence the *Raw names plus wrappers that keep returning database.ChatMessage to callers.

To make the end state match your instinct: #27172 now also removes all of the scaffolding once the columns are gone. The queries get their canonical names back, and the extra querier interface, the pass-through wrappers, the duplicated dbauthz methods, and the row-projection types are deleted. Nothing named Raw survives the stack.

@johnstcn

Copy link
Copy Markdown
Member

The scaffolding is transitional, needed only while the columns still exist

Isn't that a sign that either
a) removing the column from the query belongs in #27172, or
b) this PR and #27172 should be squashed together

@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/synthetic-keys branch from d7e123e to fa35022 Compare July 18, 2026 17:28
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from f3a8581 to b3b93ac Compare July 18, 2026 17:28
ibetitsmike added a commit that referenced this pull request Jul 18, 2026
> Mux is working on behalf of Mike.

## Summary

Add a per-user synthetic API key for chatd AI Gateway attribution. Chatd
resolves the key from the chat owner, extends it before expiry, and
discards the generated bearer token so the key is never a usable
credential.

There is no mapping table. The key is resolved from `api_keys` by a
deterministic token name (`chatd_<owner_id>_session_token`), mirroring
the provisionerd session token model, with three deltas that chatd
needs:

- **Login type guard**: token names are unvalidated user input, so a
user can create a bearer token with the colliding name. The lookup
excludes `login_type = 'token'` rows, so chatd never picks up (or
extends) a real user token. Synthetic keys are minted with the owner's
login type, which is never `token`.
- **In-place expiry extension instead of delete-and-reinsert**: chat
generations have no stop boundary, and an in-flight generation may have
already delegated the current key ID to aibridged. Extending
`expires_at` keeps the key ID stable forever.
- **Advisory-lock mint**: the unique index on token names is partial
(`WHERE login_type = 'token'`), so nothing DB-enforces uniqueness for
synthetic keys. A per-user advisory lock serializes concurrent mints.

Keys carry a minimal scope (`api_key:read`) as defense in depth; the
delegated gateway path never evaluates scopes and the secret is
discarded at mint.

Migration 000544 removes the foreign keys from the legacy message and
queue `api_key_id` columns while chatd continues stamping them for
rolling compatibility. Stale IDs are tolerated because routing uses
`chats.owner_id`. Individual key deletion, delete-all, and password
reset remove the key without changing chat history or queue versions,
and the next lookup remints it. Suspension does not delete the key;
delegated gateway authorization rejects inactive users at request time.

This is the first PR in a three-PR rollout and must be fully deployed
before #27171.

Refs
https://linear.app/codercom/issue/CODAGT-561/maintain-synthetic-api-key-per-user-per-chat
Base automatically changed from mike/chat-synthetic-keys/synthetic-keys to main July 18, 2026 18:45
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from b3b93ac to 9fabe24 Compare July 18, 2026 18:53
@ibetitsmike ibetitsmike changed the title refactor: stop storing gateway key IDs refactor(coderd): stop storing chat gateway key IDs and drop the columns Jul 18, 2026
@ibetitsmike

ibetitsmike commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Mux, on Mike's behalf.

Fair point, we went with (b). This PR now contains the column drop as well (migration 000547; the FK drop 000546 already shipped with #27170), and the transitional scaffolding is gone since sqlc regenerates the models without api_key_id. The tradeoff is a brief rolling-deploy window where old replicas still insert into the dropped column; given this is an experimental surface, the two-PR choreography was not worth the churn. #27172 is closed.

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 9fabe241fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike requested a review from johnstcn July 18, 2026 19:20
@ibetitsmike
ibetitsmike force-pushed the mike/chat-synthetic-keys/stop-legacy-storage branch from 9fabe24 to c4171a0 Compare July 19, 2026 10:24
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4171a09ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: c4171a09ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike marked this pull request as ready for review July 20, 2026 11:49
Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: bab6732c50

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbec1dbb44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbec1dbb44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: bbec1dbb44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike merged commit 4ed6fcc into main Jul 20, 2026
33 of 34 checks passed
@ibetitsmike
ibetitsmike deleted the mike/chat-synthetic-keys/stop-legacy-storage branch July 20, 2026 17:49
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 20, 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.

2 participants