Skip to content

v0.3.0

Latest

Choose a tag to compare

@nperez0111 nperez0111 released this 15 Aug 08:05
a053f8c

Bug Fixes

  • atprotoState.expiresAt now stored as a date instead of a raw epoch-millisecond number. This aligns with better-auth's own idiomatic handling of ephemeral tokens (e.g. verification.expiresAt) and maps to proper timestamp columns across dialects (SQLite date, Postgres timestamptz, MySQL timestamp(3)). The state store now normalizes both Date and legacy number values when reading.
  • atprotoSession.userId is now nullable. During the OAuth flow a temporary session row is created before the user is identified. Previously this inserted an empty-string userId, which violated the NOT NULL + foreign-key constraint on Postgres and surfaced as CALLBACK_FAILED. The temp row now inserts null and is back-filled with the real userId in the callback handler once the user is resolved.

Maintenance

  • Bumped hono (devDependency, used only in the demo) to 4.13.2, resolving 6 Dependabot advisories.
  • Bumped SHA-pinned GitHub Actions: actions/checkout v7.0.1, actions/setup-node v7.0.0.

Migration

Fresh installs need nothing — the schema is generated correctly.

Existing deployments require a one-time manual migration. better-auth's auto-migration only adds missing tables/columns; it does not alter the type or nullability of existing columns (it only logs a warning). Run the following once against your database.

atprotoState is ephemeral (~10 min TTL), so dropping its rows is safe.

PostgreSQL

DELETE FROM "atprotoState";
ALTER TABLE "atprotoState"
  ALTER COLUMN "expiresAt" TYPE timestamptz USING to_timestamp("expiresAt" / 1000.0);
ALTER TABLE "atprotoSession"
  ALTER COLUMN "userId" DROP NOT NULL;

MySQL

DELETE FROM `atprotoState`;
ALTER TABLE `atprotoState`
  MODIFY COLUMN `expiresAt` TIMESTAMP(3) NULL;
ALTER TABLE `atprotoSession`
  MODIFY COLUMN `userId` VARCHAR(255) NULL;

SQLite

SQLite stores dates as timestamps and does not enforce a separate column type here, so only the nullability of userId matters. If your adapter created userId as NOT NULL, recreate the table (SQLite cannot drop a NOT NULL constraint via ALTER):

DELETE FROM "atprotoState";
-- Recreate atprotoSession with a nullable userId if it was NOT NULL.
-- Adjust column list to match your generated schema before running.

Full Changelog: v0.2.0...v0.3.0