👷 build: add api key hash column migration (#12862)

*  feat(database): extract openapi database changes

* 📝 docs: update db-migrations and version-release skills

---------

Co-authored-by: MarioJames <mocha.wyh@msn.com>
Co-authored-by: YuTengjing <ytj2713151713@gmail.com>
This commit is contained in:
Arvin Xu
2026-03-09 23:04:45 +08:00
committed by GitHub
parent 169d5afa93
commit 4e6790e3d7
9 changed files with 12475 additions and 8 deletions

View File

@@ -21,6 +21,23 @@ And updates:
- `packages/database/src/core/migrations.json` - `packages/database/src/core/migrations.json`
- `docs/development/database-schema.dbml` - `docs/development/database-schema.dbml`
## Custom Migrations (e.g. CREATE EXTENSION)
For migrations that don't involve Drizzle schema changes (e.g. enabling PostgreSQL extensions), use the `--custom` flag:
```bash
bunx drizzle-kit generate --custom --name=enable_pg_search
```
This generates an empty SQL file and properly updates `_journal.json` and snapshot. Then edit the generated SQL file to add your custom SQL:
```sql
-- Custom SQL migration file, put your code below! --
CREATE EXTENSION IF NOT EXISTS pg_search;
```
**Do NOT manually create migration files or edit `_journal.json`** — always use `drizzle-kit generate` to ensure correct journal entries and snapshots.
## Step 2: Optimize Migration SQL Filename ## Step 2: Optimize Migration SQL Filename
Rename auto-generated filename to be meaningful: Rename auto-generated filename to be meaningful:

View File

@@ -63,7 +63,7 @@ Version number is automatically bumped by patch +1. There are 4 common scenarios
| Weekly Release | canary | `release/weekly-{YYYYMMDD}` | Weekly release train, canary → main | | Weekly Release | canary | `release/weekly-{YYYYMMDD}` | Weekly release train, canary → main |
| Bug Hotfix | main | `hotfix/v{version}-{hash}` | Emergency bug fix | | Bug Hotfix | main | `hotfix/v{version}-{hash}` | Emergency bug fix |
| New Model Launch | canary | Community PR merged directly | New model launch, triggered by PR title prefix | | New Model Launch | canary | Community PR merged directly | New model launch, triggered by PR title prefix |
| DB Schema Migration | canary | `release/db-migration-{name}` | Database migration, requires dedicated changelog | | DB Schema Migration | main | `release/db-migration-{name}` | Database migration, requires dedicated changelog |
All scenarios auto-bump patch +1. Patch PR titles do not need a version number. See `reference/patch-release-scenarios.md` for detailed steps per scenario. All scenarios auto-bump patch +1. Patch PR titles do not need a version number. See `reference/patch-release-scenarios.md` for detailed steps per scenario.
@@ -116,6 +116,14 @@ When the user requests a release:
3. Push and create a PR — **title must be `🚀 release: v{version}`** 3. Push and create a PR — **title must be `🚀 release: v{version}`**
4. Inform the user that merging the PR will automatically trigger the release 4. Inform the user that merging the PR will automatically trigger the release
### Precheck
Before creating the release branch, verify the source branch:
- **Weekly Release** (`release/weekly-*`): must branch from `canary`
- **All other release/hotfix branches**: must branch from `main` — run `git merge-base --is-ancestor main <branch> && echo OK` to confirm
- If the branch is based on the wrong source, delete and recreate from the correct base
### Patch Release ### Patch Release
Choose the appropriate workflow based on the scenario (see `reference/patch-release-scenarios.md`): Choose the appropriate workflow based on the scenario (see `reference/patch-release-scenarios.md`):
@@ -123,7 +131,7 @@ Choose the appropriate workflow based on the scenario (see `reference/patch-rele
- **Weekly Release**: Create a `release/weekly-{YYYYMMDD}` branch from canary, scan `git log main..canary` to write the changelog, title like `🚀 release: 20260222` - **Weekly Release**: Create a `release/weekly-{YYYYMMDD}` branch from canary, scan `git log main..canary` to write the changelog, title like `🚀 release: 20260222`
- **Bug Hotfix**: Create a `hotfix/` branch from main, use a gitmoji prefix title (e.g. `🐛 fix: ...`) - **Bug Hotfix**: Create a `hotfix/` branch from main, use a gitmoji prefix title (e.g. `🐛 fix: ...`)
- **New Model Launch**: Community PRs trigger automatically via title prefix (`feat` / `style`), no extra steps needed - **New Model Launch**: Community PRs trigger automatically via title prefix (`feat` / `style`), no extra steps needed
- **DB Migration**: Create a `release/db-migration-{name}` branch from canary, write a dedicated migration changelog - **DB Migration**: Create a `release/db-migration-{name}` branch from main, cherry-pick migration commits, write a dedicated migration changelog
### Important Notes ### Important Notes

View File

@@ -15,4 +15,4 @@ This release includes a **database schema migration** involving **5 new tables**
- The migration runs automatically on application startup - The migration runs automatically on application startup
- No manual intervention required - No manual intervention required
The migration owner: @arvinxx — responsible for this database schema change, reach out for any migration-related issues. The migration owner: @\[pr-author] — responsible for this database schema change, reach out for any migration-related issues.

View File

@@ -91,12 +91,13 @@ Database schema changes that need to be released independently. These require a
### Steps ### Steps
1. **Create release branch from canary** 1. **Create release branch from main and cherry-pick migration commits**
```bash ```bash
git checkout canary git checkout main
git pull origin canary git pull --rebase origin main
git checkout -b release/db-migration-{name} git checkout -b release/db-migration-{name}
git cherry-pick <migration-commit-hash>
git push -u origin release/db-migration-{name} git push -u origin release/db-migration-{name}
``` ```

View File

@@ -0,0 +1,3 @@
ALTER TABLE "api_keys" ADD COLUMN IF NOT EXISTS "key_hash" varchar(128);--> statement-breakpoint
ALTER TABLE "api_keys" DROP CONSTRAINT IF EXISTS "api_keys_key_hash_unique";--> statement-breakpoint
ALTER TABLE "api_keys" ADD CONSTRAINT "api_keys_key_hash_unique" UNIQUE("key_hash");

File diff suppressed because it is too large Load Diff

View File

@@ -623,6 +623,13 @@
"when": 1772277762014, "when": 1772277762014,
"tag": "0088_fix_benchmark_add_bot_provider", "tag": "0088_fix_benchmark_add_bot_provider",
"breakpoints": true "breakpoints": true
},
{
"idx": 89,
"version": "7",
"when": 1772723999146,
"tag": "0089_add_api_key_hash",
"breakpoints": true
} }
], ],
"version": "6" "version": "6"

View File

@@ -13,7 +13,8 @@ export const apiKeys = pgTable(
.notNull() .notNull()
.primaryKey(), .primaryKey(),
name: varchar('name', { length: 256 }).notNull(), // name of the API key name: varchar('name', { length: 256 }).notNull(), // name of the API key
key: varchar('key', { length: 256 }).notNull().unique(), // API key key: varchar('key', { length: 256 }).notNull().unique(), // encrypted API key
keyHash: varchar('key_hash', { length: 128 }).unique(), // hash of api key for authentication lookup
enabled: boolean('enabled').default(true), // whether the API key is enabled enabled: boolean('enabled').default(true), // whether the API key is enabled
expiresAt: timestamptz('expires_at'), // expires time expiresAt: timestamptz('expires_at'), // expires time
lastUsedAt: timestamptz('last_used_at'), // last used time lastUsedAt: timestamptz('last_used_at'), // last used time

View File

@@ -14,7 +14,7 @@ import { asyncTasks } from './asyncTask';
import { chatGroups, chatGroupsAgents } from './chatGroup'; import { chatGroups, chatGroupsAgents } from './chatGroup';
import { documents, files, knowledgeBases } from './file'; import { documents, files, knowledgeBases } from './file';
import { generationBatches, generations, generationTopics } from './generation'; import { generationBatches, generations, generationTopics } from './generation';
import { messageGroups, messages, messagesFiles } from './message'; import { messageGroups, messages, messagesFiles, messageTranslates } from './message';
import { chunks, documentChunks, unstructuredChunks } from './rag'; import { chunks, documentChunks, unstructuredChunks } from './rag';
import { sessionGroups, sessions } from './session'; import { sessionGroups, sessions } from './session';
import { threads, topicDocuments, topics } from './topic'; import { threads, topicDocuments, topics } from './topic';
@@ -98,6 +98,10 @@ export const threadsRelations = relations(threads, ({ one }) => ({
export const messagesRelations = relations(messages, ({ many, one }) => ({ export const messagesRelations = relations(messages, ({ many, one }) => ({
filesToMessages: many(messagesFiles), filesToMessages: many(messagesFiles),
translation: one(messageTranslates, {
fields: [messages.id],
references: [messageTranslates.id],
}),
session: one(sessions, { session: one(sessions, {
fields: [messages.sessionId], fields: [messages.sessionId],