# Changelog ## Unreleased - Reject persistent storage logs paired with an in-memory primary object store, which loses cluster metadata and cold data on restart. - Stop nodes rejected with `pool.not_found` and report their namespace and pool instead of reconnecting indefinitely. Transient connection failures still retry. - Add `connection` to `@rivetkit/effect` action requests. It holds the caller's connection `id` and a `scope` that closes when the connection ends, and it is `None` for scheduled actions. - **Authentication configuration is now required.** Deployments that previously omitted `auth` must configure an explicit production secret before upgrading: ```yaml auth: admin_token: "${RIVET_ADMIN_TOKEN}" ``` Checked-in development environments continue to use the explicit `dev` token automatically. Rivet JWT verification, issuance, and key rotation are enabled by default. The issuer is derived from the leader datacenter's `public_url`; remove the former `issuer`, `verification_enabled`, and `leader_epoch` JWT settings. For an issuer URL migration, first declare the overlap with `accepted_issuers`, then increment `issuer_generation` when activating the new leader URL. Increment it for a signing-leader datacenter change even when both leaders use the same public URL. Keep the old issuer configured until `rivet auth jwt status` reports that its retirement deadline has passed. - To restore legacy unauthenticated access behavior for actor management and routing, set `auth.insecure_allow_unauthenticated: true`. The admin token remains required, and token issuance stays authenticated. - The Rust SDK now supports actor action sets containing up to 128 action types, increased from 16. TypeScript actor definitions remain unrestricted. - `rivetkit` no longer exposes `ctx.sql` on actor contexts. Migrate raw SQLite calls to `ctx.db` from `rivetkit/db`, and keep Drizzle setup on the `rivetkit/db/drizzle` subpath. Migration example: ```ts import { db } from "rivetkit/db"; const myActor = actor({ db: db(), actions: { listTodos: async (ctx) => { return await ctx.db.execute("SELECT * FROM todos ORDER BY created_at DESC"); }, }, }); ``` - `rivetkit` no longer exports the old concrete typed error classes from `rivetkit/actor/errors` such as `QueueFull`, `ActorNotFound`, and `ActionTimedOut`. The native runtime now standardizes on `RivetError` plus `group` and `code` so the same error shape survives HTTP, WebSocket, and bridge boundaries instead of depending on `instanceof` across runtimes. Migration example: ```ts try { await actor.someAction(); } catch (e) { if (e instanceof QueueFull) { // old path } if (isRivetErrorCode(e, "queue", "full")) { // new path } } ``` Common replacements: | Removed class | Use now | | --------------------------------- | ------------------------------------------------- | | `QueueFull` | `isRivetErrorCode(e, "queue", "full")` | | `QueueMessageTooLarge` | `isRivetErrorCode(e, "queue", "message_too_large")` | | `QueueMessageInvalid` | `isRivetErrorCode(e, "queue", "message_invalid")` | | `QueuePayloadInvalid` | `isRivetErrorCode(e, "queue", "invalid_payload")` | | `QueueCompletionPayloadInvalid` | `isRivetErrorCode(e, "queue", "invalid_completion_payload")` | | `QueueAlreadyCompleted` | `isRivetErrorCode(e, "queue", "already_completed")` | | `ActionTimedOut` | `isRivetErrorCode(e, "action", "timed_out")` | | `ActionNotFound` | `isRivetErrorCode(e, "action", "not_found")` | | `ActorNotFound` | `isRivetErrorCode(e, "actor", "not_found")` | | `ActorStopping` | `isRivetErrorCode(e, "actor", "stopping")` | | `ActorAborted` | `isRivetErrorCode(e, "actor", "aborted")` | | `IncomingMessageTooLong` | `isRivetErrorCode(e, "message", "incoming_too_long")` | | `OutgoingMessageTooLong` | `isRivetErrorCode(e, "message", "outgoing_too_long")` | | `InvalidEncoding` | `isRivetErrorCode(e, "encoding", "invalid")` | | `InvalidRequest` | `isRivetErrorCode(e, "request", "invalid")` | | `InvalidQueryJSON` | `isRivetErrorCode(e, "request", "invalid_query_json")` | | `RequestHandlerNotDefined` | `isRivetErrorCode(e, "handler", "request_not_defined")` | | `WebSocketHandlerNotDefined` | `isRivetErrorCode(e, "handler", "websocket_not_defined")` | | `FeatureNotImplemented` | `isRivetErrorCode(e, "feature", "not_implemented")` | | `Unsupported` | `isRivetErrorCode(e, "feature", "unsupported")` | Keep catching `UserError` when you intentionally throw user-facing application errors yourself. The removal only affects the built-in typed subclasses that used to wrap framework/runtime failures. - Restored `Registry.handler(request)` and `Registry.serve()` for the native serverless runner endpoint described in `.agent/specs/serverless-restoration.md`. The route surface is `/api/rivet`, `/api/rivet/health`, `/api/rivet/metadata`, and `/api/rivet/start`; user traffic still goes through the Rivet Engine gateway. - `Registry.start()` now starts the native envoy path only. Built-in `staticDir` serving is not wired through the native engine subprocess yet and remains a follow-up. - Restored the supported `rivetkit/test`, `rivetkit/inspector`, and `rivetkit/inspector/client` entrypoints. `rivetkit/test` now waits for the native envoy metadata endpoint instead of the removed TypeScript in-memory runtime. - Restored the zero-runtime `*ContextOf` helper types on the root `rivetkit` export so patterns like `ActionContextOf` work again. `PATH_CONNECT`, `PATH_WEBSOCKET_PREFIX`, `KV_KEYS`, `ActorKv`, `ActorInstance`, `ActorRouter`, `createActorRouter`, and `routeWebSocket` stay removed. - `rivetkit/driver-helpers` and `rivetkit/driver-helpers/websocket` stay removed. They only exposed internal runtime/router helpers; migrate to the public `rivetkit`, `rivetkit/client`, and engine-client APIs instead of importing package internals. - `rivetkit/topologies/*` stays removed. The topology helpers are deleted on this branch; keep custom coordinate/partition logic in app code if you still need it. - `rivetkit/dynamic` and `rivetkit/sandbox/*` stay permanently removed on this branch. There is no in-package replacement, so move those integrations out of `rivetkit` imports instead of waiting for a hidden subpath to come back.