Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Oct 23, 2025

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

3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Oct 24, 2025 8:41pm
rivet-inspector Ignored Ignored Preview Oct 24, 2025 8:41pm
rivet-site Ignored Ignored Preview Oct 24, 2025 8:41pm

Copy link
Member Author

NathanFlurry commented Oct 23, 2025


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 Oct 23, 2025

PR Review: Path-based Actor Routing

Great work on implementing path-based routing for actors! The implementation is solid with excellent test coverage. Here are my findings:

✅ Strengths

  1. Excellent Test Coverage: Both Rust and TypeScript implementations have comprehensive unit tests covering edge cases (203 lines in Rust, 305 lines in TypeScript)
  2. Consistent Implementation: The parsing logic is mirrored well between Rust and TypeScript
  3. Backwards Compatibility: The fallback to header-based routing ensures existing functionality isn't broken
  4. Good Path Structure: The /gateway/actors/{id}/tokens/{token}/route/{path} pattern is intuitive and RESTful

🐛 Potential Issues

1. Typo in Header Constant (packages/guard/src/routing/pegboard_gateway.rs:13)

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Should be X_RIVET_NAMESPACE instead of X_RIVET_AMESPACE (missing 'N')

2. Token Validation Not Implemented

Both implementations have NOTE: Token validation implemented in EE comments. This means:

  • The token parameter is parsed but never validated in the OSS version
  • Potential security risk if tokens are expected to provide access control
  • Recommendation: Add documentation explaining that token validation is EE-only, or add basic validation in OSS

3. Query Parameter Routing Removed Without Migration Path

The PR removes query parameter fallbacks (x_rivet_target, x_rivet_actor, x_rivet_token) that were previously supported. While this simplifies the code, it could break existing clients using query params for routing.

  • Files: packages/guard/src/routing/mod.rs:83-91, pegboard_gateway.rs:65, runner.rs:71
  • Recommendation: Add deprecation notices in release notes if query params were publicly documented

🔒 Security Considerations

  1. Path Traversal Protection: Good validation to prevent double slashes and empty segments
  2. Fragment Stripping: Properly handled - fragments are stripped which is correct behavior for server-side routing
  3. URL Encoding: The implementations preserve URL encoding in the remaining path, which is correct
  4. Authentication Gaps:
    • Token parsing exists but validation is marked as "EE only"
    • Consider adding a warning log when tokens are present but not validated
    • The _token parameter in route_request_path_based is unused (prefixed with _), which could be confusing

🎯 Performance Considerations

  1. Early Return: Good pattern checking path-based routing first before falling back to headers
  2. String Parsing: Efficient single-pass parsing in both implementations
  3. No Regex: Using string operations instead of regex is a good performance choice

📝 Code Quality

  1. Duplicate Logic: The parseActorPath function is duplicated in Rust and TypeScript. Consider:

    • Adding integration tests to ensure both implementations stay in sync
    • Documenting the expected behavior in a shared spec
  2. Unused Imports: In routing/mod.rs:138, the parse_query_params function was removed but the import might need cleanup

  3. Documentation: Consider adding rustdoc/JSDoc comments explaining:

    • The routing precedence (path-based → header-based → fallback)
    • The expected path format with examples
    • When tokens are validated vs when they're ignored

🧪 Test Coverage

Excellent coverage for parseActorPath:

  • Valid paths (with/without tokens)
  • Query parameters and fragments
  • Trailing slashes
  • Special characters and URL encoding
  • Invalid paths (wrong prefix, missing route, too short, malformed)
  • Case sensitivity

Missing integration tests:

  • End-to-end tests for WebSocket routing via path
  • End-to-end tests for HTTP routing via path
  • Tests verifying fallback from path-based to header-based routing

🎨 Minor Code Style

  1. TypeScript Consistency: The TypeScript implementation uses let declarations and imperative style, while the Rust version is more functional. Both are fine, but consider functional patterns in TypeScript for consistency:
    const remainingPath = remainingBase.startsWith('/') 
      ? `${remainingBase}${queryString}`
      : `/${remainingBase}${queryString}`;

📋 Recommendations

  1. Fix the typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE
  2. Document token validation: Add comments explaining OSS vs EE behavior
  3. Add integration tests: Test the full routing pipeline
  4. Consider migration path: If query param routing was public, add deprecation notices
  5. Add tracing: Consider adding debug logs when path-based routing is triggered vs falling back to headers

Overall Assessment

This is a well-implemented feature with strong test coverage. The main concerns are the typo and clarifying the token validation behavior. The code is production-ready after addressing the typo.

Approval Status: ✅ Approved with minor fixes recommended

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 23, 2025

More templates

@rivetkit/actor

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

@rivetkit/cloudflare-workers

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

@rivetkit/core

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

@rivetkit/db

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

@rivetkit/framework-base

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

@rivetkit/next-js

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

@rivetkit/react

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

rivetkit

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

@rivetkit/sql-loader

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

@rivetkit/engine-runner

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

@rivetkit/engine-runner-protocol

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

commit: a5f5632

@NathanFlurry NathanFlurry force-pushed the 10-22-feat_core_allow_routing_traffic_to_actors_via_path branch from ed34c5a to 89114d1 Compare October 23, 2025 08:22
@claude
Copy link

claude bot commented Oct 23, 2025

PR Review: Path-Based Actor Routing

I've reviewed the changes in this PR that add path-based routing for actors. Overall, this is a well-implemented feature with excellent test coverage. Here are my findings:

✅ Strengths

  1. Excellent Test Coverage: Both Rust and TypeScript implementations have comprehensive test suites covering edge cases, invalid inputs, query parameters, fragments, and various path formats.

  2. Consistent Implementation: The parse_actor_path logic is duplicated between Rust and TypeScript with identical behavior, which is good for maintainability.

  3. Good Error Handling: Proper validation and error messages following the project's error handling patterns.

  4. Backward Compatibility: The PR maintains header-based routing as a fallback, ensuring existing integrations continue to work.

  5. Path Validation: Good checks for empty segments, double slashes, and malformed paths.

🔍 Issues Found

1. Typo in Header Constant (pegboard_gateway.rs:13)

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Should be X_RIVET_NAMESPACE (missing 'N'). This constant doesn't appear to be used in this PR, but the typo should be fixed.

2. Unused Parameters (pegboard_gateway.rs:19-27)

The route_request_path_based function has several unused parameters prefixed with _:

  • _token
  • _headers
  • _is_websocket

While the comment indicates token validation is implemented in EE, consider:

  • Adding a TODO comment if these will be used soon
  • Removing them if they won't be needed in the near term (YAGNI principle)
  • At minimum, document why they're present but unused

3. Fragment Handling Inconsistency

In parse_actor_path, fragments are stripped from the path:

let query_string = match (query_pos, fragment_pos) {
    (Some(q), Some(f)) if q < f => &path[q..f],  // Excludes fragment
    ...

While this is generally correct for routing, it's worth documenting this behavior explicitly since:

  • Fragments are client-side and shouldn't be sent to servers
  • The tests verify this behavior, which is good
  • A comment explaining why fragments are stripped would help future maintainers

💡 Suggestions

1. Security Considerations

Since this PR adds a new routing mechanism, consider:

  • Path Traversal: The current implementation looks safe, but adding a test case for path traversal attempts (e.g., ../../etc/passwd) would strengthen confidence
  • Actor ID Validation: Currently accepts any non-empty string. Consider if there should be format validation (length limits, character restrictions, etc.)
  • Token Security: The comment says "Token validation implemented in EE" - ensure this is properly documented for EE implementers

2. Logging Enhancement (mod.rs:54)

tracing::debug!(?actor_path_info, "routing using path-based actor routing");

Consider adding more context like the original path for debugging:

tracing::debug!(?actor_path_info, original_path = %path, "routing using path-based actor routing");

3. Code Duplication

The parse_actor_path function is duplicated between Rust and TypeScript. While this is sometimes necessary, consider:

  • Adding a comment referencing the other implementation
  • Including a test that verifies behavior matches (integration test)
  • Documenting that changes to one should be mirrored in the other

4. Edge Case: Very Long Paths

Consider adding tests and/or validation for:

  • Extremely long actor IDs or tokens
  • Paths with many segments (100+ levels deep)
  • URLs approaching maximum length limits

5. Performance Consideration (mod.rs:145-235)

The parse_actor_path function is called on every request. For high-throughput scenarios:

  • The string allocations (to_string(), format!()) could be optimized
  • Consider using Cow<str> for zero-copy cases
  • Not critical now, but worth noting for future optimization

📝 Minor Style Notes

  1. Line 13 in pegboard_gateway.rs: Fix the typo X_RIVET_AMESPACEX_RIVET_NAMESPACE

  2. Consistent Logging: Following CLAUDE.md conventions:

    • ✅ Using structured logging with ?actor_path_info
    • ✅ Lowercase messages
    • Consider adding more context fields for complex routing decisions
  3. Test Organization: The test files are well-organized with clear sections for valid/invalid cases. Excellent!

🔒 Security Assessment

✅ No security vulnerabilities identified in the defensive security context:

  • Proper input validation
  • No SQL injection risks (using structured queries)
  • No command injection vectors
  • Path traversal protection via segment-based parsing
  • Token handling deferred to EE (ensure proper validation there)

📊 Summary

This is a solid implementation with good test coverage. The main issues are:

  • Critical: Fix the typo in X_RIVET_AMESPACE
  • Medium: Document or remove unused parameters in route_request_path_based
  • Low: Consider the suggestions above for future improvements

Recommendation: ✅ Approve with minor fixes

The typo should be fixed before merge. The other items are suggestions for improvement but don't block merging.


🤖 Generated with Claude Code

@NathanFlurry NathanFlurry force-pushed the 10-22-feat_core_allow_routing_traffic_to_actors_via_path branch from 89114d1 to e5f9730 Compare October 23, 2025 08:37
@claude
Copy link

claude bot commented Oct 23, 2025

Pull Request Review: Path-Based Actor Routing

This PR introduces path-based routing for actors as an alternative to header-based routing. The implementation is well-structured and thoroughly tested. Here's my comprehensive review:


Strengths

1. Excellent Test Coverage

  • Rust tests (parse_actor_path.rs): 203 lines covering 16 test cases with both valid and invalid path scenarios
  • TypeScript tests (parse-actor-path.test.ts): Comprehensive mirroring of Rust test cases
  • Tests cover edge cases: query params, fragments, trailing slashes, empty paths, URL encoding, double slashes, case sensitivity

2. Consistent Implementation

  • The parseActorPath logic is duplicated consistently between Rust and TypeScript
  • Both implementations handle the same edge cases identically
  • Clear separation of concerns with dedicated handler functions

3. Clean Code Structure

  • Well-organized routing priority: path-based first, then fallback to header-based
  • Clear documentation in code comments
  • Proper use of structured logging with tracing
  • Good error handling with meaningful error messages

4. Backward Compatibility

  • Header-based routing remains fully functional as a fallback
  • No breaking changes to existing APIs

🔍 Issues Found

1. Critical: Typo in Header Constant (engine/packages/guard/src/routing/pegboard_gateway.rs:13)

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Issue: X_RIVET_AMESPACE should be X_RIVET_NAMESPACE

Impact: This constant is defined but never used in the code, suggesting incomplete implementation or future work. The typo would cause issues if this header is used elsewhere.

Recommendation:

  • Fix the typo to X_RIVET_NAMESPACE
  • If the header isn't needed yet, consider removing it or adding a TODO comment explaining its future purpose
  • If it should be used, add tests for it

2. Security: Token Validation Not Implemented

Multiple locations have comments stating: // NOTE: Token validation implemented in EE

Locations:

  • engine/packages/guard/src/routing/pegboard_gateway.rs:28
  • rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts:44
  • rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts:101

Issue: Token validation is deferred to Enterprise Edition (EE), but there's no validation or early return for invalid tokens in the open-source version.

Recommendation:

  • Document the security implications in PR description
  • Consider adding a validation hook or trait that can be overridden in EE
  • At minimum, log when token is provided but not validated

⚠️ Concerns & Recommendations

1. Path Parsing Edge Cases

The double slash check in parse_actor_path is good, but consider:

// Current check at mod.rs:167
if base_path.contains("//") {
    return None;
}

Recommendation: Consider normalizing paths before parsing or document why certain edge cases (like /gateway//actors/id/route/path) are rejected.

2. Query Parameter Removal

The PR removes query parameter fallback for headers/protocols throughout:

  • Removed parse_query_params function
  • Removed query_params parameter from multiple functions

Concern: This is a breaking change if any clients were using query parameters for routing.

Recommendation:

  • Document this breaking change in the PR description
  • Add migration notes if needed
  • Consider deprecation period if this affects external users

3. TypeScript Error Handling

In handleHttpGatewayPathBased (gateway.ts:96-129):

const proxyUrl = new URL(`http://actor${actorPathInfo.remainingPath}`);

Concern: No validation that remainingPath is a valid URL path. Malformed paths could cause URL constructor to throw.

Recommendation: Add try-catch or validate remainingPath format.

4. Unused Parameters

Several functions have unused parameters prefixed with _:

  • route_request_path_based: _token, _headers, _is_websocket
  • handle_websocket: _path

Recommendation:

  • If these are for future use, add TODO comments
  • If they're for EE implementation, document that
  • Consider removing if truly unused

5. Missing Integration Tests

While unit tests for parseActorPath are excellent, I don't see end-to-end tests for:

  • Complete request flow through path-based routing
  • WebSocket upgrade with path-based routing
  • Fallback behavior from path-based to header-based

Recommendation: Add integration tests that exercise the full routing stack.


🎯 Performance Considerations

1. Path Parsing on Every Request

parse_actor_path is called on every request before checking headers (mod.rs:53).

Current: O(n) string operations on every request
Impact: Minimal for most workloads, but could add latency for high-throughput scenarios

Recommendation: This is acceptable for most use cases, but consider:

  • Adding benchmarks to track regression
  • Caching parse results if the same paths are hit frequently (though probably not worth the complexity)

2. String Allocation

Multiple string allocations in parsing:

  • actor_id.to_string() at mod.rs:189
  • token cloning at mod.rs:199
  • format! for remaining_path at mod.rs:225-227

Recommendation: Consider using string slices where possible, though current approach is fine for readability.


🔒 Security Review

1. Path Traversal Protection

✅ Good: Double slash detection prevents some path traversal attempts
✅ Good: Empty segment detection (empty actor_id, empty token)
⚠️ Consider: Additional validation for:

  • Null bytes in path segments
  • Unicode normalization attacks
  • Excessive path length

2. Actor ID Validation

The code validates actor_id format via Id::parse() (pegboard_gateway.rs:31), which is good.

Recommendation: Ensure Id::parse() has comprehensive validation and rejects malicious inputs.

3. Token Exposure

Tokens in URL paths are logged and may appear in:

  • Server logs (structured logging at mod.rs:54)
  • HTTP access logs
  • Browser history
  • Proxy logs

Recommendation:

  • Document this trade-off in security documentation
  • Consider redacting tokens from logs
  • Recommend using header-based auth for sensitive use cases

📝 Code Style & Conventions

1. Following CLAUDE.md Guidelines

✅ Uses structured logging correctly: tracing::debug!(?actor_path_info, "routing using path-based actor routing")
✅ Proper error handling with anyhow and custom errors
✅ Hard tabs in Rust code
✅ Lowercase log messages

2. Minor Style Suggestions

Suggestion 1: Make ActorPathInfo fields non-public since parsing should go through parse_actor_path

// Currently at mod.rs:21-25
#[derive(Debug, Clone)]
pub struct ActorPathInfo {
	pub actor_id: String,        // Consider: actor_id: String,
	pub token: Option<String>,   // Consider: token: Option<String>,
	pub remaining_path: String,  // Consider: remaining_path: String,
}

Add accessor methods if needed.

Suggestion 2: Extract constants for path segments:

const GATEWAY_SEGMENT: &str = "gateway";
const ACTORS_SEGMENT: &str = "actors";
const TOKENS_SEGMENT: &str = "tokens";
const ROUTE_SEGMENT: &str = "route";

🎨 Documentation

What's Good

✅ Function-level documentation in TypeScript
✅ Inline comments explaining complex logic
✅ Test case descriptions

What's Missing

  • No README or docs update explaining the new routing pattern
  • No examples of using path-based routing
  • No migration guide from header-based routing

Recommendation: Add documentation covering:

  • When to use path-based vs header-based routing
  • Security implications of tokens in URLs
  • Example curl commands for both routing methods

📊 Summary

Must Fix Before Merge

  1. ❗ Fix typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE
  2. ❗ Document security implications of unvalidated tokens in CE
  3. ❗ Document breaking change (removal of query param fallbacks)

Should Fix Before Merge

  1. Add error handling for malformed paths in TypeScript URL construction
  2. Add TODO comments for unused parameters or remove them
  3. Document why token appears in logs and potential security implications

Nice to Have (Consider for Future PR)

  1. Integration tests for end-to-end routing
  2. Performance benchmarks
  3. Additional path traversal/security validations
  4. User-facing documentation and examples
  5. Make ActorPathInfo fields private with accessors

Final Verdict

This is a well-implemented feature with excellent test coverage and clean code structure. The path-based routing is a valuable addition that provides a more RESTful API alternative to header-based routing.

Recommendation: Approve with minor changes

The critical issues are minor (typo fix, documentation) and can be quickly addressed. The code is production-ready after addressing the "Must Fix" items.

Great work on the comprehensive test coverage and consistent implementation across Rust and TypeScript! 🎉


Review generated by Claude Code - feel free to push back on any suggestions or ask for clarification!

@NathanFlurry NathanFlurry force-pushed the 10-22-feat_core_allow_routing_traffic_to_actors_via_path branch from e5f9730 to a5f5632 Compare October 24, 2025 06:32
@NathanFlurry NathanFlurry force-pushed the 10-23-fix_fix_biome_ignore_path branch from 7b4e5e7 to 323a773 Compare October 24, 2025 06:32
@claude
Copy link

claude bot commented Oct 24, 2025

Pull Request Review: Path-based Actor Routing

This PR introduces path-based routing for actors, allowing traffic to be routed via URL paths in addition to headers. Overall, the implementation is well-structured with excellent test coverage. Here are my findings:


✅ Strengths

  1. Excellent Test Coverage: Both Rust and TypeScript implementations have comprehensive test suites covering edge cases (203 lines in Rust, 305 lines in TypeScript)
  2. Clean Architecture: Path-based routing is checked first, then falls back to header-based routing, maintaining backward compatibility
  3. Consistent Implementation: The path parsing logic is mirrored in both Rust and TypeScript with matching test cases
  4. Security Placeholder: Token validation is clearly marked with NOTE: Token validation implemented in EE comments

🔍 Code Quality Issues

1. Typo in Header Name (packages/guard/src/routing/pegboard_gateway.rs:13)

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Should be X_RIVET_NAMESPACE (missing 'N'). This constant is defined but never used in the codebase.

2. Unused Token Parameter (packages/guard/src/routing/pegboard_gateway.rs:22)

pub async fn route_request_path_based(
    // ...
    _token: Option<&str>,  // Prefixed with _ but mentioned in docs
    // ...
)

The _token parameter has an underscore prefix indicating it's intentionally unused, but the docstring says "NOTE: Token validation implemented in EE". Either:

  • Remove the underscore if this will be used in EE version
  • Add a more explicit comment about why it's currently unused

3. Code Duplication in Path Parsing

The path parsing logic is implemented twice (Rust and TypeScript) with slightly different approaches. While tests ensure they match, consider:

  • Documenting the canonical path format spec in a shared location
  • Adding integration tests that verify both parsers handle the same inputs identically

🐛 Potential Bugs

1. Fragment Handling Inconsistency (packages/guard/src/routing/mod.rs:147-149)

let fragment_pos = path.find('#');
// ...
(Some(q), Some(f)) if q < f => &path[q..f],

The code strips fragments from the base path but doesn't validate fragment positions. If a fragment appears before a query string (malformed URL), this could produce unexpected results. Consider adding validation.

2. Missing Path Validation in TypeScript

The TypeScript implementation at rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts appears to be truncated in the diff. Need to verify:

  • Does the TypeScript parser validate double slashes like the Rust version?
  • Are empty segments handled consistently?

🔒 Security Considerations

1. Token Validation Placeholder

Both implementations have placeholders for token validation:

// NOTE: Token validation implemented in EE

Recommendation: Ensure this is tracked and implemented before production use. Path-based tokens in URLs have different security implications than header-based auth:

  • URLs may be logged by proxies/servers
  • Tokens in URLs may appear in browser history
  • Consider adding a warning in docs about secure token handling

2. Path Traversal Protection

The current implementation doesn't explicitly sanitize the remaining_path. While this is likely handled downstream, consider:

  • Validating no .. segments in remaining path
  • Documenting where path traversal protection occurs

3. Actor ID Validation

The code accepts any non-empty string as an actor ID in the path, then validates it later:

let actor_id = Id::parse(actor_id_str).context("invalid actor id in path")?;

This is correct, but ensure the error messages don't leak sensitive information about valid/invalid actor IDs.


⚡ Performance Considerations

1. Multiple String Allocations

In parse_actor_path (packages/guard/src/routing/mod.rs:195-217):

let actor_id = segments[2].to_string();
// ...
(Some(segments[4].to_string()), 6)

Consider using string slices (&str) until the final ActorPathInfo construction to reduce allocations.

2. Path Parsing on Every Request

Path parsing happens on every request. Since most paths won't match the actor routing pattern, consider:

  • Early return if path doesn't start with /gateway/actors/
  • This optimization would avoid the more expensive segment splitting

Example:

pub fn parse_actor_path(path: &str) -> Option<ActorPathInfo> {
    // Early return for non-matching paths
    if !path.starts_with("/gateway/actors/") {
        return None;
    }
    // ... rest of parsing
}

📝 Documentation & Style

1. Missing Inline Documentation

The parse_actor_path function has pattern examples but lacks:

  • Examples of what remaining_path will contain
  • Behavior documentation for query strings and fragments
  • Return value documentation (what makes a path invalid)

2. Import Organization (Adhering to CLAUDE.md)

Per CLAUDE.md: "Always add imports at the top of the file inside of inline within the function."

The imports in the test files appear correct, but verify all new files follow this pattern.

3. Logging Follows Conventions

Good adherence to structured logging patterns:

tracing::debug!(?actor_path_info, "routing using path-based actor routing");

Lowercase messages with structured fields - matches CLAUDE.md guidelines.


🧪 Testing Recommendations

1. Add Integration Tests

While unit tests are comprehensive, consider adding:

  • End-to-end tests that verify HTTP/WebSocket requests route correctly via paths
  • Tests that verify fallback to header-based routing works correctly
  • Tests that verify both routing methods can't be used simultaneously (or document if this is allowed)

2. Security-focused Tests

Add tests for:

  • Malicious path inputs (path traversal attempts, extremely long paths)
  • URL encoding edge cases
  • Mixed routing methods (path + headers)

3. Test File Location

Test files are correctly placed:

  • engine/packages/guard/tests/parse_actor_path.rs - Rust tests
  • rivetkit-typescript/packages/rivetkit/tests/parse-actor-path.test.ts - TS tests

🎯 Recommendations Summary

Must Fix:

  1. Fix typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE
  2. Verify TypeScript path parser implementation (diff appears truncated)

Should Fix:

  1. Add early return optimization for non-matching paths (performance)
  2. Add security validation for token-in-path usage
  3. Document the path format specification in a shared location
  4. Remove underscore from _token parameter or clarify intent

Nice to Have:

  1. Reduce string allocations in path parsing
  2. Add integration tests for end-to-end routing
  3. Add security-focused tests for edge cases
  4. Improve inline documentation for parse_actor_path

📊 Overall Assessment

Code Quality: ⭐⭐⭐⭐ (4/5)
Test Coverage: ⭐⭐⭐⭐⭐ (5/5)
Security: ⭐⭐⭐ (3/5) - Pending token validation implementation
Performance: ⭐⭐⭐⭐ (4/5)
Documentation: ⭐⭐⭐ (3/5)

This is a solid implementation with excellent test coverage. The primary concerns are the typo that needs fixing and ensuring token validation is implemented before production use. The architecture is clean and maintains backward compatibility well.

Great work! 🎉

@claude
Copy link

claude bot commented Oct 24, 2025

Pull Request Review

I've reviewed PR #3250 which adds path-based routing for actor traffic. Overall, this is a well-implemented feature with excellent test coverage. Here's my detailed feedback:

✅ Strengths

  1. Excellent Test Coverage: Both Rust and TypeScript implementations have comprehensive test suites covering:

    • Valid paths (with/without tokens)
    • Query parameters and fragments
    • Edge cases (trailing slashes, empty paths, special characters)
    • Invalid inputs (malformed paths, case sensitivity, double slashes)
    • The tests are thorough and well-documented
  2. Consistent Implementation: The parsing logic is mirrored between Rust and TypeScript, ensuring consistent behavior across the stack

  3. Backwards Compatibility: Path-based routing is checked first, then falls back to header-based routing, preserving existing functionality

  4. Security-Aware: Token validation is noted as "implemented in EE" in both implementations, showing awareness of security requirements

🔍 Code Quality Issues

1. Typo in Header Constant (engine/packages/guard/src/routing/pegboard_gateway.rs:13)

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Should be X_RIVET_NAMESPACE (missing 'N'). This typo is carried through to the constant definition but the actual header name string is correct.

2. Unused Function Parameters

In route_request_path_based() (engine/packages/guard/src/routing/pegboard_gateway.rs:25-28):

pub async fn route_request_path_based(
    // ...
    _token: Option<&str>,      // Unused with underscore prefix
    // ...
    _headers: &hyper::HeaderMap,  // Unused
    _is_websocket: bool,          // Unused
)

While underscored parameters indicate intentionally unused values, consider whether these parameters will be used in the EE version for token validation. If not, they could be removed to simplify the API.

3. Query Parameter Removal

The PR removes support for passing routing information via query parameters (e.g., ?x_rivet_target=actor&x_rivet_actor=id). While this is mentioned in the diff, consider:

  • Is this a breaking change for any existing users?
  • Should there be migration documentation?
  • The TypeScript side still appears to handle some query params in path construction

🛡️ Security Concerns

1. Token Validation Not Implemented (Critical if EE not deployed)

Both Rust and TypeScript have:

// NOTE: Token validation implemented in EE
// NOTE: Token validation implemented in EE

Concerns:

  • If the EE version isn't deployed, tokens in paths are extracted but never validated
  • The _token parameter is unused in the open-source version
  • An attacker could potentially route traffic to any actor by crafting paths with arbitrary tokens
  • Recommendation: Add basic validation even in the open-source version, or ensure the routing fails securely without EE

2. Actor ID Validation

In route_request_path_based() (engine/packages/guard/src/routing/pegboard_gateway.rs:42):

let actor_id = Id::parse(actor_id_str).context("invalid actor id in path")?;

Good - Actor IDs are validated. However, in the TypeScript version, the actor ID is passed as a string without validation before being used. Consider adding validation.

3. Path Traversal Protection

The parser correctly rejects double slashes (//) which is good. However, consider:

  • Does the remaining path get normalized before being forwarded?
  • Can path segments like .. be used to traverse directories in the actor?
  • The URL-encoded paths are preserved (test at line 110-116), which is correct, but ensure downstream handlers properly decode and validate

📊 Performance Considerations

  1. Path Parsing on Every Request: The parse_actor_path() function is called on every request before falling back to header-based routing. This involves:

    • String searching for ? and #
    • String splitting and iteration
    • Multiple string comparisons

    Consider adding early returns or optimizations for the most common case (non-actor paths).

  2. String Allocations: In the Rust version (mod.rs:186-224), there are several string allocations during path parsing. For high-throughput scenarios, consider using string slices where possible.

🔧 Minor Issues

1. Inconsistent Error Context

In pegboard_gateway.rs:42:

let actor_id = Id::parse(actor_id_str).context("invalid actor id in path")?;

But in the original header-based routing (line 86):

let actor_id = Id::parse(actor_id_str).context("invalid x-rivet-actor header")?;

The error messages reference different sources. Consider making error messages more specific about path-based vs header-based routing.

2. Missing Documentation

The ActorPathInfo struct (mod.rs:20-24) could benefit from doc comments explaining:

  • What each field represents
  • The format/constraints on actor_id
  • When token is Some vs None
  • What remaining_path contains (with leading slash, query params, etc.)

3. Truncated PR Diff

The diff appears to be truncated at the end:

340/**
341 * Parse actor routing information from path
...
// Include q

This suggests there might be incomplete code that wasn't visible in the review.

📝 Recommendations

  1. Fix the typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE
  2. Add token validation: Either implement basic validation or fail securely without EE
  3. Add actor ID validation in TypeScript to match Rust
  4. Document breaking changes: If query parameter routing is being removed
  5. Add documentation: Doc comments on public types and functions
  6. Consider path normalization: Ensure remaining paths are safe from traversal attacks
  7. Performance profiling: For high-traffic scenarios, profile the path parsing overhead

✨ Summary

This is a solid implementation with excellent test coverage. The main concerns are:

  • Critical: Token validation security (if EE not available)
  • High: The typo in the constant name
  • Medium: Missing validation and documentation
  • Low: Performance optimizations for hot paths

The feature is well-designed and the fallback to header-based routing ensures backwards compatibility. Once the security and typo issues are addressed, this should be ready to merge.

@NathanFlurry NathanFlurry force-pushed the 10-23-fix_fix_biome_ignore_path branch from 323a773 to a97aa78 Compare October 24, 2025 20:40
@NathanFlurry NathanFlurry force-pushed the 10-22-feat_core_allow_routing_traffic_to_actors_via_path branch from a5f5632 to 82faa7e Compare October 24, 2025 20:40
@claude
Copy link

claude bot commented Oct 24, 2025

Pull Request Review: Actor Path-Based Routing

This PR introduces path-based routing for actors as an alternative to header-based routing, allowing traffic to be routed via URL paths like /gateway/actors/{actor_id}/route/{path}. The implementation is well-structured with comprehensive test coverage.

✅ Strengths

  1. Excellent Test Coverage: Both Rust and TypeScript implementations have thorough test suites covering:

    • Valid paths with and without tokens
    • Query parameters and fragments
    • Special characters and edge cases
    • Invalid path patterns
    • 203 test cases in Rust, 305 lines in TypeScript tests
  2. Consistent Implementation: The path parsing logic is duplicated between Rust and TypeScript with identical behavior, which is appropriate for this use case.

  3. Backward Compatibility: Path-based routing is checked first, then falls back to header-based routing, maintaining backward compatibility.

  4. Good Error Handling: Proper validation of path segments, empty values, and malformed paths.

  5. Documentation: Clear comments explaining the routing patterns and behavior.

🐛 Bug Found - Typo in Header Name

Location: engine/packages/guard/src/routing/pegboard_gateway.rs:13

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Issue: X_RIVET_AMESPACE should be X_RIVET_NAMESPACE (missing 'N')

Impact: This constant is defined but never used in this PR. However, it's exported and could cause confusion or errors if someone tries to use it later. The constant name doesn't match the actual header string.

Fix: Rename the constant to X_RIVET_NAMESPACE

🔒 Security Considerations

  1. Token Validation Placeholder: The code has // NOTE: Token validation implemented in EE comments in both Rust (pegboard_gateway.rs:30) and TypeScript (gateway.ts:42, 102). This is fine if it's intentional for the EE version, but ensure:

    • Open-source version clearly documents that tokens are not validated
    • EE version properly implements token validation
    • There's no security bypass risk from the path-based routing
  2. Path Traversal Protection: Good validation preventing:

    • Double slashes (//)
    • Empty segments
    • Proper segment ordering

    However, consider:

    • Are URL-encoded characters properly handled downstream? The tests show %20 and %2F are preserved in the remaining path, which is correct.
    • Should there be additional validation on actor_id format beyond empty check?
  3. Fragment Stripping: Fragments are correctly stripped before processing, which is appropriate since they're client-side only.

📊 Performance Considerations

  1. Path Parsing on Every Request: The parse_actor_path function is called on every request before falling back to header-based routing. The implementation is efficient (O(n) where n is path segments), but consider:

    • Is there a performance impact on non-actor requests?
    • Could a quick prefix check (path.starts_with("/gateway/actors/")) before full parsing reduce overhead?
  2. String Allocations: Both implementations allocate strings for actor_id, token, and remaining_path. This is reasonable but monitor if it becomes a hot path.

🤔 Code Quality & Best Practices

  1. Duplicate Logic: Path parsing logic is duplicated in Rust and TypeScript. While this is common for polyglot codebases, ensure:

    • Both implementations stay in sync during future changes
    • Consider adding integration tests that verify both produce identical results
  2. Magic Numbers: The code uses literal indices (3, 4, 5, 6) when checking segments. Consider extracting these as named constants for clarity:

    const TOKENS_SEGMENT_IDX: usize = 3;
    const TOKEN_VALUE_IDX: usize = 4;
    const ROUTE_AFTER_TOKEN_IDX: usize = 5;
  3. Case Sensitivity: Tests verify keywords are case-sensitive (gateway, actors, route, tokens must be lowercase). This is correct but should be documented in API docs.

  4. Query Parameter Removal: The PR removes query parameter fallback for routing (x_rivet_target, x_rivet_actor, x_rivet_token). This is a breaking change if any clients were using query params. Confirm this is intentional and documented in release notes.

🧪 Testing Recommendations

  1. Integration Tests: Consider adding integration tests that:

    • Test actual HTTP/WebSocket routing through the full stack
    • Verify that path-based and header-based routing can coexist
    • Test the peer DC re-routing mentioned in pegboard_gateway.rs:99
  2. Security Tests: Add tests for:

    • Path traversal attempts (e.g., ../../../etc/passwd)
    • Extremely long actor IDs or paths
    • Unicode characters in paths

📝 Minor Issues

  1. Unused Import: Check if X_RIVET_AMESPACE (once renamed) is needed or should be removed if not used.

  2. WebSocket Protocol Optional: The comment in actor-driver.ts:327 states "optional for path-based routing", but the old code threw an error if missing. Ensure this change is intentional and doesn't break existing clients.

  3. Inconsistent Remaining Path Default:

    • When no path after /route, Rust returns "/"
    • TypeScript also returns "/"
    • This is consistent ✅ but should be documented as the expected behavior

✅ Recommendation

Approve with minor fix required: The typo X_RIVET_AMESPACEX_RIVET_NAMESPACE should be fixed before merging.

Overall, this is a well-implemented feature with excellent test coverage. The main concern is the typo in the header constant name. After fixing that, this should be good to merge.

🎯 Action Items

  • Fix typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE
  • Confirm query parameter removal is intentional and documented
  • Verify token validation is properly implemented in EE version
  • Consider adding integration tests for full routing stack
  • Document case-sensitive keyword requirement in API docs

@claude
Copy link

claude bot commented Oct 24, 2025

PR Review: Path-based Actor Routing

This PR adds path-based routing for actors as an alternative to header-based routing. Overall, this is a well-implemented feature with excellent test coverage. Here's my detailed review:


Strengths

1. Excellent Test Coverage

  • Rust tests: 203 lines covering valid/invalid paths, edge cases, query params, fragments, trailing slashes, special characters, and error cases (engine/packages/guard/tests/parse_actor_path.rs)
  • TypeScript tests: 305 lines with comprehensive test suite mirroring the Rust implementation (rivetkit-typescript/packages/rivetkit/tests/parse-actor-path.test.ts)
  • Both implementations have parallel test cases ensuring consistency across languages

2. Clean Implementation

  • Path parsing logic is well-structured and handles edge cases properly
  • Proper separation of concerns with dedicated functions for path-based vs header-based routing
  • Good documentation with clear comments explaining the routing patterns

3. Backwards Compatibility

  • Path-based routing is checked first, then falls back to header-based routing
  • Existing functionality remains intact
  • WebSocket protocol header is now optional when using path-based routing (see actor-driver.ts:328)

🔍 Issues & Concerns

1. Typo in Header Name ⚠️

Location: engine/packages/guard/src/routing/pegboard_gateway.rs:13

pub const X_RIVET_AMESPACE: HeaderName = HeaderName::from_static("x-rivet-namespace");

Issue: X_RIVET_AMESPACE should be X_RIVET_NAMESPACE (missing 'N')

Impact: This header constant is declared but never used in this PR, so it's unclear if this is intentional or a typo. The TypeScript side has the correct name HEADER_RIVET_NAMESPACE.

Recommendation: Fix the typo to X_RIVET_NAMESPACE for consistency.


2. Unused Token Parameter 🔧

Locations:

  • engine/packages/guard/src/routing/pegboard_gateway.rs:22
  • rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts (multiple locations)
pub async fn route_request_path_based(
    // ...
    _token: Option<&str>,  // ← Unused parameter
    // ...
) -> Result<Option<RoutingOutput>> {
    // NOTE: Token validation implemented in EE

Issue: The token parameter is prefixed with _ indicating it's intentionally unused, with a comment saying "Token validation implemented in EE" (Enterprise Edition).

Concerns:

  1. Security: If this is OSS code, tokens are extracted but never validated, potentially giving a false sense of security
  2. Code clarity: Having unused parameters in the function signature is confusing
  3. Maintenance: Future developers might not realize token validation is missing

Recommendations:

  • Add a clear warning in documentation that token validation is NOT performed in the open-source version
  • Consider removing the token parameter entirely if not used, or add a placeholder validation that returns an error
  • If this is EE-only, consider documenting the security implications

3. Missing Actor ID Validation 🔒

Location: engine/packages/guard/src/routing/pegboard_gateway.rs:42

let actor_id = Id::parse(actor_id_str).context("invalid actor id in path")?;

Issue: The code parses the actor ID from the path but doesn't validate that the caller has permission to access this actor.

Security Implications:

  • Path-based routing allows direct actor ID specification
  • Without authorization checks, any user could potentially route to any actor by guessing/knowing actor IDs
  • This is different from header-based routing where the same issue exists, but path-based routing makes it more obvious/easier to exploit

Recommendations:


4. Code Duplication in Path Parsing 📋

Observation: The path parsing logic is duplicated in both Rust and TypeScript with nearly identical implementations.

Locations:

  • engine/packages/guard/src/routing/mod.rs:138-235
  • rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts:346-445

Pros:

  • Ensures consistency across platforms
  • Both languages have their own native implementations

Cons:

  • Maintenance burden - changes must be made in both places
  • Risk of divergence over time

Recommendations:

  • Ensure both implementations are kept in sync
  • Consider adding integration tests that verify both parsers produce identical results for the same inputs
  • Document that changes to path parsing must be made in both places

5. Query Parameter Handling Change ⚠️

Location: Multiple files

Change: The PR removes query parameter fallback for headers (x_rivet_target, x_rivet_actor, x_rivet_token query params)

Files affected:

  • engine/packages/guard/src/routing/mod.rs:44-47 (removed parse_query_params)
  • engine/packages/guard/src/routing/runner.rs (removed query param fallbacks)
  • engine/packages/guard/src/routing/pegboard_gateway.rs (removed query param fallbacks)

Impact:

  • Breaking change if anyone was using query parameters for routing
  • No migration guide or deprecation warning mentioned
  • Could affect existing integrations

Recommendations:

  • Document this as a breaking change in the PR description
  • Consider adding a deprecation period with warnings before full removal
  • Update any documentation that mentions query parameter routing

6. Potential Path Traversal Concerns 🔐

Location: Path parsing implementation

Observation: The remaining_path is extracted and forwarded directly to the actor without sanitization.

Example:

/gateway/actors/actor-123/route/../../../etc/passwd

Current Protection:

  • Double slashes are rejected (basePath.includes("//"))
  • But single .. path segments are not explicitly rejected

Analysis:

  • The remaining path is URL-encoded and forwarded as-is
  • Protection depends on the actor's HTTP server properly handling path traversal
  • Tests include URL-encoded characters but don't test .. segments

Recommendations:

  • Add explicit tests for path traversal attempts
  • Consider normalizing or rejecting paths containing .. segments
  • Document that actors must implement their own path validation
  • Add a security note in the documentation

📊 Code Quality

Style Adherence ✅

  • Follows Rust formatting conventions (hard tabs)
  • Proper error handling with anyhow::Result
  • Good use of structured logging with tracing
  • Log messages are lowercase (follows CLAUDE.md guidelines)

Naming Conventions ✅

  • Consistent naming across Rust and TypeScript
  • Good variable names that are self-documenting
  • Follows existing patterns in the codebase

🎯 Performance Considerations

Positive:

  • Path parsing is O(n) where n is path length - efficient
  • Early exit on invalid paths minimizes processing
  • No regex usage - using simple string operations

Potential Improvements:

  • Could cache parsed paths if same paths are frequently accessed (future optimization)
  • String allocations could be optimized but likely negligible for this use case

📝 Documentation

Good:

  • Function-level documentation explaining the routing patterns
  • Inline comments explaining the logic
  • Test cases serve as documentation of expected behavior

Missing:

  • Migration guide for users relying on query parameter routing
  • Security implications of path-based routing vs header-based
  • Documentation of authorization model
  • API documentation showing example usage

🧪 Testing Recommendations

While test coverage is excellent, consider adding:

  1. Integration tests verifying end-to-end routing with real actors
  2. Security tests for path traversal, actor ID enumeration, etc.
  3. Performance tests for path parsing under load
  4. Cross-language consistency tests ensuring Rust and TypeScript parsers agree

🎬 Summary

This is a well-implemented feature with strong test coverage and clean code. However, there are several concerns that should be addressed before merging:

Must Fix 🔴:

  1. Fix typo: X_RIVET_AMESPACEX_RIVET_NAMESPACE

Should Address 🟡:
2. Document/clarify token validation security implications
3. Document breaking change (query parameter removal)
4. Consider path traversal protection
5. Clarify authorization model for actor access

Nice to Have 🟢:
6. Reduce code duplication between Rust/TypeScript implementations
7. Add integration tests
8. Add migration documentation

Overall: Approve with minor changes required

Great work on the comprehensive testing and clean implementation! The path-based routing is a useful addition that makes the API more intuitive to use.

Base automatically changed from 10-23-fix_fix_biome_ignore_path to main October 25, 2025 09:21
@NathanFlurry NathanFlurry merged commit 761a96b into main Oct 25, 2025
8 of 17 checks passed
@NathanFlurry NathanFlurry deleted the 10-22-feat_core_allow_routing_traffic_to_actors_via_path branch October 25, 2025 09:21
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.

1 participant