Repository navigation
chore: update version and changelog - #347
Merged
Merged
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
October 6, 2026 02:22
41bf134 to
13cc111
Compare
5 tasks done
github-actions
Bot
force-pushed
the
changeset-release/main
branch
19 times, most recently
from
October 7, 2026 03:27
afaace7 to
d55fc98
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
October 7, 2026 03:28
d55fc98 to
4a1b155
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
seamless-auth-api@0.17.0
Minor Changes
4b04cec: Make
auth_eventsappend-only and tamper-evident. A new migration adds a hash chain (seq,prev_hash,hash, assigned by an insert trigger and serialized through a one-rowauth_event_chain_headtable), and triggers that refuse UPDATE, TRUNCATE, and any DELETE outside the retention job.GET /admin/auth-events/integrityrecomputes the chain and reports the first edited, missing or reordered row, along with the current head to record outside the database.The migration drops the
auth_events.user_idforeign key. ItsON DELETE SET NULLrewrote audit rows whenever a user was deleted. Audit rows now keep the id of the user they were about after that user is deleted. Existing rows are chained in the order they were written when the migration runs, which takes a pass over the whole table.be0c1c6: Add audit event retention and a bulk export.
AUDIT_RETENTION_DAYSexpires audit events older than the period. Expired events are first written toAUDIT_ARCHIVE_DIRas NDJSON files, each with a.sha256file beside it, and only then deleted. Without an archive directory nothing is deleted. Retention removes only a contiguous run from the start of the hash chain, and never the newest event, so what remains still verifies.AUDIT_RETENTION_DATABASE_URLlets the job run as a separate role that holds DELETE. The job runs daily, and each run logs the chain head as an external anchor.GET /admin/auth-events/export?from=&to=(admin, fresh step-up) streams every event in a period as oneapplication/x-ndjsondownload. Each line carries the exact hashed payload, and a trailing manifest gives the count, theseqrange, the anchor hash and the last hash, so the file can be verified without the database. Exports are themselves recorded in the audit trail.bb7de70: Add an authentication coverage report for assessment and insurance responses (No authentication coverage report for assessment and insurance responses #178).
GET /admin/reports/authentication-coverage(admin read) reports, for a period (from,to, default the last 90 days), how many active users hold a passkey overall, per organization and permonthorweekbucket, alongside the login and authenticator policy enforced now, the authenticator mix by AAGUID (with backup eligibility) and completed sign-ins by method.organizationIdscopes every figure to one organization's current members.format=csvreturns the same report as atext/csvattachment for pasting into a document.metadata.channel(emailorsms) onverify_otp_success, so the report can tell email codes from phone codes. Older rows are reported asotp.6dd2ced: Migrations can now run once per deploy instead of on every container start.
RUN_MIGRATIONS=falseskips the entrypoint's migration step, which on a 0.5 vCPU task was about 3 of the 6.8 seconds of boot. The default is unchanged.migrateargument validates the environment, applies pending migrations (creating the database if needed) and exits, for a one-off task per deploy. That also ends the race where every task in a scaled service applied the same migration.A process started directly with
node dist/server.jsagainst an unmigrated database now exits with a message naming the first pending migration, instead of failing later on a missing column.bc7f8ca: Track and invite passkey enrollment, for moving an organization onto passkeys after importing its users (feat: track and invite passkey enrollment for imported users #338).
GET /admin/enrollmentlists active users with their WebAuthn credential count and status (none,one,two_or_more), filterable by organization, status, imported users and email, with a per-status summary.POST /admin/enrollment/invitesemails users a notice to sign in and add a passkey. The link is the tenant's sign-in page (signInUrl, default<frontend_url>/login) and carries no credential.userIds(up to 200) or anorganizationId, whose unenrolled members are invited 200 at a time. Anyone invited in the last day is skipped, and the response reports whatremainingis left.x-seamless-auth-delivery-mode: external, each result carries the delivery for the caller to send.admin_enrollment_invite_sent.prompt_passkey_enrollmentsetting (defaultfalse, envPROMPT_PASSKEY_ENROLLMENT). With it on, email and phone code sign-ins and magic link sign-ins carrynextStep: 'enroll_passkey'for a user with no passkey.Requires a database migration,
@seamless-auth/types0.26.0 and@seamless-auth/messaging0.2.0.a132e8c: OAuth sign-in now supports cutting an organization over from a legacy identity provider.
promptPasskeyEnrollment(defaultfalse). With it set, a successfulPOST /oauth/:providerId/callbackcarriesnextStep: 'enroll_passkey'when the user has no passkey yet. The session in the response is a full access session, so the client can send the user straight into passkey enrollment. Absent means there is nothing further to do.PUT /admin/organizations/:organizationId/oauth-providers/:providerId/retirementretires a provider for one organization, andDELETEon the same path restores it for a rollback. Each change is recorded as anadmin_oauth_provider_retiredoradmin_oauth_provider_restoredauth event. A member of any organization that retired the provider is refused at the callback with403and codeoauth_provider_retired, before any account is claimed or linked. Retiring a provider also revokes every live session of every member of the organization, whichever method started it, so the cutover takes effect immediately; the count is recorded on the auth event. Retiring a provider that is already retired revokes nothing.retiredOAuthProvidersin every organization response.Contract change: clients that switch exhaustively over OAuth error codes need the new
oauth_provider_retiredcode. Requires a database migration and@seamless-auth/types0.25.0.c68a315: Add a phishing-resistant-only login mode and enforce the passkey fallback rule on every continuation endpoint.
phishing_resistant_onlysystem config key (envPHISHING_RESISTANT_ONLY, defaultfalse). When on, a session starts only from a passkey: email and phone codes, magic links, TOTP and OAuth are refused with403 login_method_disabled(OAuth providers are hidden), whateverlogin_methodssays, and the public config reportsloginMethods: ["passkey"]. The email code that verifies a new account's address still starts one session so the first passkey can be enrolled. Session issuance refuses a non-passkey factor in this mode as a backstop. Requires@seamless-auth/types0.27.0.passkey_login_fallback_enabled: falsenow binds on the continuation endpoints themselves, not only on the method list/loginreturns. A user who holds a passkey gets403 login_method_disabledfrom the email and phone code, magic link, TOTP login and email verification endpoints. Previously those endpoints checked only whether the method was enabled for the deployment.POST /totp/verify-logincan now answer403 login_method_disabled.c2edfbc:
GET /internal/metrics/dashboardandGET /internal/security/anomaliesacceptfromandto([Feature]: Dashboard metrics and security anomalies accept no time range #132), with the same validation as the/internal/auth-events/*endpoints and a default of the last 24 hours. Both responses carry thewindowthey covered.newUsers,loginSuccess,loginFailed,successRate,otpUsageandpasskeyUsagefor the requested window. The*24hfields keep meaning the last 24 hours.limit(1 to 200, default 200) andoffset.totalnow counts every match in the window. It used to report the number returned, which was capped at 200, so a caller could not tell there were more.Requires
@seamless-auth/types0.28.0.aecf347: Relicense from AGPL-3.0-only to the Apache License, Version 2.0 (chore: relicense the Seamless Auth ecosystem to Apache-2.0 #335). The
LICENSEfile, thelicensefield and the license header in every source file now say Apache-2.0. The commercial license offer in the README is removed, since Apache-2.0 already allows embedding the API in a proprietary product or running it as a managed service.d3f78d0: Remove the deprecated
GET /logout, which signed out every session of the current user. UseDELETE /logout/allfor that, orDELETE /logoutfor the current session only.GET /logoutnow answers 404. Every first-party client (@seamless-auth/server,@seamless-auth/react,seamless-cli) already usesDELETE. This is a breaking change for any other caller that still sendsGET.7b868d2: Record store review account use and report whether review accounts are on (feat(otp): record review account sign-ins and surface enabled review accounts #331).
REVIEW_ACCOUNT_CODE(otp_success,otp_failed,verify_otp_success,verify_otp_failed) now carrymetadata.reviewAccount: true. The code is never recorded.GET /admin/review-accounts(admin read) returnsenabled, the listedemails,codeConfiguredandrecentSignIns(sign-ins, failed verifications and the last sign-in by a review address in the lastdaysdays, default 30). The code is never returned.REVIEW_ACCOUNT_EMAILSandREVIEW_ACCOUNT_CODE.cc1d3c6: Refresh rotation no longer resets the absolute session lifetime. Each session now records when its rotation chain began (
chainStartedAt, new migration), and a rotated session expires at that start plusrefresh_token_ttlinstead of a full lifetime from the refresh. A session that refreshes continuously therefore ends at the absolute bound and the user signs in again. The idle bound still slides on each refresh, capped at the absolute one.refreshTtlin the/refreshresponse is now the time left in the chain rather than the fullrefresh_token_ttl. A refresh refused because the chain ran out, or because the session went idle, is recorded asrefresh_token_failedwithmetadata.refusalset toabsolute_lifetime_reachedoridle_timeout, so it can be told apart from an unknown or revoked token. Sessions that exist when the migration runs are capped from their most recent refresh.Patch Changes
0d0f422: Ship admin dashboard
v0.9.1at/console(wasv0.7.0). It adds the passkey enrollment view, the authentication coverage report, the audit trail panel, the phishing-resistant-only setting, ranged headline metrics and anomalies, and the store review accounts notice, which use routes this API now serves.bdb8fbd: Development signing keys are now created at startup, before the server listens, so
GET /.well-known/jwks.jsonpublishes a key from the first request. If no dev key can be read, the endpoint answers{ "keys": [] }and logs why, instead of a 500.The dev key directory defaults to
./keys/dev(/app/keys/devin the image) and can be moved withSEAMLESS_DEV_KEYS_DIR. The bundleddocker-compose.ymlkeeps/app/keyson adev-keysvolume, so a recreated container keeps its key. The public key is derived fromprivate.pem, so only the private key has to survive.The dev
kidis no longer the constantdev-main. It isdev-followed by the first 16 characters of the key's RFC 7638 JWK thumbprint, so a regenerated key gets a newkidand adapters that cache the JWKS refetch it on their own. Anything that looks the dev key up by the literaldev-mainshould read thekidfrom the JWKS instead. Thekidon adapter service tokens is not checked by the API and is unaffected.2601963: Support Node 22 and newer. The
enginesfield now requires>=22instead of>=24 <25, and CI runs the test suite on Node 22, 24, and the latest release (chore: support Node versions beyond 24 across the ecosystem #339).a132e8c: Fix
PATCH /system-config/oauth-providers/:idresetting settings the request did not mention. The parsed patch carried every default from@seamless-auth/types, so{ "enabled": false }also setallowSignup: true,accountLinking: 'email'andrequireEmailVerified: false, emptiedscopesandredirectUris, and reverted the claim paths. Fixed by@seamless-auth/types0.25.0 (fix(oauth): a partial OAuth provider update resets the provider's other settings to defaults seamless-auth-types#83).7a003fa: Update
proxy-addrto 2.0.8 for GHSA-jqcg-44mw-7w3h (critical), where a client could spoof its IP through an IPv4-mapped IPv6 address when a trusted proxy subnet is configured. It affects deployments that setTRUST_PROXY, where the client IP feeds rate limiting, lockout and the audit log.a956ba0: Update
@simplewebauthn/serverto 14.0.3 for GHSA-2g3p-m8c9-hhwh and GHSA-j3h4-m3m2-7p7j. During registration, an attestation certificate chain could make the server fetch a CRL from an attacker-chosen URL and cache it unverified in the process-wide revocation cache, influencing revocation checks for later registrations. 13.x carries the same code and has no patched release. The advertised public key algorithms are unchanged, since the API sets them explicitly, so the new ML-DSA (post-quantum) default does not apply.