From 290e89779570d01d285e10191f00346cd1c576f0 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Fri, 7 Nov 2025 13:42:35 -0800 Subject: [PATCH] chore(rivetkit): auto-generate inspector token for engine driver --- .../cloudflare-workers/src/actor-driver.ts | 9 ++--- .../rivetkit/src/actor/instance/kv.ts | 1 + .../rivetkit/src/actor/instance/mod.ts | 33 ++++++++++++++++++- .../packages/rivetkit/src/inspector/utils.ts | 1 + .../packages/rivetkit/src/manager/driver.ts | 2 ++ .../packages/rivetkit/src/manager/router.ts | 1 + 6 files changed, 42 insertions(+), 5 deletions(-) diff --git a/rivetkit-typescript/packages/cloudflare-workers/src/actor-driver.ts b/rivetkit-typescript/packages/cloudflare-workers/src/actor-driver.ts index 1bace9e7af..dbb09e359b 100644 --- a/rivetkit-typescript/packages/cloudflare-workers/src/actor-driver.ts +++ b/rivetkit-typescript/packages/cloudflare-workers/src/actor-driver.ts @@ -6,10 +6,10 @@ import type { } from "rivetkit"; import { lookupInRegistry } from "rivetkit"; import type { Client } from "rivetkit/client"; -import type { - ActorDriver, - AnyActorInstance, - ManagerDriver, +import { + type ActorDriver, + type AnyActorInstance, + type ManagerDriver, } from "rivetkit/driver-helpers"; import { promiseWithResolvers } from "rivetkit/utils"; import { KEYS } from "./actor-handler-do"; @@ -239,6 +239,7 @@ export class CloudflareActorsActorDriver implements ActorDriver { // Persist data key return Uint8Array.from([1]); } + } export function createCloudflareActorsActorDriverBuilder( diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/instance/kv.ts b/rivetkit-typescript/packages/rivetkit/src/actor/instance/kv.ts index 1865bf4c54..d046f6bbab 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/instance/kv.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/instance/kv.ts @@ -1,6 +1,7 @@ export const KEYS = { PERSIST_DATA: Uint8Array.from([1]), CONN_PREFIX: Uint8Array.from([2]), // Prefix for connection keys + INSPECTOR_TOKEN: Uint8Array.from([3]), // Inspector token key }; // Helper to create a connection key diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts b/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts index ffc097b3d5..d79a4aa93c 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts @@ -24,7 +24,7 @@ import { serializeActorKey } from "../keys"; import { processMessage } from "../protocol/old"; import { CachedSerializer } from "../protocol/serde"; import { Schedule } from "../schedule"; -import { DeadlineError, deadline } from "../utils"; +import { DeadlineError, deadline, generateSecureToken } from "../utils"; import { ConnectionManager } from "./connection-manager"; import { EventManager } from "./event-manager"; import { KEYS } from "./kv"; @@ -104,6 +104,7 @@ export class ActorInstance { #schedule!: Schedule; // MARK: - Inspector + #inspectorToken?: string; #inspector = new ActorInspector(() => { return { isDbEnabled: async () => { @@ -218,6 +219,10 @@ export class ActorInstance { return this.#inspector; } + get inspectorToken(): string | undefined { + return this.#inspectorToken; + } + get conns(): Map> { return this.#connectionManager.connections; } @@ -309,6 +314,9 @@ export class ActorInstance { // Read and initialize state await this.#initializeState(); + // Generate or load inspector token + await this.#initializeInspectorToken(); + // Initialize variables if (this.#varsEnabled) { await this.#initializeVars(); @@ -831,6 +839,29 @@ export class ActorInstance { } } + async #initializeInspectorToken() { + // Try to load existing token + const [tokenBuffer] = await this.#actorDriver.kvBatchGet( + this.#actorId, + [KEYS.INSPECTOR_TOKEN], + ); + + if (tokenBuffer !== null) { + // Token exists, decode it + const decoder = new TextDecoder(); + this.#inspectorToken = decoder.decode(tokenBuffer); + this.#rLog.debug({ msg: "loaded existing inspector token" }); + } else { + // Generate new token + this.#inspectorToken = generateSecureToken(); + const tokenBytes = new TextEncoder().encode(this.#inspectorToken); + await this.#actorDriver.kvBatchPut(this.#actorId, [ + [KEYS.INSPECTOR_TOKEN, tokenBytes], + ]); + this.#rLog.debug({ msg: "generated new inspector token" }); + } + } + async #initializeVars() { let vars: V | undefined; if ("createVars" in this.#config) { diff --git a/rivetkit-typescript/packages/rivetkit/src/inspector/utils.ts b/rivetkit-typescript/packages/rivetkit/src/inspector/utils.ts index cd86ab686c..edb2b78daa 100644 --- a/rivetkit-typescript/packages/rivetkit/src/inspector/utils.ts +++ b/rivetkit-typescript/packages/rivetkit/src/inspector/utils.ts @@ -77,6 +77,7 @@ export function getInspectorUrl(runConfig: RunnerConfigInput | undefined) { export const isInspectorEnabled = ( runConfig: RunConfig, + // TODO(kacper): Remove context in favor of using the gateway, so only context is the actor context: "actor" | "manager", ) => { if (typeof runConfig.inspector?.enabled === "boolean") { diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/driver.ts b/rivetkit-typescript/packages/rivetkit/src/manager/driver.ts index a3ab26eb03..fe70445e96 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/driver.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/driver.ts @@ -44,11 +44,13 @@ export interface ManagerDriver { router: Hono, ) => void; + // TODO(kacper): Remove this in favor of standard manager API /** * @internal */ readonly inspector?: ManagerInspector; + // TODO(kacper): Remove this in favor of ActorDriver.getinspectorToken /** * Get or create the inspector access token. * @experimental diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/router.ts b/rivetkit-typescript/packages/rivetkit/src/manager/router.ts index 774a0099f8..d6c4c455b4 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/router.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/router.ts @@ -218,6 +218,7 @@ function addManagerRoutes( managerDriver: ManagerDriver, router: OpenAPIHono, ) { + // TODO(kacper): Remove this in favor of standard manager API // Inspector if (isInspectorEnabled(runConfig, "manager")) { if (!managerDriver.inspector) {