Skip to content

v6.8.0

Choose a tag to compare

@58bits 58bits released this 16 Oct 05:37
· 24 commits to develop since this release

Highlights

  • @byline/admin, @byline/host-tanstack-start, @byline/auth, @byline/core: Optional passkey sign-in for admin users. Admins can now add passkeys from their Account page and sign in with them from the sign-in page, alongside password sign-in, which is unchanged and stays available. Adding or removing a passkey, or confirming an action with one, requires fresh proof with the account's password or one of its own passkeys, and removing a passkey signs that account out on every device. Passkeys are created on the user's own authenticator (a phone, a laptop, a password manager or a security key), so nobody, including an admin, can create one for someone else. For account recovery, a role with the new admin.users.managePasskeys ability can review and remove another user's passkeys, and each recovery removal is written to the audit log; only a super-admin can manage another super-admin's passkeys. Passkeys stay off until a site configures its relying-party trust settings (rpId, rpName and exact origins), and they require HTTPS outside local development. Built on @simplewebauthn/server and @simplewebauthn/browser 14.
  • @byline/admin, @byline/db-postgres, @byline/db-mysql: Background cleanup of authentication records. Byline now automatically cleans up expired authentication records in the background, retaining ended sign-in records for 30 days. Three recurring tasks (auth.maintenance.attempts, auth.maintenance.logins and auth.maintenance.legacy-refresh) are created by createAuthMaintenanceTasks(adminStore) from @byline/admin/auth, and run in small, bounded batches so they never hold long locks.
  • @byline/admin, @byline/host-tanstack-start, @byline/ui, @byline/i18n: Admin account and user screens refined. The sign-in page places Sign in with a passkey below an "Or continue with" divider, with a new PasskeyIcon in @byline/ui. Adding and renaming a passkey open in a drawer like the other edit panels, while removal stays a confirmation modal; on narrow screens their actions stack full-width. Cancel buttons across the account, user and role forms now use the neutral noeffect style. On the Account page, Appearance is merged into Preferences and the Passkeys card matches the surrounding cards. On the Users screen, user and role cards share the account cards' corner radius, the detail page reads Account Details and Roles, then Password, Passkeys and Delete Admin User, and your own entry keeps the admin passkey view with a link to your Account page.
  • @byline/cli: New installations include passkeys and cleanup. The bundled database baselines now include the passkey tables and cleanup indexes, and the generated server.config.ts templates read the BYLINE_PASSKEY_* variables and register the cleanup tasks.

Chores

  • monorepo: Squashed the development Drizzle migrations for PostgreSQL and MySQL into a single baseline each, and synchronised the CLI's bundled copies.

Migrations

  • @byline/db-postgres, @byline/db-mysql: Apply the passkey upgrade script before starting 6.8.0. Existing installations must apply packages/db-postgres/sql/0014_add-passkeys.sql (PostgreSQL) or packages/db-mysql/sql/0009_add-passkeys.sql (MySQL), after any earlier scripts they have not yet applied, in filename order. The scripts are not part of the npm packages. Both are safe to re-run, and the PostgreSQL script includes the ownership guard. New installations created with byline init already include these changes.
  • @byline/admin: Register the cleanup tasks. Add ...createAuthMaintenanceTasks(adminStore) to recurringTasks in byline/server.config.ts. Upgrading the packages alone does not change an existing application's configuration.
  • @byline/admin, @byline/host-tanstack-start: Enabling passkeys (optional). Follow the updated CLI templates: build a passkeys trust object from BYLINE_PASSKEY_RP_ID, BYLINE_PASSKEY_RP_NAME and BYLINE_PASSKEY_ORIGINS (set all of them or none; a partial configuration fails at boot), pass it to JwtSessionProvider, and add passkeys and passkeyRequests to the server config, with createPasskeyRequestLimiter(adminStore.signInRateLimits, signingSecret). A passkey belongs to its relying-party ID, so changing the site's domain later invalidates existing passkeys. Grant admin.users.managePasskeys to the roles that should handle passkey recovery.

Breaking Changes

  • monorepo: Node.js >=22.22.2 is now required by every published package and by the CLI's preflight check, because Byline's own toolchain (Vite 8, Vitest 5 and jsdom) needs it. If you run Node 24, use 24.15 or later. Upgrade Node before installing 6.8.0.
  • @byline/admin: Custom AdminStore implementations must add passkeys and authMaintenance. The built-in PostgreSQL and MySQL adapters provide both. Both are required even when passkeys stay off.
  • @byline/admin, @byline/db-postgres, @byline/db-mysql: refreshTokens.purgeExpired() now deletes only legacy refresh tokens: rows without a login session that expired at least 30 days ago, at most 100 per call. Tokens that belong to a login session are kept until the cleanup task removes the whole ended sign-in, so a replayed old token is still detected as reuse. If you call purgeExpired() from your own job, expect it to delete fewer rows.

All other @byline/* packages bumped to 6.8.0 in lockstep with no behavioural changes this cycle.