Skip to content

feat: agent auth 2.0 with devices, robots, quorum approvals, core email and password, and security fixes - #273

Merged
thegdsks merged 49 commits into
mainfrom
release/agent-wave9-2026-10-18
Oct 19, 2026
Merged

thegdsks merged 49 commits into
mainfrom
release/agent-wave9-2026-10-18

Conversation

@thegdsks

@thegdsks thegdsks commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

This is the second agent auth release branch. It has 41 commits on top of main, adds devices and robots next to agents, and fixes a batch of bugs that review and real database runs turned up. Nothing here is released or tagged. The later commits add quorum approvals, bring your own Drizzle, three more secondary storage backends, Supabase and WorkOS importers, client binding fixes, single-use repositories, resumable GDPR erasure, SPIFFE workload identity routes, hot path indexes and a libSQL provider. See What is new and Breaking changes.

Read this before merging

Merging this to main will publish packages. publish.yml publishes any package whose version differs from npm once main CI is green, and main already carries @glinr/theauth 1.3.0, mcp 1.2.0 and gateway 4.1.0, none of which are on npm. This branch also fixes the lockfile that is keeping main red. So the first green run ships whatever version main holds. There are 106 pending changesets, 23 of them majors for core, so the plan is 2.0.0. Run pnpm changeset version on this branch and commit it in the same merge. The full order and the patch release table are in docs-local/tasks/release-plan-2.0.md (local file, not in the repo).

Security fixes in versions already on npm

These affect @glinr/theauth 1.2.0 and need a 1.2.x patch release and advisories. The drafts for the first four exist and have not been sent.

  • Account routes (username, passkey, totp, additional fields, verify email) trusted a user id from the request body, so anyone could change another user's username or password. Every version from 0.4.2 to 1.2.0.
  • The SAML signature check could be bypassed in 1.2.0.
  • nextjs-auth 0.2.0 trusted an unsigned session cache cookie.
  • Four single use credentials could be spent twice by concurrent requests: an OIDC authorization code, an OIDC refresh token, a JWT session refresh token and a passkey challenge. The code ran a conditional update and ignored how many rows it changed.
  • The delegation subset check let a parent holding exactly tool:db delegate tool:db:secrets, which the parent could not use itself.
  • OIDC refresh token reuse now revokes the whole token family (RFC 9700 4.14.2). Before, only the reused token was refused.
  • The hourly call budget (maxCallsPerHour, table theauth_rate_limits) read its counters and then wrote one back, so parallel calls could all see room. The changeset reports 24 parallel calls against a limit of 10 all getting through. The fix reserves a slot with one guarded increment and hands it back when a call is over the limit, so the budget is never exceeded. It is a patch change. A call can be refused when it would have just fit.

Fixed before any release: org invitations could be accepted by any signed in user, and an org admin could promote themselves to owner. DELETE /delegations/:id on the admin API never wrote the shared revocation denylist, so MCP tokens tied to a revoked delegation stayed valid on other instances. Approval hashes treated NaN and Infinity like null.

What is new

  • Devices as principals: registry, pre shared key, public key or TLS thumbprint credentials, enrollment with claim codes and bulk tokens, live revocation, and signed offline policy bundles (1 hour default, 24 hour cap). theauth device, REST routes and a dashboard Devices page.
  • Signed revocation snapshots for offline devices. With devices.revocations set, issueBundle and GET /device/bundle return a signed list of the owner's revoked and suspended device ids next to the policy bundle. verifyDeviceBundle refuses a bundle with revoked when the device is listed, and with stale_revocations when the snapshot is missing, expired or older than maxAgeSeconds. verifyRevocationSnapshot answers membership for peers. The Go package iot/device verifies the same format against shared vectors.
  • Device attestation verifiers for the enrollment hook. Each one refuses on any doubt and uses Web Crypto only.
    • Android Key Attestation: createAndroidKeyAttestationVerifier and googleRevocationList, plus theauth device attest android. Tested against the real chains in google/android-key-attestation.
    • Apple App Attest: createAppleAppAttestVerifier and theauth device attest apple. Tested against Apple's own sample attestation and two real device recordings.
    • TPM 2.0 quotes: createTpm2QuoteVerifier and theauth device attest tpm. Tested against real Google Compute Engine vTPM quotes. This is not physical TPM hardware.
    • The IoT docs say what these do and do not cover.
    • The three verifiers refuse an empty string nonce. Before, an empty nonce passed the "nonce is missing" check, and a TPM quote with empty qualifying data would then match it (a patch change).
  • Robots: theauth ros2 export writes SROS2 and DDS Security permissions files. The XML validates against the sros2 schemas, and a gate (guardRobotCommand) fails closed and never waits on the network for a safety stop. Opt in path aware matching (resourceMatching: "path") so ros2:/fleet/* means what it says.
  • Step up authentication (RFC 9470) with acr, amr and auth_time, a passkey step up on the current session, and DPoP or mTLS bound agent tokens.
  • Approvals as a flow with distinct decision codes, a decide API and an approval.pending webhook. Input provenance (keyed hashes of what was in the agent's context) in the audit chain, rotating pseudonyms, and a verifier for the Go head checkpoint that finally lets TypeScript see tail truncation of a Go chain.
  • Quorum approvals. approval.request({ requiredApprovals: 2 }) requires N distinct approvers, from 1 to 10 (default 1). Approvers must differ from the requester and from each other, one denial ends the request, and each approval writes its own audit row. Argument binding, single spend and expiry apply to the whole quorum. The admin API takes requiredApprovals, the dashboard inbox shows "1 of 2 approvals", and the approval.pending payload adds requiredApprovals and approvalsReceived. A new approval.vote event reports progress. Migration 0013 adds the required_approvals column and the theauth_approval_votes table.
  • Per model database hooks. databaseHooks takes before and after hooks for create and update on user, session and account. A before hook can return false to abort or { data } to replace allowed fields. It fails closed on a throw, a timeout or a malformed result (DatabaseHookError). after hooks run once the row is committed and cannot break the write. Hooks run outside every single use claim statement, so magic links, OTP codes, OAuth state and refresh rotation stay atomic.
  • Bring your own Drizzle. database: { drizzle, dialect } takes an existing Drizzle instance for "sqlite", "postgres" or "mysql" instead of a URL. It uses the same DatabaseOpener seam, migrations use the dialect, and skipMigrations works as before.
  • Store kernel and contract suite. drizzle-kernel.ts wraps conditional claims so each claim is decided by the row count of its conditional statement. StoreConflictError reads driver codes for the nine unique index conflicts and keeps the text match as a fallback. @glinr/theauth-test-utils adds a ./store-contract subpath with runStoreContract, which covers claim races with 24 parallel callers, unique conflicts and audit chain order for any backend. Commit f7238b3 runs the store contract suite in the database matrix.
  • Secondary storage: mongoStorage(collection) for MongoDB 4.4+, sqlStorage({ dialect, run }) for any SQL database including Microsoft SQL Server, and kyselyStorage(db, { dialect, CompiledQuery }) for any Kysely dialect. None adds a dependency, since you pass your own client. All keep exact per key counters and follow the same SecondaryStorage contract as the memory, database and Redis backends. Also fixes redisStorage().incr(), which threw on a key that held plain text.
  • Importers: supabase and workos sources for the user importer and theauth migrate. Supabase reads auth.users rows (JSON or CSV, with optional auth.identities) and keeps bcrypt hashes for lazy migration. WorkOS reads List users API output and accepts an optional hash file from support, because the API returns no hashes. Guides at migrate/from-supabase and migrate/from-workos.
  • OTP senders: vonageOtpSender and plivoOtpSender, next to twilioOtpSender.
  • Client bindings: session refetch on window focus, tab visibility, reconnect and interval, plus hydrateSession(initial) on createSessionStore. The React provider, Vue plugin, Svelte client and the new Solid helper use it. createSolidAuth wraps the store as Solid accessors without depending on solid-js. Refetch runs only while something is subscribed, shares one request across overlapping refreshes, and can be stopped.
  • Managed client bindings (React, Vue, Svelte) now confirm the session with GET /auth/session, and sign out calls POST /auth/sign-out so the session is revoked on the server.
  • UI, Expo, Electron and dashboard callers now call routes the core handler serves. Before, these calls answered 404 against a TypeScript server.
  • Comparison pages now carry dated, sourced facts, and there is a new Keycloak page. The better-auth and paid platform comparisons were corrected against their own documentation (81bb584).
  • Python guards for LangGraph, CrewAI and the OpenAI Agents SDK in theauth.integrations, tested against the real frameworks. The old recipe in the docs used a package that is not a dependency and had never run; a test now runs every Python block on that page.
  • ROS 2 export verified on a real system: with ROS_SECURITY_STRATEGY=Enforce on ROS 2 Humble (Fast DDS 2.6.12, sros2 0.10.9), an allowed topic flows, a topic outside the policy is refused for publisher and subscriber, and a gated command topic is refused for a normal enclave. That run found that an exported policy alone could not start any node (its own rosout and parameter endpoints were denied), so the CLI now adds a node baseline by default. The docs say exactly what was and was not run.
  • theauth doctor --security, framework helpers for the Vercel AI SDK and OpenAI Agents SDK, a generated OpenAPI contract with drift tests, and Go and Python clients that match it.
  • MySQL now applies the whole migration chain and passes the dialect suite on a real server (MySQL 8.4.11). The gate stays on until a CI leg runs it.
  • Single-use repositories for 20 claim sites (commit 746da30). The places that spend a single-use value now go through shared single-use repositories.
  • Resumable, idempotent gdpr.deleteUser. It runs as ordered steps with a progress marker, so a crash or database error halfway is finished by calling it again, and two concurrent calls leave one clean result. Audit erasure writes each audit.erasure record once. gdpr.anonymizeUser applies its credential deletes and user update as one atomic batch, and organization.remove is one atomic batch. Deleting a user also revokes the delegation links their agents give or receive, cascading downstream, and keeps the revoked rows so downstream grants stop working.
  • Quorum follow-ups for Prisma and the CLI. The Prisma adapter gains requiredApprovals on TheAuthApprovalRequest, a TheAuthApprovalVote model, and castApprovalVote and listApprovalVotes, with the same single vote guarantee as core. A new theauth approvals command (list, show, approve, deny, request with --required-approvals) drives the admin API. The Python and Go clients send and read the quorum fields. A fix stops the completing call from reporting every counted approver when concurrent votes pushed the count past the quorum.
  • SPIFFE workload identity over HTTP, with audit rows. With devices.spiffe set, the handler serves POST /device/spiffe/verify, POST /devices/spiffe/verify, POST /devices/spiffe/token and POST /devices/:id/spiffe. Minting and linking are admin only. An X.509 chain is never read from the body of the device route, only from your clientCertificate callback or the one header you name in trustedProxyHeader (off by default). Every route is rate limited and fails closed. Every verification outcome is written to the audit log as device.spiffe.authenticate or device.spiffe.verify when it maps to a device or agent, with the SPIFFE ID, failure code and certificate thumbprint, never the certificate or token. The dashboard Devices page lists SPIFFE identities and can link one.
  • Device fleet conformance kit at @glinr/theauth/testing/devices. createDeviceFleet({ size }) enrolls simulated devices against a real in-memory theAuth through the real HTTP handler, with a virtual clock. runDeviceConformance(fleet) checks enrollment, assertions, bundle and revocation snapshot verification, offline and online use, clock skew, rollback and revocation during a session. Measured p50 and p99 at 1000 devices are in docs/device-conformance-kit.mdx.
  • Hot path indexes, migration 0014-hot-path-indexes. It adds indexes for agent lookup by token hash, active agents per owner, permissions per agent, delegation links in both directions, the hourly rate limit read and the pending approval list. Without them these lookups scanned their table on SQLite and Postgres. Along with reused crypto keys, cheaper canonicalization and matching, and fewer queries on authorize and admin lists, the hot paths are faster with the same decisions. Each fast path is pinned to the code it replaced by tests. The numbers below come from one laptop, an Apple M4 Max under load, using SQLite through better-sqlite3, so they show direction and rough size, not a figure for your deployment. Taken from docs/performance.mdx, with a SQLite file of 50,000 agents, 200,000 permissions and 50,000 delegation links: authorize with a direct permission went from 4.10 ms to 0.077 ms, authorize through a three hop delegation chain from 9.88 ms to 0.36 ms, the token hash lookup from 5.33 ms to 0.12 ms, and the admin pending approvals list (100 quorum requests) from 2.29 ms to 0.51 ms. Canonical JSON for the approval hash on a 20 row payload went from 38.6 us to 10.9 us. One result got slightly worse: an offline device bundle decision with two permissions is about 7 percent slower, because the new colon matcher costs a little more on very short inputs. The DPoP proof path did not change, since its key is new on every request.
  • Cloudflare and Paybin providers. createCloudflareProvider (Sign in with Cloudflare, profile from the Cloudflare API /user, basic or post client auth) and createPaybinProvider (Paybin OpenID Connect with PKCE), both in @glinr/theauth/auth, with provider pages.
  • Nitro and Waku integration recipes, with no new package. The recipes run against the real frameworks.
  • libSQL provider: database: { provider: "libsql", url, authToken? } for Turso and other libSQL servers, or a file: URL, backed by the optional @libsql/client peer. It migrates with the SQLite schema. A Turso, Neon and Supabase page covers connection modes and SSL.
  • Id generation: advanced.database.generateId picks how user, session and OAuth account ids are made. "uuid" (default), "uuidv7" (time ordered, RFC 9562) or a function. Results are validated (1 to 191 characters). Database generated ids throw THEAUTH_ID_UNSUPPORTED, because every table stores and references ids as text. Exports generateUuidV7 and IdGenerationError.

Breaking changes

Each has a changeset and a section in docs/upgrading-to-2.mdx. The ones most likely to hurt: self service API keys can only carry permissions the user holds (capped by the creator's org roles when the org module is on, and an empty list otherwise; the org check is an exact match, so a role entry like agents:* does not cover agents:read), the admin DELETE /delegations/:id now answers 204 like the core route instead of 200 with a body, org and apiKeys handlers need an authenticate resolver, approval hashes change for arguments with <, >, &, U+2028, U+2029 or astral keys, dashboard audit results use hasMore instead of total, and adapter peer ranges now allow core below 3.0.0.

Added in waves 12 and 13:

  • SessionStore.refresh() now returns a promise, and SessionStore.signOut() returns Promise<StoreActionResult>. Code that treats either as synchronous must await it.
  • The default sign-in and sign-up routes for the client bindings are now /auth/username/sign-in and /auth/username/sign-up, and the first argument is sent as username. Before, they called /auth/sign-in and /auth/sign-up, which the core never served. If you served your own /auth/sign-in or /auth/sign-up for these bindings, set signInPath, signUpPath and identifierField (React: the managed prop; Vue and Svelte: the plugin or client options). Expo and Electron take the same three options, and apps that relied on /sign-in/email and /sign-up/email must set them.
  • Attestation evidence without a nonce is refused unless attestation.requireNonce is false. The enrollment hook input now carries credentialKind and credentialKeyThumbprint.
  • TwoFactorVerify posts { code } to /auth/2fa/verify, and a backup code goes in the same field. OAuthButtons navigates to /auth/oauth/authorize/:provider, and the server builds the callback URL.
  • The dashboard Users, Permissions, Settings and MCP Servers pages call routes that only the CLI dev server serves. Against a server without them, those pages show a "does not serve" message. Revoking an agent now uses DELETE /agents/:id.
  • All SMS senders time out after 10 seconds (timeoutMs), and their errors carry only the HTTP status and vendor error code, not the response body.
  • SCIM group PUT now removes only the members missing from the list and adds only the new ones. Before, it deleted and re-inserted every member, which dropped roles other than member.
  • Run migration 0013 (approval quorum) before deploying.

Also in this refresh:

  • Migration 0014 (hot path indexes) is additive. createTheAuth applies it, or run theauth db up.
  • Session creation refuses banned users (ban expiry honored) with a generic UserBannedError and writes a denied sign_in audit row. This covers password, username, magic link, passkey, OAuth, SAML and SSO sign-ins.
  • User ids starting with [deleted- are reserved. user.create rejects them.
  • Anonymized ids are now an HMAC-SHA256 (128 bits) under a per-instance secret (hmacKey, else the stored audit secret). An id computed the old way, an unsalted SHA-256 prefix, no longer matches.

What I ran

Typecheck for core, cli, dashboard, mcp, gateway and the adapters. Every new or changed test file plus the related areas (about 200 core files), every adapter, the dashboard and cli suites. The dialect suites ran for real against MySQL 8.4.11 and Postgres 14, including parallel single use claims. The pre push hook ran the whole core suite. New tests were run six times in parallel to catch flakes.

For the commits since the last refresh (746da30 to 0231034), the commit messages, changesets and docs record these runs and nothing more. The hot path numbers in docs/performance.mdx come from the micro benchmarks and benchmarks/scale.mjs on SQLite, one laptop, with the load average near 14. The libSQL changeset says the store contract suite passes on a real libSQL file, both through the provider and through a bring your own drizzle-orm/libsql handle. The Nitro and Waku recipes run against the real frameworks. The migration test asserts the query plans before and after 0014. The equivalence tests named in docs/performance.mdx compare each fast path with the code it replaced. The commit messages for 0231034 and 1ec0e34 record a test change and generated file fixes, with no run results.

For the wave 12 and 13 commits, the commit messages and changesets record no runs beyond the fixture tests named under device attestation: the Android chains, Apple's sample and two device recordings, and the Google Compute Engine vTPM quotes. The store contract suite is wired into the database matrix (f7238b3), and the commit messages do not record its results.

Not verified

Postgres 16 and 17, MariaDB and older MySQL versions. ROS 2 distros other than Humble, other DDS middleware, rclcpp nodes, certificate expiry and the runtime gate node. The Python snippets in the integration docs and the rclcpp sketch. TinyGo builds of the Go device client beyond the four smoke targets in the Go PR. A Zenoh exporter does not exist yet. SAML is still hand written code with no external audit, so I would call it experimental. The robotics pages make no safety or compliance claims.

Also not verified:

  • Apple App Attest on devices other than the two recordings, and TPM hardware other than the Google Compute Engine vTPM quotes. Android devices beyond the google/android-key-attestation chains.
  • The Supabase and WorkOS importers, the Vonage and Plivo senders, and the Mongo, SQL and Kysely secondary storage backends against live services. The changesets record no live run for them.
  • Quorum approvals and database hooks against a live database. The commit messages record no run.
  • The hot path timings on Postgres and MySQL. The numbers in docs/performance.mdx are SQLite only.
  • Resumable GDPR erasure, atomic org remove, the Prisma quorum adapter and the approvals CLI against a live database. The changesets record no live run.
  • SPIFFE routes, the Cloudflare and Paybin providers and the id generation option. The changesets record no run for them.

Versions this merge publishes

The branch already carries the version bump (changeset version, two commits at the end). When main CI is green, publish.yml publishes 29 packages whose version differs from npm:

  • @glinr/theauth 1.3.0 to 2.0.0 (npm has 1.2.0) and @glinr/theauth-mcp 1.2.0 to 2.0.0 (npm has 1.1.1).
  • The ten adapters (astro, express, fastify, hono, nestjs, nextjs, nuxt, solidstart, sveltekit, tanstack) 5.1.0 to 6.0.0, and @glinr/theauth-nextjs-auth 0.2.0 to 1.0.0.
  • Minors: cli 1.3.0, client 1.2.0, gateway 4.2.0, prisma 4.1.0, plugin-telemetry 4.1.0, dashboard 0.4.0, ui 0.4.0, react 0.8.0, vue 0.4.0, svelte 0.4.0, expo 0.5.0, electron 0.4.0, test-utils 0.3.0, create-theauth-app 0.6.0.
  • Patches: email 4.1.1, plugin-discovery 4.0.2.
  • Not auto published: conformance 0.3.0, agent-frameworks 0.2.0 and the theauth alias 0.2.7. Publish those by hand if wanted. The MCP Registry entry (packages/mcp/server.json, 2.0.0) must be published after the npm publish of mcp 2.0.0.

Core 1.2.1 (security patch for 1.x) is a separate branch, release/patch-1.2.1-2026-10-19, not part of this PR.

Needs a decision

The 2.0 version bump and whether to cut a 1.2.1 patch first.

Whether the client route default change (/auth/username/sign-in) is documented as breaking for 2.0 only, or also shipped as a 1.2.x patch.

…family revoke, step up follow ups and stricter device bundles
…list enrollment tokens and share one delegation revoke
…re contract suite, Mongo and SQL secondary storage, Supabase and WorkOS importers, Vonage and Plivo OTP senders
}

export function createSessionStore(options: SessionStoreOptions = {}): SessionStore {
const base = (options.basePath ?? "/api/theauth").replace(/\/+$/, "");
const BYTES_PER_CHAR = 4;

const CREATE_INDEX =
/^CREATE\s+(UNIQUE\s+)?INDEX\s+(?:IF NOT EXISTS\s+)?(\w+)\s+ON\s+(\w+)\s*\(([^)]*(?:\([^)]*\)[^)]*)*)\)\s*$/i;
export function createHttpGuard(options: HttpGuardOptions): HttpGuard {
const doFetch = options.fetch ?? fetch;
const action = options.action ?? "execute";
const url = `${options.baseUrl.replace(/\/+$/, "")}/authorize/token`;
command: RobotCommand,
): Promise<{ allowed: true; auditId?: string } | RobotGuardResult<never>> {
const doFetch = options.fetch ?? fetch;
const url = `${options.baseUrl.replace(/\/+$/, "")}/authorize/token`;
…ure, atomic org remove, Prisma quorum, approvals CLI and client quorum fields
…on and matching, fewer queries on authorize and admin lists
…ces, declare the hot path indexes in the schemas

function chainOf(input: Uint8Array[] | string): Uint8Array[] | null {
if (typeof input !== "string") return input;
const blocks = input.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
Comment on lines +120 to +122
for (const block of pem.match(
/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g,
) ?? [pem]) {
…libsql provider, id generation, Cloudflare and Paybin providers, Nitro and Waku recipes
…te paths, fix name and metadata replacement on magic link and email otp sign-ups
…ce attestation, a kysely store kernel, and verified email linking

Core email and password module with client presets, Effect, Encore, Convex and Lynx docs, hosted database opt-in tests, and the react context split.
Apple App Attest assertions and receipts, TPM credential activation and certify, attestation constraints in authorize and signed bundles.
Audit repository and an internal Kysely kernel verified on SQLite, Postgres, MySQL and MSSQL.
One Tap, magic link and email OTP no longer log in to or claim an unverified account without clearing its credentials.
Audit text is scrubbed of NUL before hashing, MySQL increment reads back the row it updated, and the lockfile is refreshed.
const cols = (pk[2] as string).split(",").map((c) => c.trim());
let bytes = 0;
for (const col of cols) {
const m = new RegExp(`${col.replace(/[[\]]/g, "\\$&")} (NVARCHAR\\((\\d+)\\)|BIGINT)`).exec(
Applies the pending changesets with changeset version. Core lands on 2.0.0.
Versions below are the previous version on this branch (core, mcp, gateway and
create-theauth-app were already ahead of npm) and the new one.

- @glinr/create-theauth-app: 0.5.0 to 0.6.0
- @glinr/theauth: 1.3.0 to 2.0.0
- @glinr/theauth-astro: 5.1.0 to 6.0.0
- @glinr/theauth-cli: 1.2.0 to 1.3.0
- @glinr/theauth-client: 1.1.1 to 1.2.0
- @glinr/theauth-conformance: 0.2.0 to 0.3.0
- @glinr/theauth-dashboard: 0.3.0 to 0.4.0
- @glinr/theauth-electron: 0.3.0 to 0.4.0
- @glinr/theauth-email: 4.1.0 to 4.1.1
- @glinr/theauth-expo: 0.4.0 to 0.5.0
- @glinr/theauth-express: 5.1.0 to 6.0.0
- @glinr/theauth-fastify: 5.1.0 to 6.0.0
- @glinr/theauth-gateway: 4.1.0 to 4.2.0
- @glinr/theauth-hono: 5.1.0 to 6.0.0
- @glinr/theauth-mcp: 1.2.0 to 2.0.0
- @glinr/theauth-nestjs: 5.1.0 to 6.0.0
- @glinr/theauth-nextjs: 5.1.0 to 6.0.0
- @glinr/theauth-nextjs-auth: 0.2.0 to 1.0.0
- @glinr/theauth-nuxt: 5.1.0 to 6.0.0
- @glinr/theauth-plugin-discovery: 4.0.1 to 4.0.2
- @glinr/theauth-plugin-telemetry: 4.0.0 to 4.1.0
- @glinr/theauth-prisma: 4.0.0 to 4.1.0
- @glinr/theauth-react: 0.7.1 to 0.8.0
- @glinr/theauth-solidstart: 5.1.0 to 6.0.0
- @glinr/theauth-svelte: 0.3.0 to 0.4.0
- @glinr/theauth-sveltekit: 5.1.0 to 6.0.0
- @glinr/theauth-tanstack: 5.1.0 to 6.0.0
- @glinr/theauth-test-utils: 0.2.0 to 0.3.0
- @glinr/theauth-ui: 0.3.0 to 0.4.0
- @glinr/theauth-vue: 0.3.0 to 0.4.0
- theauth: 0.2.6 to 0.2.7
- @glinr/theauth-example-admin-approval-flow: 0.0.2 to 0.0.3 (private)
- @glinr/theauth-example-agent-accountability: 0.0.2 to 0.0.3 (private)
- @glinr/theauth-example-basic-agent: 0.0.15 to 0.0.16 (private)
- @glinr/theauth-example-migrate-from-auth0: 0.0.10 to 0.0.11 (private)
- @glinr/theauth-example-migrate-from-better-auth-agent-plugin: 0.0.10 to 0.0.11 (private)
- marquee-demo: 0.1.12 to 0.1.13 (private)
- playground: 0.1.1 to 0.1.2 (private)

Also updates the README package table and the version fields in packages/mcp/server.json.
Pin @vitest/coverage-v8 to 4.1.11 to match the installed vitest 4.1.11. The
caret range resolved 4.1.12 and left an unmet peer warning. Lockfile
refreshed.

The other unlisted dependencies from the knip run were already declared
(@tanstack/react-query in react and ui-headless, h3 in nuxt, vitest in
test-utils, @glinr/theauth in telemetry). server-only in nextjs-auth, the
dashboard package in cli and tailwindcss in dashboard were left alone.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
D Reliability Rating on New Code (required ≥ A)
D Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@thegdsks thegdsks changed the title feat: agent auth release branch with devices, robots, quorum approvals and client parity feat: agent auth 2.0 with devices, robots, quorum approvals, core email and password, and security fixes Oct 19, 2026
@thegdsks thegdsks self-assigned this Oct 19, 2026
@thegdsks
thegdsks merged commit d372d29 into main Oct 19, 2026
15 of 21 checks passed
@thegdsks
thegdsks deleted the release/agent-wave9-2026-10-18 branch October 19, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants