Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Nov 6, 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 6, 2025 5:37am
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 6, 2025 5:37am
rivet-inspector Ignored Ignored Preview Nov 6, 2025 5:37am
rivet-site Ignored Ignored Preview Nov 6, 2025 5:37am

Copy link
Member Author

NathanFlurry commented Nov 6, 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.

@NathanFlurry NathanFlurry force-pushed the 11-05-fix_runner_do_not_send_websocket_close_on_tunnel_shutdown_since_pegboard-runner_takes_care_of_this branch from 3e95003 to a232088 Compare November 6, 2025 01:00
@NathanFlurry NathanFlurry force-pushed the 11-05-chore_runner_explicitly_stringify_tunnel_messages_commands_and_events branch from 48c08ef to 2895f0b Compare November 6, 2025 01:00
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 6, 2025

More templates

@rivetkit/actor

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

@rivetkit/cloudflare-workers

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

@rivetkit/core

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

@rivetkit/db

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

@rivetkit/framework-base

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

@rivetkit/next-js

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

@rivetkit/react

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

rivetkit

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

@rivetkit/sql-loader

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

@rivetkit/engine-runner

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

@rivetkit/engine-runner-protocol

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

commit: b479fad

@claude
Copy link

claude bot commented Nov 6, 2025

Code Review

Summary

This PR adds explicit stringify functions for tunnel messages, commands, and events to improve logging. The changes address the issue of logging objects that contain non-JSON-serializable types like ArrayBuffer, BigInt, and Map.

Positives

  1. Well-structured solution: The new stringify.ts module is cleanly organized with separate functions for each protocol type
  2. Type safety: All stringify functions properly handle the tagged union types
  3. Comprehensive coverage: Handles all message types including tunnel messages, commands, and events
  4. Better logging: The structured logging approach improves observability by properly formatting complex data types

Issues & Recommendations

1. Security Concern - Potential Data Leakage in Logs

Severity: High

The stringify functions log header contents and other potentially sensitive data:

// Line 82 in stringify.ts
return `ToClientRequestStart{actorId: "${actorId}", method: "${method}", path: "${path}", headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;

Recommendation: Consider:

  • Redacting sensitive headers (Authorization, Cookie, etc.)
  • Adding a sanitization layer for PII
  • Documenting what data appears in logs for compliance purposes

2. Missing Escaping in String Interpolation

Severity: Medium

String values are directly interpolated without escaping, which could break the log format if they contain quotes or special characters:

// Line 63 in stringify.ts
const reasonStr = reason === null ? "null" : `"${reason}"`;

If reason contains quotes or newlines, the output will be malformed.

Recommendation: Add proper escaping or use JSON.stringify() for string values:

const reasonStr = reason === null ? "null" : JSON.stringify(reason);

3. Inconsistent Handling of Index/BigInt

Severity: Low

Some places convert bigint to string with template literals, others use the helper:

// Line 58 in stringify.ts
return `ToServerWebSocketMessageAck{index: ${index}}`; // Missing stringifyBigInt

vs.

// Line 50 in stringify.ts
return `ToServerWebSocketOpen{canHibernate: ${canHibernate}, lastMsgIndex: ${stringifyBigInt(lastMsgIndex)}}`;

Recommendation: Be consistent - either always use stringifyBigInt() or always use template literals. The stringifyBigInt() helper adds the "n" suffix which is helpful for clarity.

4. Missing Type Exhaustiveness Checks

Severity: Low

The switch statements do not have default cases that would catch new enum variants at compile time. This means if new message types are added to the protocol, TypeScript will not warn you that the stringify functions are incomplete.

Recommendation: Add exhaustiveness checks to catch new variants:

export function stringifyEvent(event: protocol.Event): string {
	switch (event.tag) {
		case "EventActorIntent":
			// ...
		case "EventActorStateUpdate":
			// ...
		case "EventActorSetAlarm":
			// ...
		default:
			const _exhaustive: never = event;
			return `Unknown event: ${(_exhaustive as any).tag}`;
	}
}

5. Missing Unit Tests

Severity: Medium

The new stringify.ts module has no test coverage for:

  • Proper handling of null values
  • ArrayBuffer stringification
  • Map stringification with special characters
  • Proper escaping of string values
  • Edge cases (empty maps, zero-length buffers, etc.)

Recommendation: Add unit tests to ensure the stringify functions handle all edge cases correctly.

6. Performance Consideration - Map Stringification

Severity: Low

The stringifyMap function creates intermediate arrays and strings for every log statement:

function stringifyMap(map: ReadonlyMap<string, string>): string {
	const entries = Array.from(map.entries())
		.map(([k, v]) => `"${k}": "${v}"`)
		.join(", ");
	return `Map(${map.size}){${entries}}`;
}

For large maps in high-frequency logging, this could create GC pressure.

Recommendation: If maps are typically large, consider:

  • Truncating after N entries
  • Adding size limits
  • Only showing count for very large maps

Code Quality

✅ Good separation of concerns
✅ Clear naming conventions
✅ Consistent code style
⚠️ Missing JSDoc for some edge case behaviors
⚠️ No validation of input data

Testing

❌ No test files included
❌ No test coverage for the new stringify functions

Recommendation: Add tests for edge cases and various message types.

Summary

Approve with changes requested

The core implementation is solid and addresses the logging issue well. However, there are some security and reliability concerns that should be addressed:

Must fix:

  1. Add proper string escaping to prevent log format corruption
  2. Add unit tests for the stringify functions

Should fix:
3. Consider sanitizing sensitive data from logs
4. Make bigint handling consistent
5. Add exhaustiveness checks to switch statements

Nice to have:
6. Add performance optimizations for large maps

Let me know if you would like help implementing any of these suggestions!

@claude
Copy link

claude bot commented Nov 6, 2025

Code Review

Summary

This PR improves logging by adding explicit stringification for tunnel messages, commands, and events that contain non-JSON-serializable types (ArrayBuffer, BigInt, Map). This is a good improvement for log readability and debugging.

Positive Aspects ✅

  1. Well-motivated change: Handles types that can't be properly logged by default JSON serialization (ArrayBuffer, BigInt, Map)
  2. Comprehensive coverage: All protocol message types are handled with dedicated stringify functions
  3. Consistent approach: Uses pattern matching on tagged unions consistently
  4. Good separation of concerns: Logging logic is separated into a dedicated module

Issues and Recommendations

1. Type Safety Concern ⚠️

The switch statements in stringify.ts don't have exhaustiveness checking. If new message types are added to the protocol, TypeScript won't warn about missing cases.

Recommendation: Add exhaustiveness checking with a default case that ensures all variants are handled.

2. BigInt Formatting Inconsistency

In mod.ts:909, the index is converted with .toString() but in stringify.ts, BigInts use the stringifyBigInt helper that adds an 'n' suffix. This creates inconsistency.

Recommendation: Use the helper consistently or remove the 'n' suffix since it's not needed for logging purposes.

3. Potential Information Leakage in Logs

The stringify functions log full headers, paths, and reason strings which might contain sensitive information.

Recommendation: Consider whether header values should be redacted or truncated in production logs, especially for authentication headers.

4. Missing Null Safety

In stringifyMap, there's no null check before calling .entries(). If a null/undefined map is passed, it will throw.

Recommendation: Add null safety checks to handle edge cases gracefully.

5. Documentation Could Be Improved

The JSDoc comments are generic. They could explain why this is needed (non-JSON-serializable types) and perhaps give examples.

Recommendation: Enhance documentation to explain the motivation and provide usage examples.

6. Performance: String Concatenation

The functions use template literals and string concatenation. For very large ArrayBuffers or Maps, this could be inefficient.

Recommendation: Consider adding size limits to prevent excessive string building (e.g., only show first N entries of a Map, truncate very large buffers).

Minor Observations

  1. The change from structured logging to string formatting in mod.ts:907-909 loses some structure - the original had separate fields for index, tag, and val. This might make log querying harder if you use structured log analysis tools.

  2. Consider adding unit tests for the stringify functions, especially edge cases (null values, empty buffers, empty maps).

Security Assessment

✅ No security concerns identified. The changes are purely cosmetic for logging purposes.

Test Coverage

⚠️ No tests appear to be included. Consider adding unit tests for the stringify module.

Overall Assessment

This is a solid improvement that will make logs more readable. The main concerns are around type safety (exhaustiveness checking) and consistency (BigInt formatting). None of the issues are blocking, but addressing them would improve code quality.

Recommendation: Approve with minor changes suggested.

@NathanFlurry NathanFlurry force-pushed the 11-05-fix_runner_do_not_send_websocket_close_on_tunnel_shutdown_since_pegboard-runner_takes_care_of_this branch from a232088 to d5276a3 Compare November 6, 2025 02:16
@NathanFlurry NathanFlurry force-pushed the 11-05-chore_runner_explicitly_stringify_tunnel_messages_commands_and_events branch from 2895f0b to f4e3b5b Compare November 6, 2025 02:16
@claude
Copy link

claude bot commented Nov 6, 2025

Code Review

This PR introduces explicit stringification for tunnel messages, commands, and events to handle non-JSON-serializable types (ArrayBuffers, BigInts, Maps) in logging. Overall, this is a solid improvement that addresses a real issue with logging complex data structures.

Strengths

  1. Clear Problem Solution: Properly handles ArrayBuffers, BigInts, and Maps that cannot be JSON.stringified
  2. Comprehensive Coverage: All relevant protocol message types are covered
  3. Type Safety: Uses TypeScript type system with exhaustive switch statements
  4. Improved Log Structure: Changes from spreading objects to using dedicated string fields improve log readability
  5. Consistent Formatting: The stringified output format is uniform and readable

Code Quality and Best Practices

Good:

  • Well-documented helper functions with JSDoc comments
  • Consistent naming conventions
  • Proper use of TypeScript switch statements with tagged unions

Potential Improvements:

  1. Missing Exhaustiveness Checks (stringify.ts:66, 104, 126, 175)

    • The switch statements do not have exhaustiveness checking. Consider adding default cases that throw or use TypeScript exhaustiveness checking pattern to catch new protocol variants at compile time.
  2. Logging Level Inconsistency (mod.ts:756, 906, 962)

    • Commands and events are logged at info level. For high-frequency operations, consider if debug level would be more appropriate to avoid log volume issues in production.
  3. BigInt Conversion Inconsistency (stringify.ts:57)

    • In ToServerWebSocketMessageAck, the index is not converted with stringifyBigInt() while other bigint fields are. This should be:
    return `ToServerWebSocketMessageAck{index: ${stringifyBigInt(index)}}`;

Potential Bugs

  1. Type Coercion Issue (stringify.ts:57)

    • If index is a bigint, the template literal will auto-convert it without the "n" suffix, making it inconsistent with other bigint representations in logs.
  2. Map Stringify Escaping (stringify.ts:20-24)

    • The stringifyMap function does not escape quotes or special characters in keys/values. If headers contain quotes, this could produce malformed log output. Consider escaping or using JSON.stringify for individual values.
  3. Potential Size Issues (stringify.ts:20-24)

    • stringifyMap converts entire Maps to strings. For very large header Maps, this could create extremely long log lines. Consider truncating or limiting size.

Security Considerations

  1. Sensitive Data Exposure (stringify.ts:82, 92, 120)

    • Headers and configuration data are logged in full. This could leak sensitive information (auth tokens, API keys, session cookies) if present in headers. Consider:
      • Redacting known sensitive header names (Authorization, Cookie, Set-Cookie, etc.)
      • Truncating or hashing certain fields in production environments
  2. Buffer Content Logging

    • ArrayBuffers are logged with size only, which is appropriate. Ensure this provides sufficient debugging information for your use cases.

Performance Considerations

  1. String Concatenation (stringify.ts:120, 40, etc.)

    • Multiple template literals and string operations per log call. For high-frequency logging, this could have overhead. Consider lazy evaluation if the log level is disabled.
  2. Map.entries() Allocation (stringify.ts:21)

    • Creates new arrays for every Map stringify. For frequently logged messages, this creates GC pressure.
  3. Index toString Conversion (mod.ts:909, 965)

    • Converting bigint indices to strings on every log. This is acceptable but note the cost for high-frequency events.

Test Coverage

Missing:

  • No tests found for the new stringify.ts module
  • Should add unit tests covering:
    • Each stringify function with various input types
    • Edge cases (null values, empty Maps, zero-length ArrayBuffers)
    • Special characters in strings (quotes, newlines, unicode)
    • Very large Maps/ArrayBuffers
    • All protocol message variants

Suggested Test Structure:
Consider adding engine/sdks/typescript/runner/tests/stringify.test.ts with comprehensive coverage of all stringify functions and edge cases.

Recommendations

High Priority:

  1. Fix the bigint inconsistency in ToServerWebSocketMessageAck (stringify.ts:57)
  2. Add exhaustiveness checking to all switch statements to catch new protocol variants
  3. Add unit tests for the stringify module

Medium Priority:
4. Consider redacting sensitive headers in logs for production safety
5. Add escaping for Map string values to prevent malformed output
6. Evaluate log levels - consider using debug for high-frequency events

Low Priority:
7. Add size limits for stringified Maps to prevent excessive log line lengths
8. Consider performance optimizations if these code paths are called at high frequency

Summary

This is a well-implemented solution to a real logging problem. The code is clean, well-structured, and addresses the core issue of logging non-JSON-serializable types. The main concerns are:

  • Missing exhaustiveness checks and potential runtime errors for new protocol variants
  • BigInt inconsistency that could cause confusion in logs
  • Lack of test coverage for critical logging infrastructure
  • Potential sensitive data exposure in headers

The changes are generally safe and improve the codebase. Addressing the high-priority items (especially tests and the bigint bug) would make this fully production-ready.

@claude
Copy link

claude bot commented Nov 6, 2025

Code Review for PR #3386

Overview

This PR adds explicit stringification for tunnel messages, commands, and events to improve logging readability. The changes prevent issues with structured logging of non-serializable types like ArrayBuffer, BigInt, and Map.

Strengths

  1. Well-motivated change - Solves a real problem where ArrayBuffers, BigInts, and Maps cannot be properly logged using structured logging
  2. Comprehensive coverage - All relevant protocol types have stringify functions
  3. Clear helper functions - Good separation of concerns with stringifyArrayBuffer, stringifyBigInt, and stringifyMap
  4. Exhaustive switch statements - TypeScript will catch any missing cases at compile time
  5. Consistent formatting - The output format is uniform and readable

Code Quality

Good:

  • Clean separation into a dedicated stringify.ts module
  • Comprehensive JSDoc comments explaining the purpose
  • Type-safe with proper TypeScript types from the protocol package
  • Consistent naming conventions

Potential Issues

  1. Escaping in stringifyMap (line 22): If header values or keys contain quotes or special characters, this could produce malformed output. Consider escaping quotes or using JSON.stringify for the values.

  2. Missing exhaustiveness check: The switch statements do not have default cases with unreachable() calls like other switch statements in the codebase (e.g., mod.ts:656). While TypeScript provides compile-time exhaustiveness, adding runtime checks would match existing patterns.

  3. Typo in tunnel.ts:434: Should be caught not catught. This appears to be a pre-existing typo.

Performance Considerations

  • The stringify functions are only called during logging, so performance impact is minimal
  • Creating intermediate strings is acceptable for debugging output
  • The Array.from(map.entries()) call creates an intermediate array, but this is fine for logging

Security Considerations

  • No security concerns identified
  • The stringify functions do not expose sensitive data beyond what is already in the logs
  • Consider if any logged data might contain sensitive information in production

Suggestions

  1. Add escaping for quotes in stringifyMap to prevent malformed output
  2. Add default: unreachable(...) cases to match codebase patterns
  3. Fix the typo catught to caught in tunnel.ts:434
  4. Consider adding unit tests for the stringify functions
  5. The stringifyEventWrapper function is exported but not used - consider if it should be used or removed

Test Coverage

No tests were added. Consider adding unit tests for each stringify function with various input types and edge cases.

Summary

This is a solid improvement that makes logging more readable and maintainable. The implementation is clean and comprehensive. The suggestions above are minor improvements.

Recommendation: Approve with minor suggestions

The code is production-ready as-is, but addressing the suggestions would make it more robust.

@NathanFlurry NathanFlurry force-pushed the 11-05-chore_runner_explicitly_stringify_tunnel_messages_commands_and_events branch from f4e3b5b to b479fad Compare November 6, 2025 05:36
@NathanFlurry NathanFlurry force-pushed the 11-05-fix_runner_do_not_send_websocket_close_on_tunnel_shutdown_since_pegboard-runner_takes_care_of_this branch from d5276a3 to 7a186f6 Compare November 6, 2025 05:36
@claude
Copy link

claude bot commented Nov 6, 2025

PR Review: Explicitly stringify tunnel messages, commands, and events

Summary

This PR adds custom stringify functions to handle logging of protocol messages that contain types incompatible with JSON serialization (ArrayBuffer, BigInt, Map). The changes improve log readability and prevent potential serialization errors.

Positives ✅

  1. Solves a Real Problem: Addresses the issue of logging complex types (ArrayBuffer, BigInt, Map) that don't serialize well with JSON.stringify()
  2. Type Safety: All stringify functions properly handle discriminated unions with exhaustive switch statements
  3. Consistent Formatting: Provides uniform, human-readable output format for all protocol messages
  4. Well Organized: Clean separation into a dedicated stringify.ts module

Issues & Concerns 🔍

1. Potential Information Leakage (Security)

The stringify functions expose potentially sensitive data in logs:

  • Headers in stringifyMap() - may contain auth tokens, API keys, cookies
  • Body sizes in stringifyArrayBuffer() - could leak information about request/response payloads
  • Actor configuration including input data

Recommendation: Consider adding sanitization for sensitive headers (Authorization, Cookie, etc.) or add a configuration option to control verbosity levels.

function stringifyMap(map: ReadonlyMap<string, string>, sanitize = true): string {
  const sensitiveKeys = new Set(['authorization', 'cookie', 'x-api-key']);
  const entries = Array.from(map.entries())
    .map(([k, v]) => {
      const value = (sanitize && sensitiveKeys.has(k.toLowerCase())) ? '[REDACTED]' : v;
      return `"${k}": "${value}"`;
    })
    .join(", ");
  return `Map(${map.size}){${entries}}`;
}

2. Missing Error Handling

The stringify functions don't handle potential errors:

  • What if buffer.byteLength throws?
  • What if Map iteration fails?

Recommendation: Add try-catch wrappers or ensure these are only called with valid inputs.

3. Incomplete Type Coverage

In stringifyEvent(), the ActorIntent handling uses a ternary chain that falls back to "Unknown":

const intentStr =
  intent.tag === "ActorIntentSleep"
    ? "Sleep"
    : intent.tag === "ActorIntentStop"
      ? "Stop"
      : "Unknown";

Similarly for ActorState. This could hide bugs if new variants are added.

Recommendation: Use exhaustive switch statements with default: unreachable(intent) to catch missing cases at runtime (I see you already import unreachable in mod.ts).

switch (intent.tag) {
  case "ActorIntentSleep":
    return "Sleep";
  case "ActorIntentStop":
    return "Stop";
  default:
    unreachable(intent);
}

4. Performance Consideration

Large headers or many map entries will be fully stringified even if logs are filtered out. Consider:

  • Truncating very large collections
  • Lazy evaluation if the logger supports it

Example:

function stringifyMap(map: ReadonlyMap<string, string>, maxEntries = 20): string {
  const entries = Array.from(map.entries())
    .slice(0, maxEntries)
    .map(([k, v]) => `"${k}": "${v}"`)
    .join(", ");
  const suffix = map.size > maxEntries ? `, ... (${map.size - maxEntries} more)` : '';
  return `Map(${map.size}){${entries}${suffix}}`;
}

5. Code Duplication

The pattern of handling nullable values is repeated:

const codeStr = code === null ? "null" : code.toString();
const reasonStr = reason === null ? "null" : `"${reason}"`;

Recommendation: Extract a helper function:

function stringifyNullable<T>(value: T | null, formatter: (v: T) => string = String): string {
  return value === null ? "null" : formatter(value);
}

6. Testing Coverage

There are no test additions for the new stringify functions.

Recommendation: Add unit tests covering:

  • Each message type variant
  • Null handling
  • Edge cases (empty maps, zero-length buffers, large bigints)
  • Potentially sensitive data scenarios

Example test structure:

describe('stringify', () => {
  describe('stringifyArrayBuffer', () => {
    it('should format buffer with byte length', () => {
      const buffer = new ArrayBuffer(1024);
      expect(stringifyArrayBuffer(buffer)).toBe('ArrayBuffer(1024)');
    });
  });
  
  describe('stringifyMap', () => {
    it('should format map entries', () => {
      const map = new Map([['key1', 'val1'], ['key2', 'val2']]);
      expect(stringifyMap(map)).toBe('Map(2){"key1": "val1", "key2": "val2"}');
    });
  });
  
  // ... more tests
});

Minor Issues

  1. Inconsistent String Formatting: Some cases use backticks with interpolation, others concatenate. Stick with one approach.

  2. Missing JSDoc Examples: The JSDoc comments could benefit from examples:

    /**
     * Stringify ToServerTunnelMessageKind for logging
     * Handles ArrayBuffers, BigInts, and Maps that can't be JSON.stringified
     * 
     * @example
     * stringifyToServerTunnelMessageKind({ tag: "TunnelAck" })
     * // => "TunnelAck"
     */
  3. Index Conversion: In mod.ts:910, index: eventWrapper.index.toString() - good catch converting BigInt to string, but consider doing this in the stringify function itself for consistency.

Performance Impact

The changes add minimal overhead:

  • Only executed when logging (typically INFO level)
  • String concatenation is relatively fast
  • No additional memory allocation for large buffers (just metadata)

Recommendations Summary

High Priority:

  1. Add tests for the stringify module
  2. Sanitize sensitive headers in logs
  3. Use exhaustive switches instead of ternary chains

Medium Priority:
4. Add error handling for edge cases
5. Consider truncation for large collections
6. Extract nullable formatting helper

Low Priority:
7. Add JSDoc examples
8. Standardize string formatting approach

Conclusion

This is a solid improvement that addresses a real logging issue. With the suggested security and robustness enhancements, particularly around sensitive data handling and test coverage, this will be a strong addition to the codebase.

Verdict: Approve with recommendations for follow-up improvements.

@claude
Copy link

claude bot commented Nov 6, 2025

Pull Request Review

Summary

This PR adds explicit stringification functions for tunnel messages, commands, and events to improve logging output. Previously, objects containing ArrayBuffer, bigint, and Map types were being logged directly, which could lead to poor formatting or serialization issues.

Code Quality & Best Practices

Strengths:

  • Well-structured code: The new stringify.ts module is cleanly organized with separate functions for each protocol type
  • Type safety: All functions properly type their parameters using the protocol types
  • Comprehensive coverage: Handles all message types in the protocol (ToServer, ToClient, Commands, Events)
  • Helper functions: Good use of small helper functions to DRY up the code
  • Documentation: JSDoc comments explain the purpose of each function

Minor Suggestions:

  1. Escaping in stringifyMap: The current implementation does not escape quotes in map keys/values. If a header value contains a double quote, it could break the output formatting
  2. Consistency in null handling: Some places use === null checks with ternaries, while others rely on TypeScript type narrowing
  3. Type exhaustiveness: The stringifyEvent function has an Unknown fallback for intent types (line 152). Consider using exhaustive switches with TypeScript never type

Potential Issues

Security Considerations:

  • Header exposure: The stringifyMap function logs all headers, which could potentially include sensitive information (auth tokens, API keys). Consider adding a redaction mechanism for sensitive headers (Authorization, Cookie, etc.) or truncating header values with a configurable max length

Performance Considerations

ArrayBuffer stringification: The approach is efficient and appropriate for logging. If debugging requires seeing actual content, you might want to add a debug mode that shows a hex preview for small buffers.

String concatenation: The use of template literals is fine for logging. Performance impact should be minimal unless processing extremely high message volumes.

Test Coverage

Missing:

  • No tests were added for the new stringify.ts module
  • Consider adding unit tests to verify:
    • Correct formatting of each message type
    • Proper handling of null values
    • Edge cases (empty maps, zero-length buffers, very large bigints)

Architecture & Design

Excellent separation of concerns: Moving stringification logic into a dedicated module is the right architectural decision. This:

  • Keeps logging logic separate from business logic
  • Makes the code more testable
  • Improves maintainability

Structured logging improvement: The changes in mod.ts and tunnel.ts show better structured logging practices by using structured fields instead of spreading object properties.

Summary & Recommendation

Overall Assessment: Approve with minor suggestions

This is a solid improvement to logging infrastructure. The code is well-structured and addresses a real problem with logging complex types.

Action Items:

  1. Consider adding security redaction for sensitive headers
  2. Add unit tests for the stringify functions
  3. (Optional) Add quote escaping in stringifyMap

The PR can be merged as-is if security considerations around header logging are acceptable for your use case, but I recommend addressing the test coverage before merging.

Great work on improving observability!

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 6, 2025

Merge activity

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

@graphite-app graphite-app bot closed this Nov 6, 2025
@graphite-app graphite-app bot deleted the 11-05-chore_runner_explicitly_stringify_tunnel_messages_commands_and_events branch November 6, 2025 05: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.

2 participants