Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Nov 7, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
rivetkit-serverless Ready Ready Preview Comment Nov 13, 2025 2:48am
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 13, 2025 2:48am
rivet-inspector Ignored Ignored Preview Nov 13, 2025 2:48am
rivet-site Ignored Ignored Preview Nov 13, 2025 2:48am

Copy link
Member Author

NathanFlurry commented Nov 7, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link

claude bot commented Nov 7, 2025

PR Review: Auto-generate inspector token for engine driver

Summary

This PR adds automatic inspector token generation and persistence for actors in the Engine driver. The token is generated once per actor, stored in KV storage, and retrieved via the new getInspectorToken method on the ActorDriver interface.


✅ Strengths

  1. Good security practice: Uses generateSecureToken() (cryptographically secure) for the Engine driver rather than generateRandomString() (Math.random-based)
  2. Proper persistence: Token is stored in KV storage and loaded on actor initialization
  3. Consistent pattern: Uses the existing KEYS pattern for KV storage organization
  4. Logging: Includes debug logs for token creation and loading
  5. Interface consistency: All drivers implement the new getInspectorToken method

🔍 Issues & Concerns

1. Security: Cloudflare Workers uses insecure token generation

// cloudflare-workers/src/actor-driver.ts:159
getInspectorToken(_actorId: string): string | undefined {
    // TODO: Inspector currently disabled. Need to implement a way to store the token in CF KV similar to the Engine driver.
    return generateRandomString();  // ⚠️ Uses Math.random(), not cryptographically secure\!
}

Impact: If the Cloudflare Workers inspector is ever enabled, it would use predictable tokens vulnerable to brute force attacks.

Recommendation: Either:

  • Return undefined to disable inspector auth (safer for now)
  • Use generateSecureToken() instead if you need a temporary token
  • Implement proper persistent token storage as the TODO suggests

2. Error handling: Synchronous invariants in async context

// drivers/engine/actor-driver.ts:941
getInspectorToken(actorId: string): string | undefined {
    const handler = this.#actors.get(actorId);
    invariant(handler, "handler does not exist in getInspectorToken");
    invariant(
        handler.inspectorToken,
        "handler.inspectorToken does not exist in getInspectorToken",
    );
    return handler.inspectorToken;
}

Concern: This method uses invariants that will throw if:

  • The actor hasn't been initialized yet
  • The token hasn't been loaded from KV storage
  • The actor was cleaned up

Questions:

  • Can getInspectorToken be called before the actor is fully initialized?
  • What happens if there's a race condition between actor creation and inspector access?
  • Should this method wait for actorStartPromise if the handler exists but the actor isn't ready?

Recommendation: Consider either:

  • Document the preconditions clearly (must be called after actor is initialized)
  • Add defensive checks and return undefined instead of throwing
  • Make this async and await the actor start promise if needed

3. Missing test coverage

The inspector tests in driver-test-suite/tests/actor-inspector.ts are entirely skipped (describe.skip). This PR adds critical security functionality without test coverage.

Recommendation:

  • Add tests that verify token persistence across actor restarts
  • Test that different actors get different tokens
  • Verify that the same actor always gets the same token
  • Test the new getInspectorToken method directly
  • Consider unskipping the existing inspector tests or explaining why they remain skipped

4. Minor: Potential KV storage efficiency

// drivers/engine/actor-driver.ts:443
const [persistedValue, inspectorTokenValue] =
    await this.#runner.kvGet(actorId, [
        KEYS.PERSIST_DATA,
        KEYS.INSPECTOR.TOKEN,
    ]);

The code loads the token on every actor initialization. This is good for correctness, but:

  • Is there a case where the token could be cached in memory after the first load?
  • The token never changes, so subsequent loads seem unnecessary

Not critical, but worth considering for optimization if actor initialization is a hot path.


5. Documentation gaps

  • The new getInspectorToken method lacks JSDoc explaining when it should be called and what the preconditions are
  • The TODO comments in manager/driver.ts suggest this is part of a larger refactoring - it would help to understand the migration plan

🎯 Recommendations

Before merge:

  1. Fix the Cloudflare Workers security issue (use generateSecureToken or return undefined)
  2. Add error handling documentation or defensive checks to getInspectorToken
  3. Add at least basic tests for token generation and persistence

Follow-up work:

  1. Unskip and update the existing inspector tests
  2. Implement proper token storage for Cloudflare Workers driver
  3. Document the inspector token architecture and migration plan

📊 Code Quality Assessment

  • Code Style: ✅ Follows project conventions
  • Error Handling: ⚠️ Needs improvement (synchronous invariants, no defensive checks)
  • Security: ⚠️ Mixed (Engine driver is good, CF Workers is insecure)
  • Performance: ✅ Reasonable approach
  • Test Coverage: ❌ No new tests, existing tests skipped
  • Documentation: ⚠️ Missing JSDoc and architecture docs

Overall Assessment

This is a solid implementation for the Engine driver, but has some gaps in error handling, security (CF Workers), and testing. The core functionality looks correct, but needs hardening before production use.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 7, 2025

More templates

@rivetkit/actor

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/actor@3409

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/cloudflare-workers@3409

@rivetkit/core

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/core@3409

@rivetkit/db

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/db@3409

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/framework-base@3409

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/next-js@3409

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/react@3409

rivetkit

pnpm add https://pkg.pr.new/rivet-dev/rivet/rivetkit@3409

@rivetkit/sql-loader

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sql-loader@3409

@rivetkit/engine-runner

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner@3409

@rivetkit/engine-runner-protocol

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner-protocol@3409

commit: 7d62e3b

@NathanFlurry NathanFlurry force-pushed the 11-07-chore_rivetkit_auto-generate_inspector_token_for_engine_driver branch from a3b30a7 to 3c5d900 Compare November 8, 2025 22:25
@NathanFlurry NathanFlurry force-pushed the 11-06-chore_rivetkit_close_websockets_on_out_of_sequence_messages branch from 2368e4d to 0513dc4 Compare November 8, 2025 22:25
@claude
Copy link

claude bot commented Nov 8, 2025

Code Review

Summary

This PR adds auto-generation of inspector tokens for the Engine driver, introducing a new getInspectorToken method to the ActorDriver interface. Overall, the implementation is solid, but there are several areas for improvement.

Findings

🔴 Critical Issues

1. Security Issue in CloudFlare Driver (cloudflare-workers/src/actor-driver.ts:161)

  • Issue: The CloudFlare driver is using generateRandomString() instead of generateSecureToken()
  • Impact: generateRandomString() uses Math.random() which is NOT cryptographically secure and should never be used for authentication tokens
  • Recommendation: Either implement proper token storage/retrieval for CloudFlare (as the TODO suggests) or return undefined to disable inspector auth until properly implemented
// Current (INSECURE):
return generateRandomString();

// Better temporary solution:
return undefined; // Disable auth until properly implemented

// Or implement proper storage like Engine driver

🟡 Medium Priority Issues

2. Interface Contract Violation (drivers/engine/actor-driver.ts:941-948)

  • Issue: The getInspectorToken method uses invariant assertions that will throw if conditions aren't met, but the interface signature suggests it can return undefined
  • Impact: If this method is called before an actor is initialized, it will throw instead of gracefully returning undefined
  • Recommendation: Handle edge cases gracefully:
getInspectorToken(actorId: string): string | undefined {
    const handler = this.#actors.get(actorId);
    if (\!handler?.inspectorToken) {
        logger().warn({ actorId, msg: "inspector token requested for uninitialized actor" });
        return undefined;
    }
    return handler.inspectorToken;
}

3. Race Condition Risk (drivers/engine/actor-driver.ts:462-483)

  • Issue: Token generation happens inside the actor initialization block, but there's a potential race where getInspectorToken could be called between handler creation (line 440) and token initialization (line 465/472)
  • Impact: Brief window where inspectorToken could be undefined even for an initialized handler
  • Recommendation: Initialize inspectorToken field in the handler object at line 438:
handler = {
    actorStartPromise: promiseWithResolvers(),
    persistedData: undefined,
    inspectorToken: undefined, // Explicitly initialize
};

4. Missing Usage of New Method

  • Issue: The new getInspectorToken method is defined across all drivers but never called anywhere in the codebase
  • Impact: Dead code that isn't tested or used
  • Recommendation: Either implement the calling code in this PR or add a GitHub issue tracking where this will be integrated

🟢 Minor Issues

5. Typo in TODO Comment (manager/driver.ts:57)

  • getinspectorToken should be getInspectorToken (capital I)

6. Inconsistent Token Storage Pattern (drivers/engine/actor-driver.ts:443-447)

  • Observation: Loading both persisted data and token together is good, but the code could be more resilient
  • Recommendation: Add error handling for corrupt token data:
if (inspectorTokenValue \!== null) {
    try {
        const decoder = new TextDecoder();
        handler.inspectorToken = decoder.decode(inspectorTokenValue);
    } catch (err) {
        logger().warn({ actorId, err, msg: "failed to decode inspector token, regenerating" });
        handler.inspectorToken = generateSecureToken();
        // Save new token...
    }
}

7. Import Organization (cloudflare-workers/src/actor-driver.ts:9-13)

  • Good: Changed from type imports to mixed imports when adding generateRandomString
  • Suggestion: Follow CLAUDE.md convention of keeping imports at file top (this is already correct, just noting for consistency)

Test Coverage

No tests found for the new getInspectorToken method or token persistence logic. Recommended test cases:

  1. Token generation for new actors
  2. Token persistence and retrieval for existing actors
  3. Token stability across actor restarts
  4. Edge cases (uninitialized actors, corrupt token data)

Performance Considerations

Good: Token is generated once and cached in memory, only written to storage on first creation
Good: Token loading is batched with persisted data fetch (line 443-447)

Positive Observations

✅ Proper use of generateSecureToken() with cryptographically secure random values in Engine driver
✅ Good logging for debugging token creation/loading
✅ Consistent interface design across all drivers
✅ Proper storage key namespacing (KEYS.INSPECTOR.TOKEN)
✅ Follows the existing patterns for actor initialization

Recommendations

  1. Fix the CloudFlare security issue immediately - either implement proper storage or disable auth
  2. Make getInspectorToken more resilient to edge cases
  3. Add test coverage for token generation and persistence
  4. Document or implement where getInspectorToken will be called from
  5. Consider adding token rotation support in a future PR

Overall, solid implementation with a few critical issues that should be addressed before merging.

@claude
Copy link

claude bot commented Nov 8, 2025

PR Review: Auto-generate Inspector Token for Engine Driver

Summary

This PR implements automatic inspector token generation for the engine driver, storing tokens persistently in KV storage. This is a security and convenience improvement that ensures each actor has a unique, persistent token for inspector authentication.

Code Quality & Best Practices

✅ Strengths

  1. Good Security Practices

    • Uses generateSecureToken() with cryptographically secure random values (crypto.getRandomValues())
    • Tokens are base64url-encoded (URL-safe) with proper character replacement
    • Persistent storage ensures tokens remain stable across actor restarts
  2. Proper Error Handling

    • Uses invariant() checks in getInspectorToken() to catch programming errors early
    • Clear error messages for debugging
  3. Efficient Implementation

    • Batches KV reads for both persisted data and inspector token in a single call (line 444-447 in engine/actor-driver.ts)
    • Only writes token once during initial creation, not on every load
  4. Good Logging

    • Debug logs for both loading existing tokens and creating new ones
    • Includes relevant context (actorId) in log messages
  5. Clean Interface Design

    • getInspectorToken returns string | undefined to allow drivers to disable auth
    • Consistent implementation across all driver types

🔍 Areas for Improvement

1. Cloudflare Driver Security Issue ⚠️

// cloudflare-workers/src/actor-driver.ts:159-162
getInspectorToken(_actorId: string): string | undefined {
    // TODO: Inspector currently disabled. Need to implement a way to store the token in CF KV simplar to the Engine driver.
    return generateRandomString();
}

Issue: The Cloudflare driver generates a new random token on every call using generateRandomString() instead of persisting it. This means:

  • The token changes on every inspector access attempt
  • Inspector authentication will fail since the token is never consistent
  • Security is effectively broken for CF deployments

Recommendation: Either:

  • Return undefined to explicitly disable auth until persistence is implemented
  • Add a TODO comment explaining the current state more clearly
  • Or implement proper persistence before merging

Suggested fix:

getInspectorToken(_actorId: string): string | undefined {
    // TODO: Inspector auth disabled for Cloudflare. Implement persistent token storage
    // using CF KV similar to Engine driver before enabling.
    return undefined;
}

2. Race Condition in Token Creation

Lines 461-483 in engine/actor-driver.ts:

The token creation happens after the handler is added to the map. If multiple concurrent calls occur, they could both see inspectorTokenValue === null and create different tokens, with the last one winning.

Current flow:

handler = { /* ... */ };
this.#actors.set(actorId, handler);  // Handler added synchronously

const [persistedValue, inspectorTokenValue] = await this.#runner.kvGet(...);

if (inspectorTokenValue !== null) {
    handler.inspectorToken = decode(inspectorTokenValue);
} else {
    handler.inspectorToken = generateSecureToken();  // Race here
    await this.#runner.kvPut(actorId, [[KEYS.INSPECTOR.TOKEN, tokenBytes]]);
}

While the comment on line 433-435 mentions avoiding race conditions for handler creation, the token generation itself could still race.

Impact: Low - the race window is small, and the last write wins. Tokens would be inconsistent only during initial creation.

Recommendation: Consider using an atomic compare-and-swap or check-and-set operation if available, or document that this edge case is acceptable.

3. TypeScript Import Style Inconsistency

// cloudflare-workers/src/actor-driver.ts:9-14
import {
    type ActorDriver,
    type AnyActorInstance,
    generateRandomString,
    type ManagerDriver,
} from "rivetkit/driver-helpers";

The PR changes from import type to import with mixed type prefixes. While this works, it's slightly inconsistent with the previous style. Consider keeping the original structure if no runtime import is needed (though generateRandomString does need a runtime import).

4. Missing Test Coverage

The PR doesn't include tests for:

  • Token generation and persistence
  • Token retrieval for existing actors
  • Token consistency across actor restarts
  • getInspectorToken() behavior

Recommendation: Add tests to verify:

// Pseudocode
test("inspector token is generated once and persisted", async () => {
    const actor = await driver.loadActor(actorId, ...);
    const token1 = driver.getInspectorToken(actorId);
    
    // Reload actor
    const actor2 = await driver.loadActor(actorId, ...);
    const token2 = driver.getInspectorToken(actorId);
    
    expect(token1).toBe(token2);
    expect(token1).toHaveLength(43); // base64url encoded 32 bytes
});

Performance Considerations

Good: The implementation batches KV reads efficiently:

const [persistedValue, inspectorTokenValue] = await this.#runner.kvGet(actorId, [
    KEYS.PERSIST_DATA,
    KEYS.INSPECTOR.TOKEN,
]);

This avoids multiple round-trips to storage.

⚠️ Minor concern: Token encoding/decoding happens on every actor load:

const decoder = new TextDecoder();
handler.inspectorToken = decoder.decode(inspectorTokenValue);

While negligible for individual tokens, consider if this pattern scales across thousands of actors. This is acceptable for now.

Security Concerns

✅ Positive Security Aspects

  1. Cryptographically Secure Token Generation

    • Uses crypto.getRandomValues() for entropy
    • 32 bytes (256 bits) of randomness
    • Base64url encoding is URL-safe
  2. Timing-Safe Comparison (existing code)

    • Inspector middleware uses crypto.timingSafeEqual() to prevent timing attacks
    • Proper implementation in compareSecrets() function
  3. Per-Actor Tokens

    • Each actor gets its own unique token
    • Tokens are isolated in KV storage by actor ID

⚠️ Security Issues

  1. Cloudflare Driver Broken Auth (see above)

    • Generates new token on every call
    • Makes authentication ineffective
  2. No Token Rotation Mechanism

    • Once created, tokens never change
    • Consider adding an admin endpoint to regenerate tokens if compromised
  3. Token Stored in Plain Text

    • Tokens are stored as plain text in KV
    • This is likely acceptable for this use case, but worth documenting

Additional Observations

  1. Good TODO Comments

    • Line 226 in manager/router.ts: "Remove this in favor of standard manager API"
    • Line 52 in manager/driver.ts: "Remove this in favor of ActorDriver.getInspectorToken"
    • These indicate a thoughtful migration path
  2. Consistent KV Key Structure

    export const KEYS = {
        PERSIST_DATA: Uint8Array.from([1]),
        INSPECTOR: {
            TOKEN: Uint8Array.from([2]),
        },
    };

    Good use of namespacing for future expansion.

  3. FileSystem Driver Correctly Returns Undefined

    getInspectorToken(_actorId: string): string | undefined {
        return undefined;
    }

    This properly disables auth for the file system driver.

Recommendations

Must Fix Before Merge

  1. Fix Cloudflare driver - Return undefined instead of random string, or implement proper persistence

Should Address

  1. Add test coverage for token generation and persistence
  2. Document the race condition behavior or add proper synchronization

Nice to Have

  1. Consider adding token rotation capabilities in a follow-up PR
  2. Add metrics/logging for inspector token usage

Verdict

This is a solid improvement that adds per-actor inspector authentication with persistent tokens. The implementation is mostly clean and follows good patterns. However, the Cloudflare driver implementation is broken and needs to be fixed before merging.

Recommendation: Request changes to fix the Cloudflare driver, then approve.


Review conducted following CLAUDE.md conventions and security best practices.

@claude
Copy link

claude bot commented Nov 9, 2025

Code Review: Auto-generate inspector token for engine driver

I've reviewed PR #3409. Overall, the implementation is solid and follows good patterns. Here are my findings:

✅ Strengths

  1. Good separation of concerns: The inspector token is properly stored in KV storage with a dedicated key constant
  2. Proper persistence: Token is generated once and persisted, ensuring consistency across actor restarts
  3. Clean code organization: Follows the existing patterns in the codebase
  4. Secure token generation: Uses generateSecureToken() which employs crypto.getRandomValues() for cryptographically secure randomness

🔍 Code Quality & Best Practices

Positive:

  • Import changes in actor-driver.ts (changing from type to mixed imports) are appropriate since the functions are now being used at runtime
  • Proper use of TextEncoder/TextDecoder for string encoding/decoding
  • Debug logging is appropriate and follows the structured logging pattern with this.#rLog.debug()
  • Getter method follows TypeScript conventions

Minor suggestion:

  • Consider adding error handling around the TextDecoder.decode() call in case of corrupted data:
if (tokenBuffer !== null) {
    try {
        const decoder = new TextDecoder();
        this.#inspectorToken = decoder.decode(tokenBuffer);
        this.#rLog.debug({ msg: "loaded existing inspector token" });
    } catch (error) {
        this.#rLog.warn({ msg: "failed to decode inspector token, regenerating", error });
        // Fall through to generate new token
    }
}

⚠️ Potential Issues

  1. Missing consumption/usage: The inspectorToken getter is added but I couldn't find where it's actually being consumed in this PR. The TODO comment at manager/driver.ts:53 suggests this should replace ActorDriver.getInspectorToken, but:

    • There's no getInspectorToken method added to the ActorDriver interface
    • The token isn't being passed to the inspector or used for authentication
    • Consider adding the actual usage or documenting the follow-up work needed
  2. Race condition potential: #initializeInspectorToken() is called during actor startup, but there's no guarantee that kvBatchPut completes before the token might be accessed. Consider:

    • Awaiting the put operation (which you already do ✅)
    • Ensuring the token isn't accessed before initialization completes
  3. Token rotation: There's no mechanism to rotate or invalidate tokens. Consider whether this is needed for security best practices.

🔒 Security Considerations

Good:

  • Uses cryptographically secure random generation via crypto.getRandomValues()
  • Tokens are stored in KV storage, not in memory only
  • The generateSecureToken() function uses URL-safe base64 encoding

Concerns:

  • Token length: Default 32 bytes (43 chars after base64) is good, but this should be documented
  • No expiration: Tokens never expire, which could be a security concern for long-lived actors
  • No validation: When loading an existing token, there's no validation that it meets the expected format/length

🧪 Test Coverage

Major gap: I couldn't find any test files covering this functionality. Recommended tests:

  1. Test that a new actor generates a token on first initialization
  2. Test that an actor loads the same token on restart
  3. Test token persistence across actor hibernation/wake cycles
  4. Test behavior with corrupted token data in KV storage
  5. Integration test verifying the token is used for inspector authentication (once that's implemented)

Example test structure:

describe('Inspector Token', () => {
  it('should generate token on first initialization', async () => {
    const actor = await createActor();
    expect(actor.inspectorToken).toBeDefined();
    expect(actor.inspectorToken).toHaveLength(43); // base64 encoded 32 bytes
  });

  it('should persist token across restarts', async () => {
    const actor1 = await createActor();
    const token1 = actor1.inspectorToken;
    await actor1.stop();
    
    const actor2 = await createActor(); // same actor ID
    expect(actor2.inspectorToken).toBe(token1);
  });
});

📝 Documentation

  • The KV key constant has a comment explaining its purpose ✅
  • Consider adding JSDoc comments to the inspectorToken getter explaining:
    • What the token is used for
    • That it's auto-generated and persisted
    • That it's undefined before initialization completes

🎯 Recommendations

Before merging:

  1. Add test coverage for token generation and persistence
  2. Clarify in the PR description or code comments what the follow-up work will be (e.g., actually using this token for inspector authentication)
  3. Consider adding error handling for token decoding

Future considerations:

  1. Implement token rotation mechanism
  2. Add token validation when loading from storage
  3. Consider token expiration for security
  4. Complete the integration with the inspector authentication flow

Summary

The implementation is well-structured and follows good coding practices. The main concerns are:

  • Lack of test coverage (should be addressed before merge)
  • Incomplete feature (token is generated but not consumed)
  • Missing error handling for edge cases

The code quality is good, but the feature appears to be incomplete. Consider either completing the integration with the inspector authentication in this PR, or clearly documenting this as phase 1 of a multi-phase implementation.

@claude
Copy link

claude bot commented Nov 9, 2025

PR Review: Auto-generate inspector token for engine driver

Summary

This PR adds automatic generation and persistence of inspector tokens for actor instances. The token is generated on first actor initialization and persisted to KV storage for subsequent uses.


Code Quality & Best Practices ✅

Strengths:

  • Clean separation of concerns with dedicated #initializeInspectorToken() method
  • Proper use of KV storage following existing patterns (similar to #initializeState())
  • Consistent error handling and logging patterns
  • Good use of TypeScript type safety with optional chaining

Minor Issues:

  1. Import organization (cloudflare-workers/src/actor-driver.ts:6-13):

    • The change from type to regular imports looks correct, but verify that this doesn't increase bundle size unnecessarily for Cloudflare Workers
    • This change seems unrelated to the PR's main purpose - consider documenting why it's needed
  2. Whitespace changes (cloudflare-workers/src/actor-driver.ts:242):

    • Extra blank line added. While harmless, prefer to avoid unrelated formatting changes per CLAUDE.md guidelines

Potential Bugs & Issues ⚠️

  1. Race condition potential (actor/instance/mod.ts:317-318):

    • #initializeInspectorToken() is called during actor initialization
    • If multiple requests try to initialize the same actor simultaneously, could two instances generate different tokens?
    • Recommendation: Verify that actor initialization is properly serialized at the driver level, or add defensive checks
  2. Token lifecycle management (actor/instance/mod.ts:842-863):

    • No mechanism to rotate or invalidate tokens
    • No expiration time tracked
    • Consideration: Document token lifecycle expectations, especially for long-lived actors
  3. Missing error handling (actor/instance/mod.ts:844-847):

    • kvBatchGet could throw, but there's no try-catch
    • If KV is unavailable during initialization, the actor will fail to start
    • Recommendation: Consider graceful degradation or explicit error handling with context
  4. Token generation during initialization (actor/instance/mod.ts:314-318):

    • Token is generated before variables initialization
    • If the actor fails to initialize after token generation, the token is already persisted
    • Question: Should token generation be part of a transactional state write, or is it acceptable to have orphaned tokens?

Performance Considerations 🔍

  1. Additional KV read on every actor initialization (actor/instance/mod.ts:844-847):

    • Every actor cold start now requires an extra KV read
    • For high-frequency actor creation, this could add latency
    • Consideration: Could tokens be cached at a higher level (e.g., in runner metadata) to avoid repeated reads?
  2. TextEncoder/TextDecoder allocation (actor/instance/mod.ts:851-857):

    • New encoder/decoder instances created each time
    • Minor optimization: Consider reusing encoder/decoder instances if this code path is hot

Security Concerns 🔒

  1. Token storage security (actor/instance/mod.ts:858-860):

    • Tokens stored as plaintext in KV
    • Question: Is the KV storage encrypted at rest? Document security assumptions
    • Question: Should tokens be hashed before storage for defense-in-depth?
  2. Token exposure via getter (actor/instance/mod.ts:222-224):

    • Public getter exposes the token
    • Concern: Ensure calling code properly protects this value in logs and error messages
    • Recommendation: Add documentation warning about sensitive nature of this value
  3. Token entropy (actor/utils.ts:87-95):

    • Uses crypto.getRandomValues() with 32 bytes - excellent entropy ✅
    • Base64url encoding without padding - good for URL safety ✅
  4. No rate limiting on token validation:

    • If tokens are used for authentication, consider if brute-force protection is needed
    • Check if compareSecrets timing-safety is sufficient (it is timing-safe ✅)

Test Coverage ❌

Critical Issue:

  • No tests added for the new functionality
  • No existing tests found for inspector token generation/persistence

Recommended test coverage:

  1. Test token generation on first actor initialization
  2. Test token persistence and retrieval on subsequent initializations
  3. Test token uniqueness across different actors
  4. Test behavior when KV operations fail
  5. Test that token is properly exposed via the getter
  6. Integration test with the inspector authentication flow

Architecture & Design 🏗️

  1. TODO comments (manager/driver.ts:47, 53):

    • Multiple TODO comments about removing inspector token handling in favor of standard APIs
    • Question: How does this PR fit into the migration path described in the TODOs?
    • Recommendation: Update TODOs to reference this PR or clarify the migration plan
  2. Inconsistent token sources (drivers/engine/actor-driver.ts:97-121):

    • Engine driver overrides inspector token with runConfig.token
    • Now actors generate their own tokens
    • Concern: Potential confusion about which token is authoritative
    • Question: Should the engine driver integration be updated to use per-actor tokens?
  3. Missing ActorDriver interface update:

    • No method added to ActorDriver interface to retrieve inspector tokens
    • The TODO comment mentions ActorDriver.getinspectorToken (note typo: should be getInspectorToken)
    • Recommendation: Add interface method for consistency, or document why it's actor-level only

CLAUDE.md Compliance 📋

  1. ✅ Logging: Uses structured logging correctly (actor/instance/mod.ts:853, 861)

    • Messages are lowercase ✅
    • No parameter interpolation in message strings ✅
  2. ✅ Error Handling: Follows patterns (returning errors from failable functions)

  3. ❌ Testing: No test output piped to /tmp/ and grepped (no tests added)

  4. ❌ Formatting: Avoid running formatting yourself per guidelines, but changes look clean


Recommendations

Before merging:

  1. Add comprehensive test coverage for the new functionality
  2. Clarify the relationship with existing inspector token mechanisms
  3. Add defensive error handling for KV operation failures
  4. Document token lifecycle and security assumptions
  5. Consider impact on actor initialization latency
  6. Fix the typo in TODO comment: getinspectorTokengetInspectorToken

Consider for future:

  1. Token rotation mechanism
  2. Token expiration/TTL
  3. Audit logging for token generation
  4. Caching strategy to reduce KV reads

Overall Assessment

Code quality: Good - follows established patterns and conventions

Functionality: Solid implementation, but missing tests and unclear integration story

Risk level: Medium - impacts critical actor initialization path without test coverage

Recommendation: Request changes - primarily need tests and clarification on TODO migration path before merging.


Generated with Claude Code - Review based on CLAUDE.md conventions and RivetKit architecture

@claude
Copy link

claude bot commented Nov 13, 2025

Pull Request Review

Overview

This PR implements auto-generation of inspector tokens for the engine driver at the actor instance level. The token is generated once per actor and persisted in KV storage, which is a good approach for maintaining consistency across actor lifecycles.


Strengths

  1. Proper Token Persistence: The implementation correctly stores and retrieves the inspector token from KV storage, ensuring consistency across actor restarts and hibernation cycles.

  2. Secure Token Generation: Uses generateSecureToken() which employs crypto.getRandomValues() and URL-safe base64 encoding - appropriate for security-sensitive tokens.

  3. Initialization Ordering: The token is initialized early in the actor lifecycle (#initializeInspectorToken() called from start()) before variables, which is correct.

  4. Proper Logging: Debug logs for both token generation and loading paths aid in troubleshooting.

  5. Clean KV Key Management: New key constant (INSPECTOR_TOKEN) properly defined in kv.ts:4 alongside other keys.


⚠️ Issues & Concerns

1. Missing Token Usage Implementation

Severity: High

The PR adds a getter for inspectorToken (mod.ts:222-224) but there's no code that actually uses this token. Based on the codebase:

  • The engine driver currently uses runConfig.inspector.token() (actor-driver.ts:120)
  • There's no integration between the per-actor token and the inspector authentication
  • The TODO comment (manager/driver.ts:53) mentions ActorDriver.getinspectorToken but there's no such method

Recommendation: Either:

  • Add an ActorDriver.getInspectorToken(actorId) method that retrieves the token from the actor instance
  • Update the inspector middleware to use per-actor tokens instead of (or in addition to) global tokens
  • Document how this token is intended to be used

2. Error Handling Gap

Severity: Medium

The #initializeInspectorToken() method doesn't handle KV operation failures:

async #initializeInspectorToken() {
    const [tokenBuffer] = await this.#actorDriver.kvBatchGet(
        this.#actorId,
        [KEYS.INSPECTOR_TOKEN],
    );
    // No try-catch - if kvBatchGet fails, actor initialization fails

Recommendation: Add error handling or document that KV failures should bubble up and fail actor initialization (which may be the intended behavior).

3. Missing Tests

Severity: Medium

No tests verify:

  • Token generation on first initialization
  • Token persistence across actor restarts
  • Token retrieval from KV storage
  • Token uniqueness per actor

Recommendation: Add tests to tests/driver-engine.test.ts or create a dedicated inspector token test suite.

4. Type Safety Concern

Severity: Low

The inspectorToken getter returns string | undefined (mod.ts:222), but it's only undefined during the narrow window before initialization. After start() completes, it's always a string.

Consideration: Document this behavior or consider throwing if accessed before initialization.


🔍 Code Quality Observations

  1. Import Style Change (cloudflare-workers/actor-driver.ts:9-12): Changed from type imports to mixed imports. This is correct - you need non-type imports to use ActorDriver at runtime for the class implementation.

  2. Whitespace (cloudflare-workers/actor-driver.ts:242): Extra blank line added. Minor style inconsistency but not problematic.

  3. TODO Comments: Three TODO comments added referencing future refactoring (manager/driver.ts:47,53; manager/router.ts:221). Good context for future work.


🔒 Security Considerations

  1. Token Storage: Tokens stored in plaintext in KV. This is likely acceptable since KV storage is trusted, but worth documenting.

  2. Token Rotation: No mechanism for rotating tokens. Consider if this is needed for long-lived actors.

  3. Token Entropy: generateSecureToken(32) provides 256 bits of entropy, which is excellent.


📋 Testing Recommendations

// Suggested test cases
describe('Inspector Token', () => {
  test('generates unique token on first actor initialization', async () => {
    // Verify token is generated and persisted to KV
  });
  
  test('reuses existing token on actor restart', async () => {
    // Start actor, get token, restart actor, verify same token
  });
  
  test('different actors have different tokens', async () => {
    // Verify token uniqueness across actors
  });
});

📝 Documentation Needs

  1. Add comments explaining the purpose of per-actor inspector tokens
  2. Document the relationship between runConfig.inspector.token() and per-actor tokens
  3. Clarify the migration path from global tokens to per-actor tokens

Summary

The implementation is technically sound for generating and persisting inspector tokens at the actor level. However, the PR is incomplete without the actual usage of these tokens. The main blocker is the missing integration with the inspector authentication flow.

Recommendation: Either:

  1. Expand this PR to include the token usage implementation, or
  2. Add a clear TODO/issue reference explaining how these tokens will be consumed in a follow-up PR

The code quality is good, follows established patterns, and uses secure token generation. With tests and usage implementation, this would be ready to merge.


🤖 Generated with Claude Code

@NathanFlurry NathanFlurry force-pushed the 11-07-chore_rivetkit_auto-generate_inspector_token_for_engine_driver branch from 24368d6 to 7d62e3b Compare November 13, 2025 02:47
@NathanFlurry NathanFlurry force-pushed the 11-06-chore_rivetkit_close_websockets_on_out_of_sequence_messages branch from aaad3ae to 775d512 Compare November 13, 2025 02:47
@claude
Copy link

claude bot commented Nov 13, 2025

Code Review: Auto-generate Inspector Token for Engine Driver

Overview

This PR adds automatic generation and persistence of inspector tokens for actor instances. The token is stored in KV storage and reused across actor lifecycle events.


✅ Positive Aspects

  1. Secure Token Generation: Uses crypto.getRandomValues() with proper URL-safe base64 encoding in generateSecureToken() (actor/utils.ts:87-95)

  2. Proper Persistence: Token is stored in KV storage using a dedicated key (KEYS.INSPECTOR_TOKEN) and reloaded on actor restart, ensuring consistency

  3. Clean Separation: New KV key is properly namespaced with value [3] in kv.ts:4

  4. Getter Access: Public getter provides read-only access to the token (mod.ts:222-224)

  5. Follows Existing Patterns: Implementation mirrors the state initialization pattern already used in the codebase


🔍 Issues & Concerns

1. Missing Error Handling (Priority: Medium)

Location: mod.ts:842-863

The #initializeInspectorToken() method lacks error handling for KV operations. If kvBatchGet or kvBatchPut fails, the error will propagate uncaught.

Recommendation: Add try-catch with appropriate logging:

async #initializeInspectorToken() {
    try {
        const [tokenBuffer] = await this.#actorDriver.kvBatchGet(
            this.#actorId,
            [KEYS.INSPECTOR_TOKEN],
        );
        // ... rest of implementation
    } catch (error) {
        this.#rLog.error({ msg: "failed to initialize inspector token", error });
        throw error;
    }
}

2. Token Security - No Rotation Mechanism (Priority: Medium)

Location: mod.ts:842-863

Once generated, the token is never rotated. If compromised, there's no mechanism to invalidate it without deleting the entire actor state.

Recommendation: Consider adding:

  • Optional token rotation via an admin API
  • Timestamp-based expiration
  • Document the security implications in code comments

3. Missing Test Coverage (Priority: High)

Issue: No tests verify the new inspector token functionality

Recommendation: Add tests for:

  • Token generation on first actor start
  • Token persistence across actor restarts
  • Token retrieval via the getter
  • Behavior when KV operations fail
  • Token uniqueness across different actors

Example test structure:

describe('Inspector Token', () => {
    it('generates token on first start', async () => { /* ... */ });
    it('reuses token after restart', async () => { /* ... */ });
    it('generates unique tokens per actor', async () => { /* ... */ });
});

4. Inconsistent Import Style (Priority: Low)

Location: cloudflare-workers/src/actor-driver.ts:6-13

Changed from type imports to mixed imports, but this appears cosmetic and doesn't affect the functionality. However, it's inconsistent with the original style.

Before:

import type {
    ActorDriver,
    AnyActorInstance,
    ManagerDriver,
} from "rivetkit/driver-helpers";

After:

import {
    type ActorDriver,
    type AnyActorInstance,
    type ManagerDriver,
} from "rivetkit/driver-helpers";

Recommendation: Revert to consistent import type unless there's a specific reason for inline type modifiers.

5. TODO Comment Lacks Context (Priority: Low)

Location: inspector/utils.ts:80

// TODO(kacper): Remove context in favor of using the gateway, so only context is the actor

While this indicates planned refactoring, it doesn't explain how this PR fits into that future work.

Recommendation: Add a comment explaining the relationship:

// TODO(kacper): Remove context in favor of using the gateway, so only context is the actor
// Note: This PR adds per-actor token generation as an interim step toward that architecture

6. Missing Documentation (Priority: Medium)

Location: mod.ts:222-224

The public getter has no JSDoc explaining its purpose, when it might be undefined, or security implications.

Recommendation: Add documentation:

/**
 * Returns the inspector access token for this actor instance.
 * The token is automatically generated on first start and persisted across restarts.
 * 
 * @returns The inspector token, or undefined if inspector is disabled or not yet initialized
 * @experimental This API may change as we move to gateway-based inspector authentication
 */
get inspectorToken(): string | undefined {
    return this.#inspectorToken;
}

🎯 Functional Concerns

7. Race Condition Potential (Priority: Low)

Location: mod.ts:314-318

If #initializeState() and #initializeInspectorToken() both perform KV operations, there could be edge cases with parallel KV access, though the current implementation appears safe since they use different keys.

Verification Needed: Confirm that the KV driver properly handles concurrent operations to different keys from the same actor.

8. Token Not Used Yet? (Priority: High - Clarification Needed)

Observation: The PR generates and stores the token, but I don't see where it's actually used for authentication in the inspector.

Questions:

  • Is this PR part 1 of a multi-part change?
  • Where will the token validation occur?
  • How will the engine expose the token to users who need to access the inspector?

The TODO comments suggest this is transitional, but the relationship to the final architecture isn't clear.


📋 Architecture Questions

  1. Token Distribution: How will users/developers obtain the inspector token to authenticate? Is there an API endpoint planned?

  2. Engine Driver Integration: The comment at drivers/engine/actor-driver.ts:97-102 mentions this is a "HACK" that will be removed. How does this PR relate to that cleanup?

  3. Migration Path: For existing actors, will they all get new tokens on next start? Is that acceptable?


✅ Testing Recommendations

Since there are no existing tests for this feature, please add:

  1. Unit Tests (packages/rivetkit/tests/inspector-token.test.ts):

    • Token generation
    • Token persistence
    • Token uniqueness
  2. Integration Tests:

    • Actor restart with token reuse
    • KV failure scenarios
  3. Driver Tests:

    • Add inspector token test cases to existing driver test suites

📝 Suggestions for Follow-up PRs

  1. Implement token validation in inspector authentication
  2. Add admin API for token rotation
  3. Document the inspector authentication flow
  4. Remove the temporary HACK in engine driver (per existing TODO)

Summary

Overall Assessment: The implementation is solid and follows good patterns, but needs:

  • ⚠️ Error handling improvements
  • ⚠️ Test coverage (critical)
  • ⚠️ Documentation
  • ⚠️ Clarification on how tokens will be used

The code quality is good and consistent with the codebase style. The main concerns are the missing tests and unclear integration story with the rest of the inspector system.

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review

I've reviewed PR #3409 and have the following feedback:

Overview

This PR adds automatic inspector token generation for the engine driver. The implementation generates a secure token per actor instance and persists it in KV storage.


✅ Strengths

  1. Secure Token Generation: Uses generateSecureToken() which properly uses crypto.getRandomValues() for cryptographically secure random token generation (rivetkit-typescript/packages/rivetkit/src/actor/utils.ts:87-95).

  2. Persistence Strategy: Tokens are correctly persisted to KV storage and reloaded on subsequent actor initializations, ensuring tokens remain stable across actor lifecycles.

  3. Key Management: Added a new dedicated key constant INSPECTOR_TOKEN to the KEYS object (rivetkit-typescript/packages/rivetkit/src/actor/instance/kv.ts:4), following the existing pattern for KV keys.

  4. Initialization Order: Token initialization is called after state initialization but before vars initialization (rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts:318), which is appropriate.

  5. Logging: Appropriate debug logging for both loading existing tokens and generating new ones.


🔍 Issues & Recommendations

1. Import Organization (Minor - Style)

In cloudflare-workers/src/actor-driver.ts, the imports were changed from type imports to regular imports with inline type keywords:

import {
	type ActorDriver,
	type AnyActorInstance,
	type ManagerDriver,
} from "rivetkit/driver-helpers";

This change appears unrelated to the PR's purpose. According to CLAUDE.md, you should "Always add imports at the top of the file inside of inline within the function." However, this seems to refer to avoiding inline imports within functions, not the type import syntax change. This change is fine but consider keeping it in a separate formatting/cleanup commit.

2. Missing Test Coverage (Medium - Testing)

There are no tests for the new inspector token functionality. Consider adding tests that verify:

  • Token generation on first actor initialization
  • Token persistence and retrieval on subsequent initializations
  • Token remains stable across actor restarts
  • Token format/length validation

3. Error Handling (Low - Robustness)

The #initializeInspectorToken() method doesn't have explicit error handling for KV operations. While the operations may throw and propagate errors appropriately, consider:

  • What happens if kvBatchGet fails?
  • What happens if kvBatchPut fails after generating a new token?
  • Should there be retry logic or fallback behavior?
async #initializeInspectorToken() {
	try {
		const [tokenBuffer] = await this.#actorDriver.kvBatchGet(
			this.#actorId,
			[KEYS.INSPECTOR_TOKEN],
		);
		// ... rest of implementation
	} catch (error) {
		this.#rLog.error({ msg: "failed to initialize inspector token", error });
		throw error; // or implement fallback
	}
}

4. Token Security Considerations (Low - Security)

  • The token is stored in plaintext in KV storage. Depending on the security model, consider if this is appropriate or if encryption at rest is needed.
  • The token is exposed via the public getter get inspectorToken(). Ensure this doesn't create unintended exposure points.
  • Consider documenting the intended usage/access patterns for the inspector token.

5. Type Safety (Low - Type Safety)

The inspectorToken getter returns string | undefined. Consider:

  • Should the token always be defined after initialization? If so, make it non-optional and ensure it's always set.
  • If undefined is valid, document when/why it might be undefined.
get inspectorToken(): string | undefined {
	return this.#inspectorToken;
}

6. Documentation (Low - Documentation)

The new TODO comments added are helpful but consider:

  • Adding JSDoc comments to the inspectorToken getter explaining its purpose
  • Documenting the lifecycle of the inspector token
  • The TODOs reference future refactoring (e.g., "Remove this in favor of ActorDriver.getinspectorToken") - note there's a typo: should be getInspectorToken not getinspectorToken

🧪 CI/CD Status

The PR has a failing quality check in the JavaScript workflow. Please review and fix the failure before merging.


📝 Minor Issues

  • Extra blank line added at line 242 in cloudflare-workers/src/actor-driver.ts - this is fine but appears to be a formatting change unrelated to the PR.

Summary

The implementation is solid and follows good security practices for token generation. The main areas for improvement are:

  1. Add test coverage for the new functionality
  2. Consider error handling for KV operations
  3. Fix the failing CI check
  4. Add documentation for the inspector token API

Overall, this is a well-structured change that implements the intended functionality correctly. With the addition of tests and resolution of the CI failure, this would be ready to merge.

Recommendation: Request changes to add tests and fix CI before merging.

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 13, 2025

Merge activity

  • Nov 13, 8:47 PM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Nov 13, 8:48 PM UTC: CI is running for this pull request on a draft pull request (#3463) due to your merge queue CI optimization settings.
  • Nov 13, 8:50 PM UTC: Merged by the Graphite merge queue via draft PR: #3463.

@graphite-app graphite-app bot closed this Nov 13, 2025
@graphite-app graphite-app bot deleted the 11-07-chore_rivetkit_auto-generate_inspector_token_for_engine_driver branch November 13, 2025 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants