Skip to content

🚀 Release v0.28.8#4029

Merged
Siumauricio merged 4 commits intomainfrom
canary
Mar 19, 2026
Merged

🚀 Release v0.28.8#4029
Siumauricio merged 4 commits intomainfrom
canary

Conversation

@github-actions
Copy link
Copy Markdown

@github-actions github-actions bot commented Mar 18, 2026

This PR promotes changes from canary to main for version v0.28.8.

🔍 Changes Include:

  • Version bump to v0.28.8
  • All changes from canary branch

✅ Pre-merge Checklist:

  • All tests passing
  • Documentation updated
  • Docker images built and tested

🤖 This PR was automatically generated by GitHub Actions

Greptile Summary

This release (v0.28.8) migrates the apikey table to align with @better-auth/api-key's expected schema when using references: "user", renaming the user_id column to reference_id and adding a config_id column. The migration is split across two SQL files — the first safely backfills data before setting constraints, the second swaps the foreign key and drops the old column. The Drizzle schema and auth configuration are updated consistently.

Key changes:

  • Two new Drizzle migrations (0150, 0151) rename apikey.user_idapikey.reference_id and add apikey.config_id.
  • account.ts schema updated: referenceId field and apikeyRelations updated to join through the new column.
  • auth.ts gains references: "user" in the apiKey plugin config so better-auth maps sessions to referenceId.
  • services/user.ts createApiKey creates the key then updates metadata in a separate, non-atomic DB call — if the metadata update fails, the key is orphaned and permanently unusable since validateRequest requires organizationId in the metadata.
  • 0151_modern_sunfire.sql is missing a trailing newline.

Confidence Score: 3/5

  • Safe to merge with awareness of the non-atomic API key creation issue which can produce orphaned keys under failure conditions.
  • The schema migration is well-structured (two-phase, data-safe) and the schema/auth changes are consistent. The main concern is the non-atomic key + metadata creation in user.ts — a failure between the two DB operations leaves a permanently unusable key with no recovery path, since validateRequest requires organizationId in the metadata. This is a real reliability issue under transient DB failures. The missing EOF newline in the SQL file is trivial.
  • packages/server/src/services/user.ts — the non-atomic createApiKey logic deserves attention before the release ships to production.

Last reviewed commit: "Merge pull request #..."

Greptile also left 2 inline comments on this PR.

Siumauricio and others added 3 commits March 18, 2026 16:26
- Modified the apikey table to drop the user_id column and replace it with reference_id, establishing a foreign key relationship with the user table.
- Added config_id column with a default value to the apikey table.
- Updated related code in the account schema and user service to reflect these changes.
- Enhanced the journal and snapshot files to include the latest schema updates.
…nbale-to-generate-new-ones-after-upgrade-to-0287

feat: update apikey schema and relationships
@github-actions github-actions bot requested a review from Siumauricio as a code owner March 18, 2026 22:29
@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Mar 18, 2026
Comment on lines 435 to +457
@@ -450,10 +450,9 @@ export const createApiKey = async (
if (input.metadata) {
await db
.update(apikey)
.set({
metadata: JSON.stringify(input.metadata),
})
.where(eq(apikey.id, apiKey.id));
.set({ metadata: JSON.stringify(input.metadata) })
.where(eq(apikey.id, result.id));
}
return apiKey;

return result;
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.

P1 Non-atomic API key creation leaves orphaned unusable keys

The API key is created in one call, then metadata (containing organizationId) is set in a separate UPDATE. If the update on line 452–455 fails (e.g. due to a transient DB error or process crash), the key will persist in the database without the organizationId metadata.

In validateRequest in auth.ts (lines 457–465), any API key whose metadata lacks organizationId immediately returns { session: null, user: null }, so the key is permanently non-functional and there is no recovery path for the caller.

Consider passing the metadata during key creation or wrapping both operations in a transaction to guarantee atomicity:

const result = await auth.createApiKey({
    body: {
        name: input.name,
        expiresIn: input.expiresIn,
        prefix: input.prefix,
        rateLimitEnabled: input.rateLimitEnabled,
        rateLimitTimeWindow: input.rateLimitTimeWindow,
        rateLimitMax: input.rateLimitMax,
        remaining: input.remaining,
        refillAmount: input.refillAmount,
        refillInterval: input.refillInterval,
        userId,
        metadata: input.metadata ? JSON.stringify(input.metadata) : undefined,
    },
});

If the auth.createApiKey API does not accept metadata at creation time, wrap the two operations in a db.transaction so a failed metadata update rolls back the key creation as well.

ALTER TABLE "apikey" DROP CONSTRAINT "apikey_user_id_user_id_fk";
--> statement-breakpoint
ALTER TABLE "apikey" ADD CONSTRAINT "apikey_reference_id_user_id_fk" FOREIGN KEY ("reference_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "apikey" DROP COLUMN "user_id"; No newline at end of file
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.

P2 Missing newline at end of file

This file is missing a trailing newline (\ No newline at end of file in the diff). While this does not affect SQL execution, it is inconsistent with the other migration files in this repository and can cause noisy diffs in the future.

Suggested change
ALTER TABLE "apikey" DROP COLUMN "user_id";
ALTER TABLE "apikey" DROP COLUMN "user_id";

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

- Changed the authorization check for deleting an API key to use referenceId instead of userId, ensuring proper validation against the current user's ID.
@Siumauricio Siumauricio merged commit 4d8a2a3 into main Mar 19, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated pr release size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant