Skip to content

refactor: clarify RSC parser helpers and release safeguards (#3258)#3343

Open
justin808 wants to merge 6 commits into
mainfrom
jg/3258-rsc-migration-parser-clarity
Open

refactor: clarify RSC parser helpers and release safeguards (#3258)#3343
justin808 wants to merge 6 commits into
mainfrom
jg/3258-rsc-migration-parser-clarity

Conversation

@justin808
Copy link
Copy Markdown
Member

@justin808 justin808 commented May 21, 2026

Summary

Follow-up to #3219 / fixes #3258. This PR is now rebased onto main, so the stale stacked-branch CI failure from the pre-#3420 OpenTelemetry syntax issue is no longer part of the branch.

RSC migration parser cleanup

  • Rename rsc_plugin_without_client_references? to any_rsc_plugin_missing_client_references? and document the existential semantics.
  • Consolidate the lightweight JS scanner support/limitation notes onto advance_js_scan_state, including caller coverage and regex/template-literal caveats.
  • Clarify why add_rsc_client_references_setup keeps defensive duplicate-helper guards.

Adjacent hardening

  • Strengthen Node renderer SECURITY: comments for CommonJS wrapping via both additionalContext and supportModules.
  • Make the package-json publish rewrite use a same-directory temp file plus atomic rename before marking the file as changed.
  • Add coverage for the package-json pin fallback warning formatter.
  • Keep the retry-sleep guard in release metadata lookup explicit and make the webpack helper test description path-agnostic.

Review Follow-Ups

  • Must-fix: none remaining from thread-aware review.
  • Optional fixed: supportModules security anchor, package-json warning formatter spec, and release helper atomic rewrite.
  • Discuss/advice: the partial-write trade-off is now avoided by atomic rename, so the prior caveat no longer needs to be defended.

Test Plan

  • pnpm install --frozen-lockfile
  • bundle exec rspec react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb — 110 examples, 0 failures
  • (cd react_on_rails && bundle exec rubocop) — 203 files, no offenses
  • pnpm run lint
  • pnpm run type-check
  • pnpm --dir packages/react-on-rails-pro-node-renderer exec tsc --project src/tsconfig.json --noEmit
  • pnpm exec prettier --check packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts packages/react-on-rails/tests/webpackHelpers.test.ts

Note

Low Risk
Changes are mostly comments, renames, docs, and safer file I/O during publish; no runtime behavior changes to SSR auth or payment paths.

Overview
This PR tightens documentation and naming around RSC webpack migration and Node renderer config, plus small release/generator reliability fixes.

RSC generator: rsc_plugin_without_client_references? is renamed to any_rsc_plugin_missing_client_references? with comments explaining existential semantics (not the complement of “all define clientReferences” when multiple plugins exist). Lightweight JS scanner limits and the advance_js_scan_state contract are centralized in one place; add_rsc_client_references_setup duplicate-guard rationale is spelled out.

Node renderer: configBuilder.ts SECURITY: notes now state explicitly that supportModules: true and any plain-object additionalContext (including {}) wrap the bundle with host require, disabling VM sandboxing.

Release: Publish-time package.json workspace rewrites use a same-directory temp file + atomic rename; changed is set only after rename succeeds so ensure restore matches reality. NPM metadata retry loop uses a clearer unless guard.

Generator deps: Failed installs that fall back to writing pins now emit a formatted warning listing name@version pairs; specs cover that and release restore behavior.

Tests: Webpack reactDomClientWarning test description is path-agnostic.

Reviewed by Cursor Bugbot for commit 06dc380. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Tests

    • Added test coverage for webpack helper warnings and dependency manager fallback messaging.
  • Chores

    • Improved npm publishing workflow with atomic file operations and optimized retry logic.
    • Refactored React Server Components generator logic for enhanced clientReferences handling.
    • Enhanced internal documentation and helper methods for build tooling.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 923fdb2c-3626-4b9f-b7dc-56e83c9b6171

📥 Commits

Reviewing files that changed from the base of the PR and between e2f2ca0 and 06dc380.

📒 Files selected for processing (7)
  • packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts
  • packages/react-on-rails/tests/webpackHelpers.test.ts
  • rakelib/release.rake
  • react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb
  • react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb
  • react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
  • react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb

Walkthrough

This PR makes targeted improvements across multiple subsystems: Node-renderer VM sandboxing documentation, atomic file operations for npm publishing, extraction of a shared dependency warning helper, and refinement of RSC plugin detection logic to correctly handle multi-section configurations. No feature-level behavioral changes to user-facing functionality.

Changes

Maintenance and refinement improvements across Node-renderer, release infra, generators, and RSC setup

Layer / File(s) Summary
Node-renderer VM sandboxing documentation
packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts
Security documentation for supportModules and additionalContext configuration options expands on when the renderer wraps bundles, injects host require, and how plain objects change execution mode and sandboxing behavior.
Webpack warning assertion refinement
packages/react-on-rails/tests/webpackHelpers.test.ts
Test assertion for reactDomClientWarning is updated to verify the warning match is independent of the file path referenced in webpack's "Module not found" message.
Atomic package.json publication for npm release
rakelib/release.rake, react_on_rails/spec/react_on_rails/release_rake_helpers_spec.rb
New write_publishable_package_json helper performs atomic tempfile + rename writes to safely persist modified package.json for npm publishing; with_publishable_package_json sets the changed flag only after the atomic write completes. Test stub updated to reflect new write timing behavior.
Dependency manager pin fallback warning helper
react_on_rails/lib/generators/react_on_rails/js_dependency_manager.rb, react_on_rails/spec/react_on_rails/generators/js_dependency_manager_spec.rb
Version-pin warning formatting is extracted into a new package_json_pin_fallback_warning helper that generates comma-separated name@version specs and includes "Wrote the following version pins to package.json" messaging. Test verifies the helper's formatting and output.
RSC client references migration logic refinement
react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb
New any_rsc_plugin_missing_client_references? predicate detects when at least one plugin section lacks the top-level clientReferences: key; "rewrite needed?" and "rewritable plugin?" gates now use this existential check instead of whole-plugin predicates, correctly handling multi-section configurations. Scanner and defensive-guard documentation clarifies supported constructs (regex/nested-template edge cases), downstream validation behavior, and why duplicate-declaration guards are preserved.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • #3258: Follow-up RSC migration parser helper clarity — PR directly addresses all three nits: renames the predicate with explicit "any-section" semantics via any_rsc_plugin_missing_client_references?, clarifies the scanner surface around regex literals and nested templates, and documents why add_rsc_client_references_setup defensive guards are preserved.

Possibly related PRs

  • shakacode/react_on_rails#3221: Configuration documentation clarifies how supportModules and additionalContext affect VM injection of host globals, aligning with node-renderer missing-globals and fetch-injection guidance in that PR.
  • shakacode/react_on_rails#3358: Webpack warning assertion refinement directly relates to that PR's introduction of reactDomClientWarning matcher and webpack-4/webpack-5 warning test expectations.
  • shakacode/react_on_rails#3219: Both PRs modify RSC RSCWebpackPlugin clientReferences migration logic; this PR refines the "rewrite needed?" detection while that PR updates templates to inject scoped clientReferences: rscClientReferences.

Suggested labels

enhancement, review-needed, full-ci, P3

Poem

🐰 Atomic writes and clearer paths ahead,
Docs refined, and logic led,
Helpers extracted, logic tight,
RSC plugin checks now right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main refactoring work (RSC parser helpers and release safeguards) and directly relates to the changeset across multiple files including client_references.rb, release.rake, and documentation updates.
Linked Issues check ✅ Passed The PR comprehensively addresses all three coding objectives from issue #3258: renames rsc_plugin_without_client_references? to any_rsc_plugin_missing_client_references? with documented semantics, clarifies JS scanner limitations in comments, and explains defensive guards in add_rsc_client_references_setup.
Out of Scope Changes check ✅ Passed All changes are within scope: RSC parser clarifications, supporting helper test coverage, security documentation hardening, package.json atomic write safety, and retry-loop readability. No unrelated refactoring or feature changes were introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jg/3258-rsc-migration-parser-clarity

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

packages/react-on-rails/tests/webpackHelpers.test.ts

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 21, 2026

Greptile Summary

This is a documentation and naming clarification pass over rsc_setup.rb with no behaviour change. A grep across the full repo confirms the old method name rsc_plugin_without_client_references? has been fully replaced by any_rsc_plugin_missing_client_references? with no dangling references.

  • Method rename (rsc_plugin_without_client_references?any_rsc_plugin_missing_client_references?): the new name accurately reflects the existential (any?) semantics and pairs more intuitively with the sibling rsc_plugin_defines_client_references?. A doc-comment is added explaining the non-complement behaviour when multiple plugin sections are present.
  • Scanner documentation consolidated onto advance_js_scan_state: the supported lexical surface (comments, all three string types, ${expr} interpolations), the two unsupported cases (regex literals, nested template literals), the downstream catch via rsc_plugin_options_followed_by_close_paren?, and a concrete "future expansion" sketch are all now in one authoritative place.
  • Guard documentation in add_rsc_client_references_setup made explicit: the comment now names the concrete failure mode the defensive returns prevent (Identifier 'rscClientReferences' has already been declared SyntaxError) and articulates why keeping them is cheaper than re-deriving the precondition at every future call site.

Confidence Score: 5/5

Safe to merge — the only functional change is a method rename that is fully applied with no dangling references anywhere in the repo.

All changes are documentation and a method rename. No logic paths are altered, the renamed predicate's call site is updated, and a repo-wide grep confirms zero remaining uses of the old name. The expanded advance_js_scan_state comment and the clarified guard rationale in add_rsc_client_references_setup are accurate descriptions of the existing code behaviour.

No files require special attention.

Important Files Changed

Filename Overview
react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Documentation-only refactor: renames one predicate method to clarify existential semantics and consolidates JS-scanner surface documentation onto advance_js_scan_state. No logic changes; old name has zero remaining references.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[rewritable_rsc_plugin?] -->|calls| B["any_rsc_plugin_missing_client_references?\nrenamed from rsc_plugin_without_client_references?"]
    B --> C[rsc_plugin_option_sections]
    C --> D{any section missing clientReferences?}
    D -->|yes| E[return true - file is rewritable]
    D -->|no| F[rsc_plugin_defines_client_references?]
    F -->|all configured| G[warn + return false]
    F -->|none found| H[warn_missing_rsc_plugin_target + return false]

    C --> JSS
    subgraph JSS [advance_js_scan_state - central dispatcher]
        S1[line and block comments]
        S2[single / double / template-literal strings]
        S3[simple dollar-brace interpolations]
    end

    JSS -->|brace depth confused by regex or nested templates| I[rsc_plugin_option_sections_partition checks for trailing close-paren]
    I -->|missing| J[mark section unparseable - warn user]
    I -->|present| K[section is parseable]
Loading

Reviews (1): Last reviewed commit: "refactor: clarify RSC migration parser h..." | Re-trigger Greptile

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 21, 2026

Code Review

Summary: Pure documentation and refactoring PR — one method rename and comment/doc improvements in rsc_setup.rb. No runtime behavior changes; all existing specs pass.

What's good

  • Rename is semantically correct. any_rsc_plugin_missing_client_references? accurately conveys existential semantics (at least one section is missing the key), where the old name rsc_plugin_without_client_references? implied a universal check. The pairing with rsc_plugin_defines_client_references? is now consistent.
  • Non-complement clarification is valuable. The new docblock explicitly notes that a file with one configured and one unconfigured plugin returns true from both predicates — this edge case was easy to miss before.
  • Consolidated advance_js_scan_state doc is thorough. Listing supported constructs, unsupported surface (regex literals, nested template literals), the downstream catch mechanism, and future-expansion sketches all in one place is significantly cleaner than scattered per-method notes.
  • Defensive guard explanation in add_rsc_client_references_setup now documents the concrete failure mode (duplicate const → SyntaxError at config load) rather than just labelling it 'belt-and-suspenders'. Good.

Issues

1. Missing caller in the advance_js_scan_state docblock (see inline comment)

The docblock enumerates 6 callers but last_js_code_char_index (line ~1120) is a 7th. The list reads as exhaustive, so the omission is misleading — a future developer extending the scanner won't know to re-validate that method.

2. Minor: 'short-circuit on false' is imprecise terminology

In add_rsc_client_references_setup:

so in normal flow both guards short-circuit on false

'Short-circuit' conventionally describes boolean operators (&&, ||). Here the guards are return if condition — if the condition is false, no early return fires; nothing is short-circuited. Suggested wording: 'both conditions evaluate to false and no early return is triggered'.

3. Future-expansion note: point 2 understates the change scope

Both require expanding advance_js_default_scan_state

Stack-based nested template literals (point 2) would also require changes to advance_js_string_state (currently a simple toggle), not just advance_js_default_scan_state. Worth updating so a future implementer isn't surprised.


Overall this is a clean, low-risk clarification PR. The only actionable issue is the incomplete caller list; the other two are wording nits.

Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup.rb Outdated
@justin808 justin808 force-pushed the jg/3258-rsc-migration-parser-clarity branch 2 times, most recently from f952cb4 to 09137c8 Compare May 24, 2026 04:08
Comment thread react_on_rails_pro/lib/react_on_rails_pro/license_validator.rb
Comment thread packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 24, 2026

Code Review

Overview

The PR title describes an RSC migration parser refactor, but this branch carries 12 commits across 6 independent concerns, each at a different risk level:

Area Risk
RSC migration parser rename + doc consolidation Low (no behaviour change, all specs pass)
CI: remove setup-node-with-retry action Medium (see note below)
react-on-rails/webpackHelpers subpath export Low (additive new export with tests)
Pro: wrapServerComponentRenderer side-effect import Medium (runtime behaviour change, mitigated by webpack integration test)
Pro: algorithms: ["RS256"] + jwt constraint >= 2.7 High (security fix — see below)
Docs / planning / analysis cleanup Low

Security: algorithm:algorithms: in license_validator.rb

This is the most important change in the PR. jwt 3.0 removed the singular algorithm: option (deprecated in 2.x), so on 16.7.0.rc.0 with jwt 3.2.0 resolved the RS256 restriction was silently dropped — tokens signed with HS256 or bearing alg:none were not rejected by the algorithm check. The new plural algorithms: ["RS256"] is honored by both jwt 2.x (>= 2.7) and 3.x.

The two new specs (HS256 confusion attack, hand-crafted alg:none) directly cover the attack vectors the old code was vulnerable to. This fix is correct and the tests are excellent.


CI: Removing setup-node-with-retry

The composite action was created to work around intermittent V8 bytecode deserialization crashes on Node 22.21.0. The workflows now pin node-version: 22.11.0 (comment: "Pin to 22.11.0 (LTS) to avoid V8 bug in 22.21.0"), which is a valid mitigation. Two concerns:

  1. The Node pin is a comment-level constraint, not an enforced upper bound. If someone bumps the version past the buggy range later without reinstating the retry, the flakiness would silently return.
  2. Once the action is deleted, the original context for why it existed is gone from the repo.

Consider adding an inline note to the affected workflow files linking to the original issue/PR so the decision context survives the deletion.


wrapServerComponentRenderer/client side-effect import

The direct import 'react-on-rails-rsc/client.browser' is the right fix for the transitive-chain fragility, and the webpack integration test with memfs is the correct level of verification. One small risk: the import ordering may conflict with an import/order ESLint rule if side-effect imports are enforced in a specific group position — worth a quick lint run to confirm.


additionalContext documentation in configBuilder.ts

The new JSDoc correctly calls out that any non-null additionalContext (including {}) enables CommonJS mode with host require. The phrase "Use only with trusted bundle sources" is accurate but underplays the blast radius — the bundle gets unrestricted access to require('fs'), require('child_process'), etc. Consider stronger language in the warning. (Inline comment posted.)


Minor: CHANGELOG.md Fastify CVE entry placement

The Fastify 5.8.5 bump entry was added to the [16.7.0.rc.0] section (a tagged/released version). If this was retroactively added, confirm the described version matches what was actually shipped to avoid misleading the changelog.


Summary

The core RSC parser rename is clean and correct. The license_validator security fix is the most impactful change and is well-tested. The main review friction is that 12 distinct changes are bundled under a title that describes only one of them — no blocking issues found other than the documentation wording suggestion for additionalContext.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 24, 2026

size-limit report 📦

Path Size
react-on-rails/client bundled (gzip) 62.83 KB (0%)
react-on-rails/client bundled (gzip) (time) 62.83 KB (0%)
react-on-rails/client bundled (brotli) 53.9 KB (0%)
react-on-rails/client bundled (brotli) (time) 53.9 KB (0%)
react-on-rails-pro/client bundled (gzip) 63.77 KB (0%)
react-on-rails-pro/client bundled (gzip) (time) 63.77 KB (0%)
react-on-rails-pro/client bundled (brotli) 54.81 KB (0%)
react-on-rails-pro/client bundled (brotli) (time) 54.81 KB (0%)
registerServerComponent/client bundled (gzip) 127.95 KB (0%)
registerServerComponent/client bundled (gzip) (time) 127.95 KB (0%)
registerServerComponent/client bundled (brotli) 62.06 KB (0%)
registerServerComponent/client bundled (brotli) (time) 62.06 KB (0%)
wrapServerComponentRenderer/client bundled (gzip) 122.37 KB (0%)
wrapServerComponentRenderer/client bundled (gzip) (time) 122.37 KB (0%)
wrapServerComponentRenderer/client bundled (brotli) 57.09 KB (0%)
wrapServerComponentRenderer/client bundled (brotli) (time) 57.09 KB (0%)

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 24, 2026

Code Review

Overview

This PR is titled as a refactor of RSC migration parser helpers, but it is actually a mixed-scope PR containing at least five distinct categories of change:

  1. RSC parser refactor — rename + comment consolidation in rsc_setup.rb (the stated purpose)
  2. Security fixalgorithm:algorithms: in LicenseValidator#decode_license, with new attack-vector specs
  3. CI simplification — remove the custom setup-node-with-retry composite action
  4. New public APIreact-on-rails/webpackHelpers subpath export
  5. Bug fixes — RSC client manifest side-effect import, Fastify CVE bump, Ruby 3.4 base64 compatibility

The mixed scope makes individual rollback harder and obscures the security change in review. That said, the changes themselves are generally well-executed. Notes below by area.


RSC parser refactor (rsc_setup.rb) ✅

The rename from rsc_plugin_without_client_references? to any_rsc_plugin_missing_client_references? is a clear improvement — the original read as a universal check but the body was existential. The comment added to advance_js_scan_state is the right place to consolidate the scanner's supported-surface documentation. The guard explanation in add_rsc_client_references_setup is accurate and well-reasoned.

No issues here.


Security fix — JWT algorithm allowlist ⚠️ Important

The CHANGELOG correctly identifies this as a real vulnerability in 16.7.0.rc.0: algorithm: "RS256" (the jwt 3.x singular form) was silently ignored on jwt 3.x, meaning the algorithm restriction was not enforced and HS256/alg-none tokens could pass the JWT.decode step. Switching to algorithms: ["RS256"] (the jwt 2.x plural form, also accepted in 3.x) is the correct fix, and the new specs for the HS256-confusion and alg-none attacks are exactly the right regression tests.

One item deserves explicit acknowledgment: the previous release (16.7.0.rc.0, PR #3322) intentionally raised the floor from ~> 2.7 to >= 3.2.0 specifically to pick up the ruby-jwt empty-key HMAC vulnerability fix. This PR lowers it back to >= 2.7. The rationale (RS256 is asymmetric so the HMAC empty-key advisory doesn't apply to this validator) is sound, but it should be documented in the gemspec comment alongside the existing algorithm-restriction comment so a future maintainer understands why the floor was widened again. See inline comment on react_on_rails_pro.gemspec.


CI: removal of setup-node-with-retry ⚠️ Regression risk

The custom composite action was introduced specifically to handle intermittent V8 bytecode deserialization crashes on GitHub-hosted runners (nodejs/node#56010). The workflows still pin to node-version: '22.11.0' which was the known-stable version, so the pin is the actual mitigation — but the reason that mitigation is sufficient should be documented. If a runner image upgrade silently upgrades the cached Node binary or the pin is relaxed in a future PR, the V8 crashes will return and CI will be intermittently flaky with no obvious cause.

Suggestion: either keep a # Removed setup-node-with-retry: V8 crash issue resolved upstream in Node 22.x after 22.11.0. See nodejs/node#56010. comment in one of the workflow files, or open a tracking issue so the decision is findable.


New webpackHelpers export ✅

Clean addition. .cts module format is consistent with reactApis.cts. Package exports map and files array are correctly updated to include lib/**/*.d.cts. Tests cover the positive and negative cases adequately.

Minor: the test description for the second case says "matches the webpack 4 'Module not found' warning for react-dom/client" — the actual warning text format is identical to webpack 5; the only difference is the file path (src vs lib). The test still verifies the right thing (the regex matches both paths), the description is just slightly misleading. See inline comment.


RSC client manifest side-effect import ✅

The direct import 'react-on-rails-rsc/client.browser' in wrapServerComponentRenderer/client.tsx is the correct fix for the transitive-chain fragility. The two-level test strategy (source-file regex check + webpack integration test) is the right approach for a webpack-plugin-dependent invariant. The conditional it.skip when the lib output doesn't exist is appropriately commented to be visible in the test report rather than silently green.


configBuilder.ts security note ✅

The new SECURITY: comment on additionalContext is valuable — the footgun (any non-null object activates CommonJS mode with unrestricted host require) is non-obvious and could lead to sandbox escapes. Good addition.


Minor dependency items

  • fastify 5.8.3 → 5.8.5 for CVE-2026-33806: straightforward, no concerns.
  • base64 gem declared explicitly for Ruby 3.4+: correct fix, require: false is right.

Comment thread react_on_rails_pro/react_on_rails_pro.gemspec Outdated
Comment thread packages/react-on-rails/tests/webpackHelpers.test.ts Outdated
Comment thread react_on_rails_pro/lib/react_on_rails_pro/license_validator.rb
@justin808
Copy link
Copy Markdown
Member Author

Mattered

  • Addressed the Pro jwt dependency rationale in 738dd85f: react_on_rails_pro.gemspec now explains why jwt >= 2.7 is sufficient for this RS256-only validator and why the jwt 3.2.0 empty-key HMAC advisory does not apply to this code path.
  • Verified the RSC client side-effect import ordering: eslint.config.ts has import/order and import/first disabled, and pnpm run lint passed on HEAD.
  • Verified the Pro license validator regression coverage: bundle exec rspec spec/react_on_rails_pro/license_validator_spec.rb passed with 62 examples, 0 failures.

Optional

  • Updated the webpackHelpers test description in 738dd85f to avoid implying a webpack 4/5 warning-format difference.
  • Confirmed the current RSC scanner doc already includes last_js_code_char_index in the caller list and calls out stack-aware advance_js_string_state work for nested template literals.
  • Confirmed the current additionalContext security warning documents module.wrap(), unrestricted host require, Node built-ins, and disabled VM sandboxing.

Skipped

  • CodeRabbit's skipped-review/status comment and Greptile's summary were informational.

Verification

  • pnpm run lint
  • pnpm --filter react-on-rails run test -- webpackHelpers.test.ts (Jest ran the matching package suite: 17 suites, 152 tests)
  • pnpm start format.listDifferent
  • bundle exec rspec spec/react_on_rails_pro/license_validator_spec.rb
  • bundle exec rubocop --ignore-parent-exclusion from react_on_rails_pro

Scan window: full PR review history through 2026-05-24T08:48:00Z. Future full-PR scans should start after this comment unless check all reviews is requested.

@justin808 justin808 force-pushed the jg/3258-rsc-migration-parser-clarity branch from 738dd85 to 5c13228 Compare May 25, 2026 04:22
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 25, 2026

Review: refactor: clarify RSC migration parser helpers (#3258)

Overall: Approved with one minor nit. This is a clean documentation + rename PR with no behavioral changes. All four files look correct.


Rename: rsc_plugin_without_client_references?any_rsc_plugin_missing_client_references?

The rename is an improvement. The old name implied a universal check ("the plugin is without client references") when the implementation is existential ("any plugin section is missing client references"). The new name makes the quantifier explicit, and the added docstring correctly documents the non-complement relationship when multiple plugin sections exist. Both call sites in client_references.rb are updated (lines 80 and 102). No stale references remain.


Consolidated JS scanner docs on advance_js_scan_state

The new docblock is thorough and well-structured: supported constructs, unsupported constructs with concrete examples, how downstream code catches failures, and a two-item future expansion sketch. The cross-references from rsc_plugin_options_without_comments and matching_js_closing_brace pointing to the central doc are the right call — duplicated scanner-limit prose was harder to keep in sync.


add_rsc_client_references_setup comment

The expanded comment clearly justifies keeping the defensive guards: the duplicate-declaration error is named (Identifier 'rscClientReferences' has already been declared), the cost of the check is quantified (two boolean ops on the already-loaded body), and the "future second caller" motivation is explained. This is the right level of detail for a method with non-obvious guard semantics.


configBuilder.ts security comments

Upgrading NOTE: to SECURITY: and explicitly listing fs, child_process, and os as accessible built-ins is a meaningful improvement for anyone skimming the interface. One minor formatting nit posted inline.


react_on_rails_pro.gemspec jwt comment

The comment correctly justifies >= 2.7 by noting that decode_license uses only RS256, so the HMAC empty-key advisory fixed in 3.2.0 is irrelevant to this gem. That's exactly the reasoning a security auditor would need. Looks good.


Webpack helper test rename

"matches the 'Module not found' warning regardless of file path" is more accurate — the test fixture has a path that was never webpack-4-specific. Minor cleanup, no issues.

Comment thread packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 25, 2026

Code Review — PR #3343

Overview

This PR is broader than its title suggests — it combines several distinct changes:

  1. Version bump 16.7.0-rc.116.7.0-rc.2 across all gems and npm packages
  2. Release pipeline safety (rakelib/release.rake): workspace protocol rewriting before pnpm publish + post-publish npm registry verification with retry
  3. Install generator fallback (js_dependency_manager.rb): writes versioned specs to package.json as last resort when all installs fail
  4. Security policy (SECURITY.md): structured support window with CVSS thresholds and time-bound backport commitments
  5. RSC parser clarity (rsc_setup/client_references.rb): rename rsc_plugin_without_client_references?any_rsc_plugin_missing_client_references? + consolidated advance_js_scan_state docblock

Strengths

  • Release pipeline (rakelib/release.rake): The with_publishable_package_json ensure-based restore is solid — it preserves original content verbatim and correctly prioritizes the publish error over a restore error when both fail. Test coverage is thorough (workspace protocol replacement, retry behavior, error preservation).
  • npm verification (verify_npm_package_published!): The three-check sequence (existence → version match → no workspace protocol leaks) directly addresses the root cause of the broken rc.1 publish. The 6×5s retry window handles normal registry propagation delays well.
  • RSC parser rename: any_rsc_plugin_missing_client_references? is a clear improvement — the existential semantics are now unambiguous, and the docblock correctly notes the non-complement property when mixed plugin sections exist.
  • advance_js_scan_state docblock: Centralizing the scanner's limitations (regex literals, nested template literals) and future-expansion notes in one place is the right call. The "future expansion" sketch in particular is useful for the next maintainer who needs to extend the scanner.
  • SECURITY.md: The explicit CVSS thresholds (≥ 7.0 / ≥ 9.0) and time-bounded windows (6 months post-next-minor) are a substantial improvement over the previous vague "we triage" policy.

Issues

1. write_versioned_package_specs_to_package_json succeeds silently

When both primary and fallback installs fail, this method modifies package.json without producing any output. Users who run the generator will find their package.json updated with no explanation of why or what to do next (e.g., "Please run npm install to finish installing the following packages: ..."). The error path already uses GeneratorMessages.add_warning — the success path needs the equivalent so users understand what happened.

2. add_packages return-value semantics changed

Previously add_packages returned whatever install_packages_with_fallback returned (which could be true on success). Now it always returns false when the package-manager install fails, even if write_versioned_package_specs_to_package_json wrote the pins. This is the correct semantic (the install did not succeed), but callers that previously interpreted the return value as "at least something succeeded" will silently see changed behavior. Worth a mention in the commit message or a brief inline comment on the method.

3. Retry logic readability nit in fetch_npm_package_metadata_with_retries

next if attempt == attempts - 1 is correct (it skips the sleep on the last attempt, which has no next iteration), but it reads as "skip to the next iteration" rather than "skip the trailing sleep." See the inline comment for a suggested rephrasing.

4. PR scope — mixed concerns make bisecting harder

Combining a version bump, release pipeline infrastructure, install generator behavior change, security policy, and RSC refactoring in one PR makes it harder to bisect regressions and to review each change in isolation. Not blocking, but worth noting for future splits.


Verdict

The release pipeline additions are well-implemented and address a real production incident. The RSC parser changes are behavior-neutral and well-documented. The main actionable item is the missing user message in the install-fallback success path (write_versioned_package_specs_to_package_json). Everything else is polish.

Comment thread rakelib/release.rake Outdated
Comment thread rakelib/release.rake
@justin808 justin808 force-pushed the codex/fix-rsc-client-reference-scope branch from 4e2b5e1 to d74e827 Compare May 26, 2026 03:23
@justin808 justin808 force-pushed the jg/3258-rsc-migration-parser-clarity branch from 900c70a to 20886c9 Compare May 26, 2026 03:40
Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb Outdated
Comment thread react_on_rails/lib/generators/react_on_rails/rsc_setup/client_references.rb Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

Code Review: refactor: clarify RSC migration parser helpers (#3258)

Summary: Documentation/rename-only refactoring with no intended behavior changes. The overall direction is good — the rename is more precise, the consolidated scanner docs are useful, and the configBuilder.ts SECURITY improvements are clear. Two documentation issues filed as inline comments are worth addressing before merge.


Issues (see inline comments)

  1. Missing caller in advance_js_scan_state doc listlast_js_code_line_start (line 858) calls advance_js_scan_state but is absent from the exhaustive caller list at lines 453–456. A future author auditing scanner limitations would miss it.

  2. Inaccurate blanket regex-literal limitation claimjs_top_level_position? and js_code_position? both apply js_regex_literal_start? preprocessing before delegating to advance_js_scan_state, so they handle regex literals correctly already. The limitation note as written implies all listed callers are affected, which overstates the risk for those two methods.

  3. return false → bare return (minor) — functionally safe since the caller tests truthiness only (unless), but return false would match the explicit boolean convention used everywhere else in ensure_rsc_client_references_setup.


Positives

  • Rename rsc_plugin_without_client_references?any_rsc_plugin_missing_client_references? is accurate; the new doc comment correctly explains the non-complement relationship with rsc_plugin_defines_client_references?.
  • configBuilder.ts SECURITY wording is meaningfully improved: concrete built-in examples (child_process, os) and the explicit module.wrap() mechanics are more actionable than the prior note.
  • Test description rename to "regardless of file path" is more future-proof.
  • The duplicate-declaration guard comment in add_rsc_client_references_setup clearly motivates keeping the defensive checks even when the current call chain makes them redundant.

justin808 added a commit that referenced this pull request May 26, 2026
- client_references.rb: include `last_js_code_line_start` in the
  `advance_js_scan_state` caller list and scope the regex-literal /
  template-literal limitations to callers that do not run
  `js_regex_literal_start?` preprocessing, since `js_code_position?` and
  `js_top_level_position?` handle regex literals via their own pre-pass.
- client_references.rb: switch `add_rsc_client_references_setup` early
  returns to explicit `return false` to match the boolean-return
  convention used in `ensure_rsc_client_references_setup`.
- configBuilder.ts: start the second `SECURITY:` block on a new line so
  the tag is a clear visual anchor, matching the first block.
- js_dependency_manager.rb: emit a `GeneratorMessages.add_warning` from
  `write_versioned_package_specs_to_package_json` so users learn when
  the fallback wrote version pins to `package.json` and what they need
  to install manually.
- release.rake: in `with_publishable_package_json`, only flip `changed`
  to true after `File.write` succeeds so a failed write does not drive
  the ensure-block restore against an unchanged file.
- release.rake: replace `next if attempt == attempts - 1` with an
  `unless` guard around the retry puts+sleep block for readability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justin808
Copy link
Copy Markdown
Member Author

Mattered

  • Fixed the two doc accuracy gaps claude[bot] flagged in client_references.rb (9962c1696): the advance_js_scan_state caller list now includes last_js_code_line_start, and the regex-literal / template-literal limitation block is scoped to callers that do not run js_regex_literal_start? preprocessing (so js_top_level_position? and js_code_position? are correctly called out as unaffected).
  • Added a GeneratorMessages.add_warning to write_versioned_package_specs_to_package_json in js_dependency_manager.rb so users learn that the fallback wrote version pins to package.json and which packages they need to install manually. Extracted a package_json_pin_fallback_warning helper to keep cyclomatic complexity within rubocop's threshold.
  • Tightened the with_publishable_package_json ensure-block guard in release.rake: changed now flips to true only after File.write succeeds, so a failed write does not drive the ensure block to restore against an unchanged file.

Optional

  • Started the second SECURITY: block on a new line in configBuilder.ts so both SECURITY: tags read as visual anchors.
  • Restructured the retry-loop sleep in release.rake#fetch_npm_package_metadata_with_retries to unless attempt == attempts - 1 do ... for readability — no behavior change.
  • Switched the two early returns in add_rsc_client_references_setup to explicit return false to match ensure_rsc_client_references_setup's boolean-return convention.

Skipped

  • "Good rename" acknowledgment on client_references.rb:241 — replied and resolved.

Verification

  • bundle exec rubocop on client_references.rb, js_dependency_manager.rb, release.rake (3 files, 0 offenses).
  • bundle exec rspec spec/react_on_rails/generators/rsc_generator_spec.rb spec/react_on_rails/release_rake_helpers_spec.rb (216 examples, 0 failures).
  • pnpm exec eslint packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts (no offenses; the existing opentelemetry.ts parse errors on this branch are unrelated).
  • pnpm exec prettier --check packages/react-on-rails-pro-node-renderer/src/shared/configBuilder.ts (clean).
  • Pre-commit lefthook ran prettier + autofix + rubocop + eslint on the changed files and passed.

Scan window: PR review history from 2026-05-24T08:48:01Z through 2026-05-26T04:01:08Z. Future full-PR scans should start after this comment unless check all reviews is requested.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9962c16960

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rakelib/release.rake Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

Code Review - Summary: Pure refactoring/documentation pass with no behavior change to the RSC parser logic. Clean, well-reasoned PR.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

Code Review

Summary: Pure refactoring/documentation pass with no behavior change to the RSC parser logic. The changes improve naming clarity, consolidate scanner documentation, and harden two minor edge cases in the release tooling. Clean, well-reasoned PR.


RSC Migration Parser Cleanup

Rename: rsc_plugin_without_client_references? -> any_rsc_plugin_missing_client_references? is a genuine improvement. The old name implied a universal check; the new name correctly signals existential semantics. The added docblock explicitly calls out the non-complement behavior when multiple plugin sections exist (one configured, one not -- both predicates can return true simultaneously). Old name is confirmed fully removed from react_on_rails/ and react_on_rails_pro/.

Consolidated advance_js_scan_state docblock: The 45-line block is long but justified -- this function has 8 call sites, non-obvious limitations, a caller contract invariant (block_comment_exit_guard), and documented future-expansion requirements. The pointer approach at rsc_plugin_options_without_comments and matching_js_closing_brace is cleaner than duplicating the limitation prose.

add_rsc_client_references_setup comment: Correctly explains both what the duplicate guard prevents (SyntaxError at config load) and why it is kept even though the single caller already checked. Good defensive design rationale.


Release Rake Hardening

with_publishable_package_json fix: Deferring changed = true until after a successful File.write is a real correctness improvement. In the original code, if File.write raised, changed was already true, causing the ensure block to attempt a redundant restore of an unchanged file. The new ordering avoids that. See inline note for a minor edge-case caveat.

fetch_npm_package_metadata_with_retries restructure: Functionally identical to the prior next if attempt == attempts - 1 guard. The unless block is a valid style choice, though Ruby conventionally favors the one-liner next if form for early-exit guards. Not a blocking issue.


JS Dependency Manager

Warning placement: Moving add_warning after File.write (and before true) is correct -- the user-facing message now only fires when the write actually succeeded. The extracted package_json_pin_fallback_warning helper is clean and independently testable.

Minor style note: other warnings in this file use heredocs. The new helper uses string concatenation. Both are fine for a single-sentence message.


Node Renderer Security Comments

Upgrading NOTE: to SECURITY: and naming specific built-ins (fs, child_process, os) is strictly better than the prior text. The two separate SECURITY: markers for additionalContext and supportModules correctly call out that either option independently enables CommonJS mode -- a reader scanning only one of the two options will still see the warning.


Test Coverage

The PR runs the 137-example RSC generator spec with 0 failures. No spec changes are needed since there is no behavior change. The test description fix in webpackHelpers.test.ts accurately reflects what the fixture tests (path-agnostic pattern matching, not webpack 4 specifically).


Verdict: Approve with one minor inline observation. The rename, documentation consolidation, and release-rake hardening are all sound. No blocking issues.

Comment thread rakelib/release.rake
@justin808
Copy link
Copy Markdown
Member Author

Mattered

  • Documented the partial-write trade-off on rakelib/release.rake:683 in 918acd37f so a future reader doesn't flip the changed = true ordering back. This addresses both the codex-connector concern about restoring a partially-written package.json and the claude[bot] suggestion to note the trade-off inline. Both review threads resolved.

Considered, kept as-is

  • js_dependency_manager.rb#package_json_pin_fallback_warning (heredoc vs string concatenation): The helper builds a single-sentence warning that needs string interpolation in the middle (pinned_list); the two-line concatenation reads cleanly without the visual overhead of a heredoc + interpolation. Reviewer explicitly noted "Both are fine."
  • fetch_npm_package_metadata_with_retries unless block vs next if attempt == attempts - 1: kept the unless form because it scopes both the "retrying" message and the sleep under a single guard — the next if one-liner would either need the message duplicated outside the guard or hidden behind a separate conditional. Reviewer flagged this as "Not a blocking issue."

Acknowledged

  • The praise on the any_rsc_plugin_missing_client_references? docblock — making the non-complement trap explicit was the goal of that comment.

CI note: the OpenTelemetry build failures on this branch trace to the stale base (codex/fix-rsc-client-reference-scope) missing the hotfix from PR #3420 that already landed on main. Will resolve once #3219 merges (it's approved with green CI) and this PR rebases onto main.

@justin808 justin808 changed the title refactor: clarify RSC migration parser helpers (#3258) refactor: clarify RSC parser helpers and harden release tooling (#3258) May 26, 2026
justin808 added a commit that referenced this pull request May 26, 2026
…elper

Expand the comment on `changed = true` to spell out the trade-off the
current ordering accepts: if `File.write` partially writes before
raising, the `ensure` block will not restore the original content. This
is rare on local filesystems for small JSON files (effectively atomic
single-buffer write) and acceptable for a release-time helper, but
documenting it prevents a future reader from flipping the ordering back
without understanding the implication.

Addresses review feedback on PR #3343.
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

Code Review: refactor: clarify RSC parser helpers and harden release tooling (#3258)

Overall: This is a low-risk, well-scoped cleanup PR. The rename, documentation consolidation on advance_js_scan_state, and release-tooling hardening are all clean. Three things worth addressing before merge:


1. configBuilder.ts — SECURITY anchor for supportModules is unreachable from the field's own comment block

The PR description says "each [option] gets its own anchor — a reader scanning only one will still see the warning," but both SECURITY: blocks currently live inside the additionalContext comment (lines 58–66). A developer who reads through the supportModules field docs (lines 45–53) and stops at supportModules: boolean; will never see the security annotation.

At minimum a short pointer in the supportModules comment block would fix this:

// SECURITY: Setting this to true wraps the bundle via module.wrap() and injects the host
// require — see the security note on `additionalContext` for the full trust-boundary details.
supportModules: boolean;

The detailed explanation can stay under additionalContext; this just ensures the anchor is visible at the field that independently triggers CommonJS mode.


2. js_dependency_manager.rb — warning was previously absent (not "moved"), and the extracted helper has no test

The PR body says "Move GeneratorMessages.add_warning(...) to fire only after File.write succeeds," but the pre-PR code had no add_warning call in write_versioned_package_specs_to_package_json at all — the fallback path was previously silent. This is a net new improvement (good!), but the description is slightly misleading.

The body also says package_json_pin_fallback_warning is extracted "so the message is independently testable," but no test is added. Since the PR itself flags testability as a motivation, even a single spec asserting the name@version, name@version format would fulfill that promise and guard against regressions.


3. release.rake — acknowledged partial-write gap; atomic write pattern available at low cost

The new comment correctly documents the trade-off: a partial File.write before raising means ensure won't restore the original. For release tooling a safer pattern — write to a Tempfile, then FileUtils.mv — gives true atomicity for effectively zero extra code. Not a blocker, but worth considering given this runs during an actual gem release.


Minor positives

  • The rename rsc_plugin_without_client_references?any_rsc_plugin_missing_client_references? is complete; zero stale references remain.
  • The consolidated documentation on advance_js_scan_state is excellent — supported surface, failure modes, and future-expansion sketch are exactly what a future maintainer needs.
  • The unless attempt == attempts - 1 refactor is semantically equivalent and more readable.
  • The webpack helper test description fix is correct.

// `supportModules: false`. When `supportModules: true`, the renderer wraps the bundle and
// injects the host `require` regardless of `additionalContext`.
// `supportModules: false`.
// SECURITY: When `supportModules: true`, the renderer also wraps the bundle and injects the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both SECURITY: blocks currently live inside the additionalContext comment section. A reader who reads only the supportModules field docs (lines 45–52) and stops at supportModules: boolean; will not see this anchor.

Consider adding a brief pointer directly before supportModules: boolean;:

Suggested change
// SECURITY: When `supportModules: true`, the renderer also wraps the bundle and injects the
// SECURITY: When `supportModules: true`, the renderer also wraps the bundle and injects the
// host `require` regardless of `additionalContext`.

…and place a short forward-reference in the supportModules comment block pointing to the detailed note on additionalContext. That way both entry points surface the warning independently.

pinned_list = versioned_packages.map { |name, version| "#{name}@#{version}" }.join(", ")
"⚠️ Package manager install failed. Wrote the following version pins to package.json " \
"so you can rerun your package manager manually: #{pinned_list}"
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description explicitly calls out that package_json_pin_fallback_warning is extracted to be "independently testable," but no spec is added for it. The format "#{name}@#{version}" joined by ", " is a user-visible contract — worth a single unit test asserting the output string so a future refactor can't silently break the message.

# Example spec skeleton:
describe "#package_json_pin_fallback_warning" do
  it "formats pinned packages as name@version list" do
    result = subject.send(:package_json_pin_fallback_warning, [["react", "18.0.0"], ["react-dom", "18.0.0"]])
    expect(result).to include("react@18.0.0, react-dom@18.0.0")
  end
end

Comment thread rakelib/release.rake
# restore the original content; we accept this as a known limitation of the single-buffer
# write approach, since this is a release-time helper running on local disk where
# `File.write` is effectively atomic for small JSON files.
changed = true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment correctly documents the trade-off. For a release helper that runs once locally against a real package.json, a proper atomic write is low-cost and eliminates the partial-write scenario entirely:

require "tempfile"

tmpfile = Tempfile.new("package_json", File.dirname(package_json_path))
tmpfile.write("#{JSON.pretty_generate(package_json)}\n")
tmpfile.close
FileUtils.mv(tmpfile.path, package_json_path)
changed = true

File.rename (which FileUtils.mv uses on the same filesystem) is an atomic kernel operation — the old file is either replaced fully or not at all. This removes the need for the trade-off comment entirely. Happy to leave it as-is if the current behaviour is intentional, but wanted to flag the pattern.

Base automatically changed from codex/fix-rsc-client-reference-scope to main May 27, 2026 00:42
justin808 and others added 6 commits May 26, 2026 15:54
Follow-up to PR #3219 cloud review. Internal cleanup, no behavior change.

- Rename `rsc_plugin_without_client_references?` to
  `any_rsc_plugin_missing_client_references?` and add a docstring spelling
  out the any-section existential semantics — the prior name read as
  universal but the implementation is existential.
- Consolidate the lightweight JS scanner's supported-surface notes onto
  `advance_js_scan_state` (the central dispatcher): which lexical
  constructs are tracked, which fall outside (regex literals, nested
  template literals), how downstream `rsc_plugin_option_sections_partition`
  detects the unsafe cases and warns, and what real-world expansion would
  look like. Replace the scattered shorter notes at
  `rsc_plugin_options_without_comments` and `matching_js_closing_brace`
  with pointers to the consolidated doc.
- Document the defensive guards in `add_rsc_client_references_setup`:
  what bad outcome they prevent (a duplicate `const rscClientReferences`
  declaration → `Identifier already declared` SyntaxError at config load)
  and why two boolean checks are worth keeping in case a future caller
  bypasses `ensure_rsc_client_references_setup`.

Fixes #3258

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- client_references.rb: include `last_js_code_line_start` in the
  `advance_js_scan_state` caller list and scope the regex-literal /
  template-literal limitations to callers that do not run
  `js_regex_literal_start?` preprocessing, since `js_code_position?` and
  `js_top_level_position?` handle regex literals via their own pre-pass.
- client_references.rb: switch `add_rsc_client_references_setup` early
  returns to explicit `return false` to match the boolean-return
  convention used in `ensure_rsc_client_references_setup`.
- configBuilder.ts: start the second `SECURITY:` block on a new line so
  the tag is a clear visual anchor, matching the first block.
- js_dependency_manager.rb: emit a `GeneratorMessages.add_warning` from
  `write_versioned_package_specs_to_package_json` so users learn when
  the fallback wrote version pins to `package.json` and what they need
  to install manually.
- release.rake: in `with_publishable_package_json`, only flip `changed`
  to true after `File.write` succeeds so a failed write does not drive
  the ensure-block restore against an unchanged file.
- release.rake: replace `next if attempt == attempts - 1` with an
  `unless` guard around the retry puts+sleep block for readability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…elper

Expand the comment on `changed = true` to spell out the trade-off the
current ordering accepts: if `File.write` partially writes before
raising, the `ensure` block will not restore the original content. This
is rare on local filesystems for small JSON files (effectively atomic
single-buffer write) and acceptable for a release-time helper, but
documenting it prevents a future reader from flipping the ordering back
without understanding the implication.

Addresses review feedback on PR #3343.
@justin808 justin808 changed the title refactor: clarify RSC parser helpers and harden release tooling (#3258) refactor: clarify RSC parser helpers and release safeguards (#3258) May 27, 2026
@justin808 justin808 force-pushed the jg/3258-rsc-migration-parser-clarity branch from 918acd3 to 06dc380 Compare May 27, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow up RSC migration parser helper clarity

1 participant