# Changelog

All notable changes to `@better-auth/infra` are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.3] - 2026-08-25

### Added

- **SAML `wantAssertionsSigned`** — Dash SSO create/update accept and persist `samlConfig.wantAssertionsSigned` (default `true`). Required for directory sync SAML pairing; can be disabled only when the IdP cannot sign assertions.

## [0.4.2] - 2026-08-21


### Fixed

- **Identification on OAuth callbacks** — Sentinel and dash run identification on GET OAuth callback routes and persist `X-Request-Id` as the `__infra-rid` cookie in an after hook, so visitor identity resolves from KV across redirect-based social/OAuth sign-in (where identify headers are absent).
- **Issuer-scoped account lookups** — OAuth callback user resolution honors `account.identityStrategy` (`issuer` vs `provider-id`) when deriving account keys, matching Better Auth 1.7 issuer-scoped identity and the provider-scoped compatibility mode.

### Changed

- **No runtime dependency on SCIM / SSO packages** — Directory-sync SCIM user-link acquisition and SAML SP policy checks are implemented in-package (aligned with `@better-auth/scim` / `@better-auth/sso`). Those packages remain type-only deps and are excluded from the published bundle.

## [0.4.1] - 2026-08-19

### Fixed

- **React Native / Hermes crypto** — SHA-256 (including Sentinel PoW challenge solve/verify) no longer requires `crypto.subtle`. Prefers Web Crypto when present; otherwise falls back to `@noble/hashes`.

## [0.4.0] - 2026-08-14


### Added

- **Managed SCIM directory sync** — Opt-in `dash({ managedDirectorySync: { enabled: true } })` control plane for Better Auth 1.7+ managed connections. Adds dashboard lifecycle endpoints to create, list, get, rotate credentials, revoke credentials, list events, unpair, and decommission organization directories, plus schema for `directorySyncConnection` / membership provenance, optional SSO pairing hooks, and SCIM → organization membership projection.
- **Issuer-scoped accounts** — Dashboard user create, set-password, and account unlink paths work with Better Auth 1.7 issuer-scoped account identity (`issuer` + subject) while remaining compatible with pre-issuer schemas.
- **Configurable API / KV client options** — Shared `apiOptions` / `kvOptions` (timeout and KV retry/backoff) on `dash` and `sentinel`. Legacy `apiTimeout` / `kvTimeout` remain supported as deprecated aliases.
- **`GET /dash/config` joins insight** — Config insights report `hasJoinsEnabled` from `advanced.database.joins` (and pre-1.7 `experimental.joins` when applicable).

### Changed

- **Better Auth 1.7 RC compatibility** — Support matrix and runtime paths updated through 1.7 rc.4 (issuer-scoped accounts, session lifecycle hooks, SSO domain verification contracts).
- **SSO domain verification TXT records** — Dashboard domain verification uses the SSO plugin `tokenPrefix` and the `_` + prefix + provider id TXT name shape expected by Better Auth domain verification.
- **Session lifecycle event tracking** — Sign-in / session-created / impersonation tracking deferred correctly when session creation runs before the user is available on the request context (Better Auth 1.7 rc.2+).
- **Directory list mode split** — Legacy pre-1.7 SCIM provider listing stays on the legacy surface; managed connection APIs only run when managed directory sync is enabled.
- **Account unlink body** — `unlinkAccount` requires `accountId` (local account row id) together with `providerId`.

### Fixed

- **SSO domain verify errors** — `verify-domain` maps provider-changed, already-verified, and missing-DNS cases to stable dashboard responses instead of leaking raw API errors.
- **Sentinel stale-account handling** — Stale-user blocks clear the session cookie and surface a consistent `STALE_ACCOUNT` error after the endpoint runs, not only inside DB hooks.
- **SCIM token redaction** — Sensitive SCIM credential fields stay redacted in dash config / plugin option dumps.

## [0.3.7] - 2026-07-20

### Added

- **`GET /dash/config` error URL insight** — Config insights now include `hasErrorURLConfigured`, reflecting whether `onAPIError.errorURL` is set.

## [0.3.6] - 2026-07-09

### Changed

- **Activity tracking writes** — `lastActiveAt` updates now run through Better Auth background tasks (`runInBackgroundOrAwait`) instead of blocking the request or using fire-and-forget promises, so activity tracking no longer delays responses when a background runner is available.

## [0.3.5] - 2026-07-06


### Added

- **`GET /dash/users` partial fetches** — Endpoint was optimized to load only the requested fields (sessions or accounts) instead of all fields.

### Changed

- **SCIM organization ownership model** — On Better Auth 1.7+, directory sync ownership is tied to the organization; this version closely follows the new ownership model while maintaining backwards compatibility with older versions.
- **Dashboard query performance** — Organization, team, user, and invitation routes use narrower `select` clauses, adapter joins instead of sequential lookups, parallel independent queries, and a shared concurrency cap (`DASH_DB_QUERY_CONCURRENCY`, 5) for analytics workloads.
- **Activity tracking writes** — `lastActiveAt` updates were optimized to avoid unnecessary row returns.
- **Sentinel on dashboard routes** — `/dash` routes skip device identification and Sentinel security checks (free-trial abuse, impossible travel, credential stuffing, and related hooks).
- **Event tracking** — Session lifecycle events reuse user data from the request context when available, avoiding redundant user lookups after sign-in.

## [0.3.4] - 2026-06-26

### Fixed

- **SCIM directory sync types** — `SCIMPlugin` uses a type-only import so `@better-auth/scim` typedefs are not bundled into published output.

## [0.3.3] - 2026-06-26

### Added

- **`dashCompleteInvitationHandoff`** — New `GET /dash/complete-invitation-handoff` endpoint completes invitations on the auth server after the platform validates credentials via a one-time handoff, so session cookies reach the invitee's browser.

### Changed

- **Invitation accept workflows** — Password and social completion endpoints enforce auth mode rules: `direct_redirect` invitations cannot use platform completion; `create_no_session` omits session cookies and revokes sessions after social completion; `create_with_session` allows passwordless user creation.
- **SSO domain verification** — `mark-domain-verified` no longer accepts `verified: true`; domains can only be verified through DNS (`verify-domain`) or have verification cleared.
- **User list pagination** — `getUsers` clamps `limit` (max 100) and `offset` to prevent expensive unbounded queries.
- **Email validation** — Validation always uses the configured policy strictness; the optional MX bypass has been removed.

### Security

- **Trusted redirect URLs** — Invitation redirects, impersonation targets, and email callback URLs are resolved against the auth base URL and `trustedOrigins`; untrusted origins fall back or are rejected.
- **SCIM directory sync** — Creating a directory provider with an existing `providerId` in the same organization is rejected.

## [0.3.2] - 2026-06-22

### Fixed

- **`dashClient` typing** — Restores correct `createAuthClient` inference when composing `dashClient()` with other client plugins.

## [0.3.1] - 2026-06-22

### Changed

- **`dashClient` typing** — The client plugin now declares an explicit `BetterAuthClientPlugin` uses the updated signature, so `createAuthClient` inference works without casts when composing with other plugins.

### Fixed

- **Package metadata** — Repository and issue tracker URLs now point to `better-auth/infrastructure`.

## [0.3.0] - 2026-06-19

### Added

- **Better Auth 1.7.x support** — SCIM directory sync works without the removed `providerOwnership` option; SSO dashboard routes no longer require `@better-auth/sso` as a separate peer dependency.
- **Backwards compatibility for Better Auth 1.4–1.6** — Session deletion and session listing work across internal adapter API changes; secondary-storage sessions missing `id` are normalized for dashboard use.
- **Expanded invitation auth modes** — Invitation acceptance supports `credential_setup`, `create_with_session`, and `create_no_session` in addition to `auth` and `direct`, aligned with the platform dashboard.
- **`deleteAllSessions` on ban endpoints** — `banUser` and `banManyUsers` accept an optional `deleteAllSessions` flag (defaults to `true`); `banManyUsers` now revokes sessions for banned users.
- **Strict user schemas** — Dashboard user create and update routes validate against schemas derived from the auth user table.

### Changed

- **Better Auth upgrade** — Compatibility target raised to Better Auth 1.7.x.
- **Dash config redaction** — Plugin options and sensitive auth configuration use shared redaction utilities for more consistent masking.
- **Client IP resolution** — Platform proxy headers are trusted by default; custom `ipAddressHeaders` must be configured explicitly.
- **Sentinel security evaluation** — Security check events fall back to an untrusted visitor ID when trusted device identification is unavailable.
- **Free-trial abuse prevention** — Uses atomic signup reservation and confirmation instead of a pre-create check.
- **SMS client IP forwarding** — Outbound SMS requests can include the end-user IP via `x-better-auth-client-ip` for server-side abuse limits.

### Fixed

- **Generic OAuth callback events** — Failed sign-in events are tracked for generic OAuth2 callbacks (`/oauth2/callback/:providerId`).
- **Event property typo** — Tracked failed sign-in events now use `userName` instead of `nameName`.
- **Credential stuffing on reset-password** — Sentinel breached-password checks now run on the reset-password route.
- **Sentinel identification** — Identify requests retry with exponential backoff, stale identification sessions expire and regenerate, and auth routes retry identification when the page-load attempt failed.
- **Free-trial security checks** — Fixed race conditions on signup reservation and confirmation.
- **Invitation scoping** — Cancel and resend invitation operations validate the invitation ID and scope queries to the authenticated organization.

### Security

- **Session tokens in dash responses** — Bearer tokens are stripped from dashboard user session listings.
- **Credential stuffing fingerprints** — Failed-login password fingerprints use per-tenant HMAC-SHA256 instead of unsalted SHA-256.
- **Identification for free-trial abuse** — Sign-up is blocked when free-trial abuse prevention is enabled but device identification is missing.
- **Security check binding** — Sentinel security API calls include `requestId` for tighter operation binding.
- **Redirect URL validation** — Dashboard and invitation routes validate callback and redirect URLs as safe `http(s)` URLs without embedded credentials.
- **Organization slug validation** — Organization routes enforce comprehensive slug validation.
- **User schema enforcement** — Dashboard user mutations are restricted to writable fields from the auth schema.

## [0.2.14] - 2026-06-09

### Added

- **`dashCompleteTwoFactorSetup`** — New dashboard endpoint (`POST /dash/complete-two-factor-setup`) to mark 2FA as enabled after the user verifies their TOTP code, separating "setup started" from "setup complete"
- **`twoFactorStatus` on user details** — `getUserDetails` now returns `twoFactorStatus: "disabled" | "pending" | "enabled"`, so the dashboard can distinguish users who started but haven't finished 2FA setup.

### Changed

- **Two-factor routes align with Better Auth** — Dashboard 2FA endpoints now respect the two-factor plugin's configuration: custom `twoFactorTable`, TOTP issuer/digits/period, and backup code options.
- **`enableTwoFactor` behavior** — Orphaned setup records (user started `/two-factor/enable` but never verified) are cleared and replaced instead of returning "already enabled." Only users with `twoFactorEnabled: true` are treated as fully enabled.
- **Event location coverage** — Tracked events now consistently include location, including: email verification, magic link verification, invitation acceptance, and social invitation completion.
- **Outbound HTTP clients** — All outbound HTTP clients now send the same `User-Agent` header (`@better-auth/infra v{version}`) for simpler observability.

### Fixed

- **OAuth social sign-in failures** — Failed social login attempts are now correctly attributed to the user.

### Security

- **Timing-safe API key comparison** — JWT middleware now uses constant-time hash comparison when validating API keys.

## [0.2.13] - 2026-06-05

### Changed

- Event tracking now consistently records location data on tracked events.

### Fixed

- Fixed impossible travel security challenges.

[0.3.7]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.6...infra@v0.3.7
[0.3.6]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.5...infra@v0.3.6
[0.4.0]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.7...infra@v0.4.0
[0.3.5]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.4...infra@v0.3.5
[0.3.4]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.3...infra@v0.3.4
[0.3.3]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.2...infra@v0.3.3
[0.3.2]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.1...infra@v0.3.2
[0.3.1]: https://github.com/better-auth/infrastructure/compare/infra@v0.3.0...infra@v0.3.1
[0.3.0]: https://github.com/better-auth/infrastructure/compare/infra@v0.2.14...infra@v0.3.0
[0.2.14]: https://github.com/better-auth/better-auth-infra/compare/@better-auth/infra@0.2.13...@better-auth/infra@0.2.14
[0.2.13]: https://github.com/better-auth/better-auth-infra/compare/@better-auth/infra@0.2.12...@better-auth/infra@0.2.13
