Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@vercel
Copy link

vercel bot commented Nov 10, 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 8:55pm
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 13, 2025 8:55pm
rivet-inspector Ignored Ignored Preview Nov 13, 2025 8:55pm
rivet-site Ignored Ignored Preview Nov 13, 2025 8:55pm

Copy link
Member Author

NathanFlurry commented Nov 10, 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 10, 2025

Code Review for PR #3429

Summary

This PR successfully refactors WebSocket protocol parsing logic by extracting duplicated code into a shared utility function parseWebSocketProtocols(). The refactoring reduces code duplication and improves maintainability.

✅ Positive Changes

  1. Good DRY principle application: Successfully eliminates ~50 lines of duplicated parsing logic across 3 files
  2. Clear function documentation: The new parseWebSocketProtocols() function has a clear JSDoc comment
  3. Consistent behavior: All three call sites now use the same parsing logic, reducing the risk of inconsistent behavior
  4. Improved maintainability: Future changes to WebSocket protocol parsing only need to happen in one place

🔍 Code Quality & Best Practices

Issue 1: Silent fallback behavior change in getRequestEncoding()

The PR changes getRequestEncoding() to return "json" as a default instead of throwing an error when the encoding header is missing:

// Before:
if (!encodingParam) {
    throw new errors.InvalidEncoding("undefined");
}

// After:
if (!encodingParam) {
    return "json";
}

Concerns:

  • This is a breaking behavioral change that affects error handling in common/router.ts:66 where the try-catch expects this function to throw
  • The comment mentions supporting "vanilla curl requests," but this changes existing error handling semantics
  • Could mask configuration issues where clients forget to send the encoding header

Recommendation: Consider one of these approaches:

  1. Keep the original error-throwing behavior and add a separate getRequestEncodingOrDefault() function for cases where a default is acceptable
  2. Add an optional parameter: getRequestEncoding(req: HonoRequest, defaultEncoding?: Encoding)
  3. If this change is intentional, update the error handler in common/router.ts to remove the now-unnecessary try-catch

Issue 2: Missing error handling in parseWebSocketProtocols()

const encoding = EncodingSchema.parse(encodingRaw);
const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;

Both EncodingSchema.parse() and JSON.parse() can throw exceptions:

  • If encodingRaw is undefined or invalid, EncodingSchema.parse() will throw
  • If connParamsRaw contains invalid JSON, JSON.parse() will throw

Recommendation:

  • Use EncodingSchema.safeParse() like the original getRequestEncoding() function does, and throw an InvalidEncoding error with proper context
  • Wrap JSON.parse() in try-catch and throw an appropriate error (e.g., InvalidRequest or MalformedMessage)
  • This ensures consistent error messages for clients

Example:

const result = EncodingSchema.safeParse(encodingRaw);
if (!result.success) {
    throw new errors.InvalidEncoding(encodingRaw);
}
const encoding = result.data;

let connParams: unknown;
if (connParamsRaw) {
    try {
        connParams = JSON.parse(connParamsRaw);
    } catch (error) {
        throw new errors.MalformedMessage(`Invalid connection parameters: ${error}`);
    }
}

🐛 Potential Bugs

Bug 1: encodingRaw can be undefined

If no rivet_encoding. protocol is provided, encodingRaw will be undefined, causing EncodingSchema.parse(undefined) to throw without a clear error message.

Expected behavior: Should either:

  1. Throw InvalidEncoding("undefined") for consistency with the previous code
  2. Default to "json" if that's the intended new behavior

Bug 2: Inconsistent default behavior

  • getRequestEncoding() now defaults to "json" when missing
  • parseWebSocketProtocols() will throw when encoding is missing

This creates inconsistent behavior between HTTP requests and WebSocket connections.

🔒 Security Concerns

Low-severity concern: Missing URL decode validation

connParamsRaw = decodeURIComponent(
    protocol.substring(WS_PROTOCOL_CONN_PARAMS.length),
);

While decodeURIComponent() can throw on malformed input, the error isn't caught or handled gracefully. Consider wrapping in try-catch to provide a clearer error message.

⚡ Performance Considerations

No significant performance concerns. The refactoring actually improves performance slightly by:

  • Removing code duplication (smaller bundle size)
  • Using the same parsing logic (more consistent V8 optimization)

🧪 Test Coverage

Missing test coverage:

  • No unit tests found for the new parseWebSocketProtocols() function
  • No tests for getRequestEncoding() default behavior change

Recommendation:
Add tests covering:

  1. Valid protocol parsing with both encoding and connParams
  2. Valid protocol with encoding only
  3. Valid protocol with connParams only
  4. No protocols provided (should test error/default behavior)
  5. Invalid encoding value
  6. Malformed JSON in connParams
  7. Malformed URL encoding in connParams

📋 Suggested Changes

  1. Add proper error handling to parseWebSocketProtocols() (High priority)
  2. Reconsider the default behavior change in getRequestEncoding() (High priority)
  3. Add unit tests (Medium priority)
  4. Ensure consistent default behavior between HTTP and WebSocket paths (Medium priority)
  5. Add error handling for decodeURIComponent() (Low priority)

Summary Rating

  • Code Quality: ⚠️ Good with concerns - The refactoring is solid, but error handling needs improvement
  • Security: ✅ Acceptable - No major security issues
  • Performance: ✅ Good - Slight improvement
  • Test Coverage: ❌ Insufficient - Missing tests for new functionality

Overall, this is a good refactoring that improves code maintainability, but it needs stronger error handling and test coverage before merging.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 10, 2025

More templates

@rivetkit/actor

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

@rivetkit/cloudflare-workers

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

@rivetkit/core

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

@rivetkit/db

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

@rivetkit/framework-base

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

@rivetkit/next-js

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

@rivetkit/react

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

rivetkit

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

@rivetkit/sql-loader

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

@rivetkit/engine-runner

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

@rivetkit/engine-runner-protocol

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

commit: e10206c

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review for PR #3429

Summary

This PR refactors WebSocket protocol parsing logic by extracting duplicated code into a shared utility function parseWebSocketProtocols. The refactoring is well-executed and improves code maintainability by eliminating duplication across router.ts and actor-driver.ts.

Positive Aspects

Code Quality:

  • ✅ Successfully eliminates ~55 lines of duplicated parsing logic
  • ✅ The new parseWebSocketProtocols function is well-documented with a clear JSDoc comment
  • ✅ Import cleanup properly removes unused constants (WS_PROTOCOL_CONN_PARAMS, WS_PROTOCOL_ENCODING) from files that no longer need them
  • ✅ Function is properly exported and placed in the appropriate shared module (router-endpoints.ts)

Behavior Change:

  • ✅ The change to getRequestEncoding to default to "json" is a good UX improvement for supporting vanilla curl requests
  • ✅ The comment explains the rationale for the default behavior

Issues & Concerns

🔴 Critical: Missing Error Handling

Location: router-endpoints.ts:600-601

The new parseWebSocketProtocols function has a critical error handling issue:

const encoding = EncodingSchema.parse(encodingRaw);
const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;

Problems:

  1. When encodingRaw is undefined (no encoding protocol provided), EncodingSchema.parse() will throw a Zod validation error, but this is not wrapped in a try-catch or handled with .safeParse()
  2. JSON.parse(connParamsRaw) can throw if the JSON is malformed, but this is not wrapped in error handling

Impact:

  • Uncaught exceptions will crash the WebSocket connection establishment
  • Users will get generic internal server errors instead of helpful error messages
  • This is inconsistent with the error handling patterns used elsewhere in the codebase

Previous Behavior:
Looking at the original code in both files, they simply called .parse() without error handling, so this PR doesn't introduce a new bug—it just preserves an existing one. However, since you're touching this code, it would be an excellent opportunity to fix it.

Recommended Fix:

export function parseWebSocketProtocols(protocols: string | null | undefined): {
	encoding: Encoding;
	connParams: unknown;
} {
	let encodingRaw: string | undefined;
	let connParamsRaw: string | undefined;

	if (protocols) {
		const protocolList = protocols.split(",").map((p) => p.trim());
		for (const protocol of protocolList) {
			if (protocol.startsWith(WS_PROTOCOL_ENCODING)) {
				encodingRaw = protocol.substring(WS_PROTOCOL_ENCODING.length);
			} else if (protocol.startsWith(WS_PROTOCOL_CONN_PARAMS)) {
				connParamsRaw = decodeURIComponent(
					protocol.substring(WS_PROTOCOL_CONN_PARAMS.length),
				);
			}
		}
	}

	// Handle encoding with proper error handling
	const encodingResult = EncodingSchema.safeParse(encodingRaw);
	if (!encodingResult.success) {
		throw new errors.InvalidEncoding(encodingRaw);
	}
	const encoding = encodingResult.data;

	// Handle conn params with proper error handling
	let connParams: unknown = undefined;
	if (connParamsRaw) {
		try {
			connParams = JSON.parse(connParamsRaw);
		} catch (err) {
			throw new errors.InvalidParams(
				`Invalid connection params JSON: ${err}`,
			);
		}
	}

	return { encoding, connParams };
}

This would:

  • Use .safeParse() for validation with proper error checking (consistent with getRequestEncoding)
  • Wrap JSON.parse in try-catch (consistent with getRequestConnParams)
  • Throw appropriate ActorError subclasses that provide helpful error messages to clients

🟡 Minor: Inconsistent Default Behavior

Location: router-endpoints.ts:524-528 vs parseWebSocketProtocols:600

The getRequestEncoding function now defaults to "json" when the header is missing (line 527), but parseWebSocketProtocols does not default encodingRaw when it's undefined. This means:

  • HTTP requests without encoding header → defaults to "json"
  • WebSocket connections without encoding protocol → throws error ❌

This inconsistency could confuse users. Consider applying the same default behavior:

const encodingResult = EncodingSchema.safeParse(encodingRaw ?? "json");

Security Considerations

✅ No security issues identified. The refactoring maintains the same security properties as the original code:

  • Connection parameters are properly URI-decoded
  • JSON parsing happens on user-controlled input (appropriate error handling would mitigate risks)

Performance Considerations

✅ Performance is neutral or slightly improved:

  • No additional allocations or computations introduced
  • Code size reduced (better for bundle size in TypeScript)

Test Coverage

⚠️ Missing Information: The PR doesn't include test changes or additions. Consider adding tests for:

  1. parseWebSocketProtocols with various protocol combinations
  2. Error cases (missing encoding, malformed JSON)
  3. Edge cases (empty protocols, URL-encoded connection params)

Example test cases to consider:

// Valid cases
parseWebSocketProtocols("rivet_encoding.json")
parseWebSocketProtocols("rivet_encoding.cbor,rivet_conn_params.%7B%22foo%22%3A%22bar%22%7D")

// Error cases (once error handling is added)
parseWebSocketProtocols("") // Should use default or error
parseWebSocketProtocols("rivet_encoding.invalid") // Invalid encoding
parseWebSocketProtocols("rivet_conn_params.{invalid-json}") // Malformed JSON

Recommendations

Before Merging:

  1. 🔴 Add proper error handling to parseWebSocketProtocols (see detailed recommendation above)
  2. 🟡 Consider adding default encoding behavior for consistency
  3. Add unit tests for the new utility function

Future Improvements:

  • Consider extracting similar patterns for other protocol/header parsing utilities
  • Document the WebSocket protocol format in a centralized location

Conclusion

This is a solid refactoring that improves code maintainability. However, the missing error handling in parseWebSocketProtocols should be addressed before merging to ensure a robust user experience and prevent uncaught exceptions.

The refactoring itself is well-structured and follows good practices—it just needs better error handling to match the quality of the rest of the codebase.

@NathanFlurry NathanFlurry force-pushed the 11-09-refactor_rivetkit_restructure_connection_lifecycle_contexts branch from 7de7488 to 27c352a Compare November 13, 2025 02:47
@NathanFlurry NathanFlurry force-pushed the 11-09-refactor_rivetkit_extract_websocket_protocol_parsing_to_shared_utility branch from 8fdd032 to 14348ed Compare November 13, 2025 02:47
@vercel
Copy link

vercel bot commented Nov 13, 2025

Deployment failed with the following error:

Too many requests - try again in 5 minutes (more than 120, code: "api-deployments-flood-pro").

Learn More: https://vercel.com/docs/limits#rate-limits

@claude
Copy link

claude bot commented Nov 13, 2025

PR Review: Extract WebSocket Protocol Parsing to Shared Utility

Summary

This PR successfully extracts duplicated WebSocket protocol parsing logic into a shared utility function (parseWebSocketProtocols). The refactoring is clean and improves code maintainability by eliminating ~50 lines of duplicated code across 3 files.

Positive Aspects

Code Quality ✅

  • Excellent DRY principle application: The extraction of parseWebSocketProtocols eliminates significant code duplication
  • Consistent API: The function returns a clean object structure { encoding, connParams } that's easy to use
  • Good documentation: Added helpful JSDoc comment explaining the function's purpose
  • Proper location: Placing the utility in router-endpoints.ts makes sense since it's shared between router and driver code

Improved User Experience ✅

  • Better default handling: Changing getRequestEncoding to default to "json" when encoding is not provided is a significant UX improvement, as noted in the comment about supporting vanilla curl requests

Issues Found

1. Critical: Inconsistent Error Handling 🔴

The new parseWebSocketProtocols function has different error handling behavior compared to the original code:

Before (router.ts:142):

const encoding = EncodingSchema.parse(encodingRaw);

After (router-endpoints.ts:600):

const encoding = EncodingSchema.parse(encodingRaw);

The issue is that when encodingRaw is undefined (no protocol provided), EncodingSchema.parse() will throw a Zod validation error, but there's no handling for this case. This is inconsistent with the UX improvement made to getRequestEncoding.

Recommendation: Add a default value or handle the undefined case:

const encoding = EncodingSchema.parse(encodingRaw ?? "json");

This would align with the new behavior of getRequestEncoding and provide better UX for WebSocket connections.

2. Bug: JSON.parse Can Throw 🟡

In router-endpoints.ts:601:

const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;

The JSON.parse call is not wrapped in error handling. If connParamsRaw is malformed JSON, this will throw an uncaught error.

Recommendation: Wrap in try-catch and throw an appropriate ActorError:

let connParams: unknown;
if (connParamsRaw) {
  try {
    connParams = JSON.parse(connParamsRaw);
  } catch (error) {
    throw new errors.InvalidParams(`Failed to parse connection parameters: ${error}`);
  }
}

3. Inconsistency: getRequestEncoding Change 🟡

The change to getRequestEncoding (router-endpoints.ts:527) is good for UX, but it creates an inconsistency:

  • HTTP requests: default to "json" if encoding not provided ✅
  • WebSocket requests: will throw error if encoding not provided ❌

This behavioral difference between the two protocols is confusing and could lead to bugs.

Recommendation: Apply the same default behavior to both protocols for consistency.

Performance Considerations

No performance concerns: The refactoring doesn't introduce any performance regressions. String operations are minimal and well-contained.

Security Considerations

⚠️ Potential DoS via malformed JSON: The unhandled JSON.parse could be exploited by sending malformed connection parameters, causing the server to throw uncaught exceptions. While this is mitigated by existing error boundaries, it's better to handle explicitly.

Test Coverage

⚠️ Missing test coverage: There don't appear to be unit tests for the new parseWebSocketProtocols function. This is concerning given that it handles user input and has error cases.

Recommendations:

  1. Add unit tests covering:

    • Valid encoding + connParams
    • Missing encoding (should test current behavior and potentially fix to default to "json")
    • Missing connParams
    • Malformed JSON in connParams
    • Multiple protocols in various orders
    • Invalid encoding values
    • Edge cases (empty string, special characters, etc.)
  2. Integration tests to verify WebSocket connections work with:

    • No protocol header (test default behavior)
    • Only encoding protocol
    • Only connParams protocol
    • Both protocols

Additional Observations

Code Style ✅

  • Follows TypeScript best practices
  • Proper use of const/let
  • Good naming conventions
  • Consistent formatting

Documentation

The added comment about defaulting to JSON for curl requests is helpful. Consider adding similar documentation to parseWebSocketProtocols explaining expected protocol format.

Summary

Overall assessment: Good refactoring with some critical issues to address

Required fixes:

  1. Handle undefined encoding in parseWebSocketProtocols (align with HTTP behavior)
  2. Add error handling for JSON.parse
  3. Add test coverage for the new utility function

Nice to have:

  • Consistent default behavior between HTTP and WebSocket protocols
  • More comprehensive documentation of expected protocol formats

Once these issues are addressed, this will be a solid improvement to the codebase.


🤖 Generated with Claude Code

@claude
Copy link

claude bot commented Nov 13, 2025

Code Review: refactor(rivetkit): extract WebSocket protocol parsing to shared utility

Summary

This PR extracts duplicated WebSocket protocol parsing logic into a shared utility function parseWebSocketProtocols. The refactoring successfully eliminates ~50 lines of duplicate code across two locations while maintaining the same functionality.

Positive Aspects ✅

  1. DRY Principle: Excellent refactoring that eliminates code duplication between router.ts and actor-driver.ts
  2. Clear Documentation: The new parseWebSocketProtocols function has proper JSDoc documentation
  3. Consistent Behavior: The extracted logic maintains identical functionality across both call sites
  4. Improved Maintainability: Future changes to protocol parsing only need to happen in one place
  5. Better Default Handling: The change to getRequestEncoding to default to "json" is a good UX improvement for vanilla curl requests

Issues & Concerns 🔴

1. Critical: Error Handling Inconsistency

The new parseWebSocketProtocols function has different error handling compared to the original implementations:

Before (original code):

// Both locations handled the case where encoding is undefined
const encoding = EncodingSchema.parse(encodingRaw);

After (new function):

// Line 600 in router-endpoints.ts
const encoding = EncodingSchema.parse(encodingRaw);

Problem: When encodingRaw is undefined, EncodingSchema.parse() will throw a Zod validation error rather than a meaningful application error. This is a regression from the original behavior.

Original behavior in getRequestEncoding (lines 524-535):

  • Explicitly checks for undefined and returns default "json"
  • Uses safeParse() for validation
  • Throws InvalidEncoding error with the invalid value

New behavior in parseWebSocketProtocols:

  • No check for undefined
  • Uses parse() which throws generic Zod errors
  • Users will see cryptic Zod validation errors instead of InvalidEncoding

2. Potential Bug: JSON Parsing Exception

Line 601:

const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;

Issue: JSON.parse() can throw an exception if connParamsRaw contains malformed JSON. The original implementations had this same issue, but now it's centralized in a shared utility that should be more robust.

Impact: An attacker or buggy client could send malformed JSON in the connection parameters, causing an unhandled exception that crashes the WebSocket connection handler.

3. Type Safety: Missing Return Type Annotations

The function returns an inline object type. Consider defining a proper type:

export interface WebSocketProtocolConfig {
  encoding: Encoding;
  connParams: unknown;
}

export function parseWebSocketProtocols(
  protocols: string | null | undefined
): WebSocketProtocolConfig {
  // ...
}

Recommendations 🔧

High Priority:

  1. Fix error handling to match the robustness of getRequestEncoding:
export function parseWebSocketProtocols(protocols: string | null | undefined): {
  encoding: Encoding;
  connParams: unknown;
} {
  let encodingRaw: string | undefined;
  let connParamsRaw: string | undefined;

  if (protocols) {
    const protocolList = protocols.split(",").map((p) => p.trim());
    for (const protocol of protocolList) {
      if (protocol.startsWith(WS_PROTOCOL_ENCODING)) {
        encodingRaw = protocol.substring(WS_PROTOCOL_ENCODING.length);
      } else if (protocol.startsWith(WS_PROTOCOL_CONN_PARAMS)) {
        connParamsRaw = decodeURIComponent(
          protocol.substring(WS_PROTOCOL_CONN_PARAMS.length),
        );
      }
    }
  }

  // Use safeParse like getRequestEncoding does
  const result = EncodingSchema.safeParse(encodingRaw);
  if (\!result.success) {
    throw new errors.InvalidEncoding(encodingRaw || "undefined");
  }

  // Add error handling for JSON parsing
  let connParams: unknown = undefined;
  if (connParamsRaw) {
    try {
      connParams = JSON.parse(connParamsRaw);
    } catch (err) {
      throw new errors.InvalidParams(
        `Invalid conn params JSON: ${err}`,
      );
    }
  }

  return { encoding: result.data, connParams };
}
  1. Add unit tests for the new utility function covering:
    • Valid encoding values
    • Invalid encoding values
    • Missing encoding
    • Valid connection parameters
    • Malformed JSON in connection parameters
    • Edge cases (empty string, null, undefined)

Medium Priority:

  1. Consider default encoding: Should parseWebSocketProtocols also default to "json" when encoding is not provided, similar to getRequestEncoding? The current behavior will throw an error, which may not be the desired UX.

  2. Extract the type definition for better reusability

Security Considerations 🔒

  • Input Validation: The function processes untrusted input from WebSocket headers. The lack of proper error handling for JSON.parse is a potential DoS vector
  • URL Decoding: The decodeURIComponent call should be wrapped in a try-catch to handle malformed percent-encoding

Test Coverage 📊

Current: No tests found for this new function
Recommended: Add comprehensive unit tests before merging

Overall Assessment

This is a good refactoring that improves code organization, but it has critical error handling regressions that need to be addressed before merging. The extracted function is less robust than the code it's replacing, which is a step backward in terms of error handling and user experience.

Recommendation: Request changes to fix error handling and add tests.


Files reviewed:

  • rivetkit-typescript/packages/rivetkit/src/actor/router-endpoints.ts
  • rivetkit-typescript/packages/rivetkit/src/actor/router.ts
  • rivetkit-typescript/packages/rivetkit/src/drivers/engine/actor-driver.ts

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 13, 2025

Merge activity

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

@graphite-app graphite-app bot closed this Nov 13, 2025
@graphite-app graphite-app bot deleted the 11-09-refactor_rivetkit_extract_websocket_protocol_parsing_to_shared_utility branch November 13, 2025 21:16
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