react-on-rails-pro-node-renderer 16.7.0-rc.3 → 17.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,7 +53,7 @@ reactOnRailsProNodeRenderer({
53
53
  ReactOnRailsPro.configure do |config|
54
54
  config.server_renderer = "NodeRenderer"
55
55
  config.renderer_url = ENV.fetch("REACT_RENDERER_URL", "http://localhost:3800")
56
- config.renderer_password = ENV.fetch("RENDERER_PASSWORD", "devPassword")
56
+ config.renderer_password = ENV["RENDERER_PASSWORD"]
57
57
  end
58
58
  ```
59
59
 
@@ -24,6 +24,8 @@
24
24
  */
25
25
  export { default as log } from '../shared/log.js';
26
26
  export { addErrorNotifier, addMessageNotifier, addNotifier, error, message, Notifier, ErrorNotifier, MessageNotifier, } from '../shared/errorReporter.js';
27
- export { setupTracing, setupSubSpan, subSpan, TracingContext, TracingIntegrationOptions, UnitOfWorkOptions, SubSpanOptions, SubSpanFn, SubSpanController, } from '../shared/tracing.js';
28
- export { configureFastify, FastifyConfigFunction } from '../worker/fastifyConfig.js';
27
+ export { resetTracing, resetSubSpan, setupTracing, setupSubSpan, subSpan, TracingContext, TracingIntegrationOptions, UnitOfWorkOptions, SubSpanOptions, SubSpanFn, SubSpanController, } from '../shared/tracing.js';
28
+ export { getOpenTelemetryTracerProvider, setOpenTelemetryTracerProvider, } from '../shared/opentelemetryState.js';
29
+ export { configureFastify, registerFastifyConfigFunction, FastifyConfigFunction, } from '../worker/fastifyConfig.js';
30
+ export { registerWorkerShutdownHook, WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS, WorkerShutdownHook, } from '../worker/shutdownHooks.js';
29
31
  //# sourceMappingURL=api.d.ts.map
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  return (mod && mod.__esModule) ? mod : { "default": mod };
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.configureFastify = exports.subSpan = exports.setupSubSpan = exports.setupTracing = exports.message = exports.error = exports.addNotifier = exports.addMessageNotifier = exports.addErrorNotifier = exports.log = void 0;
30
+ exports.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS = exports.registerWorkerShutdownHook = exports.registerFastifyConfigFunction = exports.configureFastify = exports.setOpenTelemetryTracerProvider = exports.getOpenTelemetryTracerProvider = exports.subSpan = exports.setupSubSpan = exports.setupTracing = exports.resetSubSpan = exports.resetTracing = exports.message = exports.error = exports.addNotifier = exports.addMessageNotifier = exports.addErrorNotifier = exports.log = void 0;
31
31
  var log_js_1 = require("../shared/log.js");
32
32
  Object.defineProperty(exports, "log", { enumerable: true, get: function () { return __importDefault(log_js_1).default; } });
33
33
  var errorReporter_js_1 = require("../shared/errorReporter.js");
@@ -37,9 +37,18 @@ Object.defineProperty(exports, "addNotifier", { enumerable: true, get: function
37
37
  Object.defineProperty(exports, "error", { enumerable: true, get: function () { return errorReporter_js_1.error; } });
38
38
  Object.defineProperty(exports, "message", { enumerable: true, get: function () { return errorReporter_js_1.message; } });
39
39
  var tracing_js_1 = require("../shared/tracing.js");
40
+ Object.defineProperty(exports, "resetTracing", { enumerable: true, get: function () { return tracing_js_1.resetTracing; } });
41
+ Object.defineProperty(exports, "resetSubSpan", { enumerable: true, get: function () { return tracing_js_1.resetSubSpan; } });
40
42
  Object.defineProperty(exports, "setupTracing", { enumerable: true, get: function () { return tracing_js_1.setupTracing; } });
41
43
  Object.defineProperty(exports, "setupSubSpan", { enumerable: true, get: function () { return tracing_js_1.setupSubSpan; } });
42
44
  Object.defineProperty(exports, "subSpan", { enumerable: true, get: function () { return tracing_js_1.subSpan; } });
45
+ var opentelemetryState_js_1 = require("../shared/opentelemetryState.js");
46
+ Object.defineProperty(exports, "getOpenTelemetryTracerProvider", { enumerable: true, get: function () { return opentelemetryState_js_1.getOpenTelemetryTracerProvider; } });
47
+ Object.defineProperty(exports, "setOpenTelemetryTracerProvider", { enumerable: true, get: function () { return opentelemetryState_js_1.setOpenTelemetryTracerProvider; } });
43
48
  var fastifyConfig_js_1 = require("../worker/fastifyConfig.js");
44
49
  Object.defineProperty(exports, "configureFastify", { enumerable: true, get: function () { return fastifyConfig_js_1.configureFastify; } });
50
+ Object.defineProperty(exports, "registerFastifyConfigFunction", { enumerable: true, get: function () { return fastifyConfig_js_1.registerFastifyConfigFunction; } });
51
+ var shutdownHooks_js_1 = require("../worker/shutdownHooks.js");
52
+ Object.defineProperty(exports, "registerWorkerShutdownHook", { enumerable: true, get: function () { return shutdownHooks_js_1.registerWorkerShutdownHook; } });
53
+ Object.defineProperty(exports, "WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS", { enumerable: true, get: function () { return shutdownHooks_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS; } });
45
54
  //# sourceMappingURL=api.js.map
@@ -1,22 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.init = init;
4
- /* eslint-disable no-restricted-imports --
5
- * This integration needs internal worker/shared modules that the public
6
- * api.ts does not yet re-export (tracing adapter slots, OTel global state,
7
- * fastify config + worker shutdown hook registration). Tracked in #3419
8
- * — once api.ts surfaces these, remove this disable. */
9
- const tracing_js_1 = require("../shared/tracing.js");
10
- const opentelemetryState_js_1 = require("../shared/opentelemetryState.js");
11
- const fastifyConfig_js_1 = require("../worker/fastifyConfig.js");
12
- const shutdownHooks_js_1 = require("../worker/shutdownHooks.js");
13
- /* eslint-enable no-restricted-imports */
14
4
  const api_js_1 = require("./api.js");
15
5
  const DEFAULT_SERVICE_NAME = 'react-on-rails-pro-node-renderer';
16
6
  const DEFAULT_SHUTDOWN_TIMEOUT_MS = 5000;
17
7
  // Leave 1s of headroom under the worker's hard cap so the shutdown hook can
18
8
  // resolve cleanly even when provider.shutdown() runs right at its limit.
19
- const MAX_SHUTDOWN_TIMEOUT_MS = shutdownHooks_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS - 1000;
9
+ const MAX_SHUTDOWN_TIMEOUT_MS = api_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS - 1000;
20
10
  function isProduction() {
21
11
  return process.env.NODE_ENV === 'production' || process.env.RAILS_ENV === 'production';
22
12
  }
@@ -32,7 +22,7 @@ function resolveShutdownTimeoutMs(opts) {
32
22
  return DEFAULT_SHUTDOWN_TIMEOUT_MS;
33
23
  }
34
24
  if (requested > MAX_SHUTDOWN_TIMEOUT_MS) {
35
- api_js_1.log.warn('[OpenTelemetry] shutdownTimeoutMs=%dms exceeds worker shutdown hook cap (%dms); capping to %dms so the hook can resolve before the worker is forcibly destroyed.', requested, shutdownHooks_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS, MAX_SHUTDOWN_TIMEOUT_MS);
25
+ api_js_1.log.warn('[OpenTelemetry] shutdownTimeoutMs=%dms exceeds worker shutdown hook cap (%dms); capping to %dms so the hook can resolve before the worker is forcibly destroyed.', requested, api_js_1.WORKER_SHUTDOWN_HOOKS_TIMEOUT_MS, MAX_SHUTDOWN_TIMEOUT_MS);
36
26
  return MAX_SHUTDOWN_TIMEOUT_MS;
37
27
  }
38
28
  return requested;
@@ -78,10 +68,10 @@ function disableOpenTelemetryGlobals(otelApi) {
78
68
  }
79
69
  function resetInstalledTracingAdapters(installedAdapters) {
80
70
  if (installedAdapters.subSpan) {
81
- (0, tracing_js_1.resetSubSpan)();
71
+ (0, api_js_1.resetSubSpan)();
82
72
  }
83
73
  if (installedAdapters.tracing) {
84
- (0, tracing_js_1.resetTracing)();
74
+ (0, api_js_1.resetTracing)();
85
75
  }
86
76
  return { tracing: false, subSpan: false };
87
77
  }
@@ -115,7 +105,7 @@ async function shutdownProviderWithTimeout(provider, shutdownTimeoutMs) {
115
105
  }
116
106
  }
117
107
  function init(opts = {}) {
118
- if ((0, opentelemetryState_js_1.getOpenTelemetryTracerProvider)()) {
108
+ if ((0, api_js_1.getOpenTelemetryTracerProvider)()) {
119
109
  (0, api_js_1.message)('[OpenTelemetry] init() called more than once; ignoring duplicate call.');
120
110
  return;
121
111
  }
@@ -179,7 +169,7 @@ function init(opts = {}) {
179
169
  // reference) correctly disables the globals if register() throws.
180
170
  ownsOpenTelemetryGlobals = true;
181
171
  registeredProvider = provider;
182
- (0, opentelemetryState_js_1.setOpenTelemetryTracerProvider)(provider);
172
+ (0, api_js_1.setOpenTelemetryTracerProvider)(provider);
183
173
  // Re-call provider.register() to set context manager + propagator globals.
184
174
  // The second setGlobalTracerProvider() call inside register() is a no-op
185
175
  // (registerGlobal returns false because the proxy is already owned by us),
@@ -205,7 +195,7 @@ function init(opts = {}) {
205
195
  }
206
196
  if (opts.tracing) {
207
197
  const tracer = loadedOtelApi.trace.getTracer(serviceName);
208
- installedAdapters.tracing = (0, tracing_js_1.setupTracing)({
198
+ installedAdapters.tracing = (0, api_js_1.setupTracing)({
209
199
  startSsrRequestOptions: () => ({
210
200
  // Keep the root span free of request payload data. Future safe
211
201
  // attributes should be derived from structured metadata supplied by
@@ -252,7 +242,7 @@ function init(opts = {}) {
252
242
  span.end();
253
243
  }
254
244
  });
255
- installedAdapters.subSpan = (0, tracing_js_1.setupSubSpan)(subSpanImpl);
245
+ installedAdapters.subSpan = (0, api_js_1.setupSubSpan)(subSpanImpl);
256
246
  }
257
247
  else {
258
248
  (0, api_js_1.message)('[OpenTelemetry] tracing integration was not installed because another tracing integration is ' +
@@ -264,8 +254,8 @@ function init(opts = {}) {
264
254
  shutdownOpenTelemetryPromise ?? (shutdownOpenTelemetryPromise = (async () => {
265
255
  try {
266
256
  await shutdownProviderWithTimeout(provider, shutdownTimeoutMs);
267
- if ((0, opentelemetryState_js_1.getOpenTelemetryTracerProvider)() === provider) {
268
- (0, opentelemetryState_js_1.setOpenTelemetryTracerProvider)(null);
257
+ if ((0, api_js_1.getOpenTelemetryTracerProvider)() === provider) {
258
+ (0, api_js_1.setOpenTelemetryTracerProvider)(null);
269
259
  disableOpenTelemetryGlobals(loadedOtelApi);
270
260
  ownsOpenTelemetryGlobals = false;
271
261
  installedAdapters = resetInstalledTracingAdapters(installedAdapters);
@@ -281,8 +271,8 @@ function init(opts = {}) {
281
271
  // Register these last so failed init paths do not leave partial shutdown hooks
282
272
  // behind. The worker hook runs during cluster restarts, while Fastify onClose
283
273
  // still handles explicit app.close() calls from tests or custom integrations.
284
- unregisterWorkerShutdownHook = (0, shutdownHooks_js_1.registerWorkerShutdownHook)(shutdownOpenTelemetry);
285
- unregisterFastifyConfig = (0, fastifyConfig_js_1.registerFastifyConfigFunction)((app) => {
274
+ unregisterWorkerShutdownHook = (0, api_js_1.registerWorkerShutdownHook)(shutdownOpenTelemetry);
275
+ unregisterFastifyConfig = (0, api_js_1.registerFastifyConfigFunction)((app) => {
286
276
  app.addHook('onClose', shutdownOpenTelemetry);
287
277
  });
288
278
  api_js_1.log.info('[OpenTelemetry] Tracer provider initialized');
@@ -293,8 +283,8 @@ function init(opts = {}) {
293
283
  if (ownsOpenTelemetryGlobals &&
294
284
  registeredProvider &&
295
285
  otelApi &&
296
- (0, opentelemetryState_js_1.getOpenTelemetryTracerProvider)() === registeredProvider) {
297
- (0, opentelemetryState_js_1.setOpenTelemetryTracerProvider)(null);
286
+ (0, api_js_1.getOpenTelemetryTracerProvider)() === registeredProvider) {
287
+ (0, api_js_1.setOpenTelemetryTracerProvider)(null);
298
288
  disableOpenTelemetryGlobals(otelApi);
299
289
  ownsOpenTelemetryGlobals = false;
300
290
  }
@@ -181,32 +181,41 @@ function logSanitizedConfig() {
181
181
  'Final renderer settings': sanitizedSettings(config, '<NOT PROVIDED>'),
182
182
  });
183
183
  }
184
+ const KNOWN_WEAK_PASSWORDS = new Set(['devPassword', 'myPassword1', 'password', 'changeme', 'admin', 'secret', 'test', 'renderer'].map((p) => p.toLowerCase()));
185
+ const MIN_PASSWORD_LENGTH = 16;
184
186
  function validatePasswordForProduction(aConfig) {
185
- // Only a truthy password satisfies the production-like requirement. Null, undefined, and empty strings are
186
- // all treated as missing passwords.
187
- if (aConfig.password)
188
- return null;
189
- // Require all present runtime envs to be development/test; fail closed otherwise.
190
- // If either env indicates a production-like value, or neither env is set, password is required.
191
- // This preserves a fail-closed invariant across the renderer startup path and the Ruby-side checks.
192
- const allowMissingPassword = runtimeEnvsAllowDevelopmentDefaults();
193
- if (allowMissingPassword)
187
+ const isProductionLike = !runtimeEnvsAllowDevelopmentDefaults();
188
+ if (!aConfig.password || aConfig.password.trim() === '') {
189
+ if (isProductionLike) {
190
+ return ('RENDERER_PASSWORD must be set in production-like environments ' +
191
+ `(NODE_ENV: "${env.NODE_ENV ?? '(not set)'}", RAILS_ENV: "${env.RAILS_ENV ?? '(not set)'}").` +
192
+ '\n\n' +
193
+ 'In development and test environments, the renderer password is optional and no authentication\n' +
194
+ 'is required. In all other environments, you must explicitly configure a password to secure\n' +
195
+ 'communication between Rails and the Node Renderer.\n\n' +
196
+ 'To fix this, set the RENDERER_PASSWORD environment variable:\n\n' +
197
+ ' export RENDERER_PASSWORD="your-secure-password"\n\n' +
198
+ 'Or pass it in the config object:\n\n' +
199
+ ' reactOnRailsProNodeRenderer({ password: process.env.RENDERER_PASSWORD });\n\n' +
200
+ 'Environment matrix:\n' +
201
+ ' development — password optional (no authentication)\n' +
202
+ ' test — password optional (no authentication)\n' +
203
+ ' (neither set) — treated as production-like; RENDERER_PASSWORD required\n' +
204
+ ' all other environments (staging, production, qa, preview, etc.) — RENDERER_PASSWORD required');
205
+ }
194
206
  return null;
195
- return ('RENDERER_PASSWORD must be set in production-like environments ' +
196
- `(NODE_ENV: "${env.NODE_ENV ?? '(not set)'}", RAILS_ENV: "${env.RAILS_ENV ?? '(not set)'}").` +
197
- '\n\n' +
198
- 'In development and test environments, the renderer password is optional and no authentication\n' +
199
- 'is required. In all other environments, you must explicitly configure a password to secure\n' +
200
- 'communication between Rails and the Node Renderer.\n\n' +
201
- 'To fix this, set the RENDERER_PASSWORD environment variable:\n\n' +
202
- ' export RENDERER_PASSWORD="your-secure-password"\n\n' +
203
- 'Or pass it in the config object:\n\n' +
204
- ' reactOnRailsProNodeRenderer({ password: process.env.RENDERER_PASSWORD });\n\n' +
205
- 'Environment matrix:\n' +
206
- ' development — password optional (no authentication)\n' +
207
- ' test — password optional (no authentication)\n' +
208
- ' (neither set) — treated as production-like; RENDERER_PASSWORD required\n' +
209
- ' all other environments (staging, production, qa, preview, etc.) — RENDERER_PASSWORD required');
207
+ }
208
+ if (KNOWN_WEAK_PASSWORDS.has(aConfig.password.toLowerCase())) {
209
+ // Don't log the literal value — even a known-default value is the user's
210
+ // *current* live credential until they rotate it.
211
+ log_js_1.default.warn('RENDERER_PASSWORD matches a known-default value. ' +
212
+ `Set RENDERER_PASSWORD to a random value of at least ${MIN_PASSWORD_LENGTH} characters.`);
213
+ }
214
+ else if (aConfig.password.length < MIN_PASSWORD_LENGTH) {
215
+ log_js_1.default.warn(`RENDERER_PASSWORD is shorter than ${MIN_PASSWORD_LENGTH} characters (current length: ${aConfig.password.length}). ` +
216
+ 'Consider using a stronger password.');
217
+ }
218
+ return null;
210
219
  }
211
220
  /**
212
221
  * Lazily create the config.
@@ -1,4 +1,11 @@
1
1
  import type { NodeTracerProvider as NodeTracerProviderType } from '@opentelemetry/sdk-trace-node';
2
2
  export declare function getOpenTelemetryTracerProvider(): NodeTracerProviderType | null;
3
+ /**
4
+ * Updates the process-global OpenTelemetry provider reference.
5
+ *
6
+ * Caller contract: only integrations that own the OpenTelemetry init/shutdown
7
+ * lifecycle should call this, and the value must mirror that lifecycle's
8
+ * current provider ownership.
9
+ */
3
10
  export declare function setOpenTelemetryTracerProvider(provider: NodeTracerProviderType | null): void;
4
11
  //# sourceMappingURL=opentelemetryState.d.ts.map
@@ -6,6 +6,13 @@ let tracerProvider = null;
6
6
  function getOpenTelemetryTracerProvider() {
7
7
  return tracerProvider;
8
8
  }
9
+ /**
10
+ * Updates the process-global OpenTelemetry provider reference.
11
+ *
12
+ * Caller contract: only integrations that own the OpenTelemetry init/shutdown
13
+ * lifecycle should call this, and the value must mirror that lifecycle's
14
+ * current provider ownership.
15
+ */
9
16
  function setOpenTelemetryTracerProvider(provider) {
10
17
  tracerProvider = provider;
11
18
  }
@@ -0,0 +1,3 @@
1
+ export declare const SENSITIVE_REQUEST_BODY_KEYS: Set<string>;
2
+ export declare function sanitizeBodyKeys(body: object): string[];
3
+ //# sourceMappingURL=sensitiveKeys.d.ts.map
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SENSITIVE_REQUEST_BODY_KEYS = void 0;
4
+ exports.sanitizeBodyKeys = sanitizeBodyKeys;
5
+ exports.SENSITIVE_REQUEST_BODY_KEYS = new Set([
6
+ 'password',
7
+ 'token',
8
+ 'secret',
9
+ 'api_key',
10
+ 'api-key',
11
+ 'apikey',
12
+ 'authorization',
13
+ 'auth_token',
14
+ 'auth-token',
15
+ 'authtoken',
16
+ 'access_token',
17
+ 'accesstoken',
18
+ 'bearer',
19
+ 'credentials',
20
+ ]);
21
+ function sanitizeBodyKeys(body) {
22
+ return Object.keys(body).filter((key) => !exports.SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
23
+ }
24
+ //# sourceMappingURL=sensitiveKeys.js.map
@@ -52,7 +52,10 @@ export declare function setupTracing(options: TracingIntegrationOptions): boolea
52
52
  export declare function trace<T>(fn: UnitOfWork<T>, unitOfWorkOptions: UnitOfWorkOptions): Promise<T>;
53
53
  /**
54
54
  * Resets the installed tracing executor + startSsrRequestOptions back to
55
- * defaults. Internal integrations use this during lifecycle teardown.
55
+ * defaults. Integrations use this during lifecycle teardown or failed initialization cleanup.
56
+ *
57
+ * Caller contract: only integrations that own the active tracing lifecycle
58
+ * should call this, and only while tearing that lifecycle down.
56
59
  */
57
60
  export declare function resetTracing(): void;
58
61
  /**
@@ -119,7 +122,10 @@ export declare function setupSubSpan(impl: SubSpanFn): boolean;
119
122
  export declare function subSpan<T>(opts: SubSpanOptions, fn: (controller: SubSpanController) => Promise<T>): Promise<T>;
120
123
  /**
121
124
  * Resets the installed sub-span implementation back to the default pass-through.
122
- * Internal integrations use this during lifecycle teardown.
125
+ * Integrations use this during lifecycle teardown or failed initialization cleanup.
126
+ *
127
+ * Caller contract: only integrations that own the active sub-span lifecycle
128
+ * should call this, and only while tearing that lifecycle down.
123
129
  */
124
130
  export declare function resetSubSpan(): void;
125
131
  /**
@@ -50,7 +50,10 @@ function trace(fn, unitOfWorkOptions) {
50
50
  }
51
51
  /**
52
52
  * Resets the installed tracing executor + startSsrRequestOptions back to
53
- * defaults. Internal integrations use this during lifecycle teardown.
53
+ * defaults. Integrations use this during lifecycle teardown or failed initialization cleanup.
54
+ *
55
+ * Caller contract: only integrations that own the active tracing lifecycle
56
+ * should call this, and only while tearing that lifecycle down.
54
57
  */
55
58
  function resetTracing() {
56
59
  executor = (fn) => fn();
@@ -129,7 +132,10 @@ function subSpan(opts, fn) {
129
132
  }
130
133
  /**
131
134
  * Resets the installed sub-span implementation back to the default pass-through.
132
- * Internal integrations use this during lifecycle teardown.
135
+ * Integrations use this during lifecycle teardown or failed initialization cleanup.
136
+ *
137
+ * Caller contract: only integrations that own the active sub-span lifecycle
138
+ * should call this, and only while tearing that lifecycle down.
133
139
  */
134
140
  function resetSubSpan() {
135
141
  subSpanImpl = defaultSubSpan;
@@ -10,6 +10,7 @@ exports.checkProtocolVersion = checkProtocolVersion;
10
10
  */
11
11
  const packageJson_js_1 = __importDefault(require("../shared/packageJson.js"));
12
12
  const log_js_1 = __importDefault(require("../shared/log.js"));
13
+ const sensitiveKeys_js_1 = require("../shared/sensitiveKeys.js");
13
14
  const NODE_ENV = process.env.NODE_ENV || 'production';
14
15
  // Cache to store version comparison results to avoid repeated normalization and logging
15
16
  // Key: gemVersion string, Value: boolean (true if matches, false if mismatch)
@@ -43,7 +44,7 @@ function checkProtocolVersion(body) {
43
44
  status: 412,
44
45
  data: `Unsupported renderer protocol version ${reqProtocolVersion
45
46
  ? `request protocol ${reqProtocolVersion}`
46
- : `MISSING with body ${JSON.stringify(body)}`} does not match installed renderer protocol ${packageJson_js_1.default.protocolVersion} for version ${packageJson_js_1.default.version}.
47
+ : `MISSING (received fields: ${(0, sensitiveKeys_js_1.sanitizeBodyKeys)(body).join(', ') || '(none)'})`} does not match installed renderer protocol ${packageJson_js_1.default.protocolVersion} for version ${packageJson_js_1.default.version}.
47
48
  Update either the renderer or the Rails server`,
48
49
  };
49
50
  }
package/lib/worker.js CHANGED
@@ -57,6 +57,7 @@ const requestPrechecks_js_1 = require("./worker/requestPrechecks.js");
57
57
  const authHandler_js_1 = require("./worker/authHandler.js");
58
58
  const handleRenderRequest_js_1 = require("./worker/handleRenderRequest.js");
59
59
  const handleGracefulShutdown_js_1 = __importDefault(require("./worker/handleGracefulShutdown.js"));
60
+ const sensitiveKeys_js_1 = require("./shared/sensitiveKeys.js");
60
61
  const startupErrorHandler_js_1 = require("./worker/startupErrorHandler.js");
61
62
  const handleIncrementalRenderRequest_js_1 = require("./worker/handleIncrementalRenderRequest.js");
62
63
  const handleIncrementalRenderStream_js_1 = require("./worker/handleIncrementalRenderStream.js");
@@ -136,22 +137,6 @@ const errorCode = (error) => {
136
137
  return typeof code === 'string' ? code : undefined;
137
138
  };
138
139
  const isValidRenderingRequest = (value) => typeof value === 'string' && value.length > 0;
139
- const SENSITIVE_REQUEST_BODY_KEYS = new Set([
140
- 'password',
141
- 'token',
142
- 'secret',
143
- 'api_key',
144
- 'api-key',
145
- 'apikey',
146
- 'authorization',
147
- 'auth_token',
148
- 'auth-token',
149
- 'authtoken',
150
- 'access_token',
151
- 'accesstoken',
152
- 'bearer',
153
- 'credentials',
154
- ]);
155
140
  const invalidRenderingRequestMessage = (body) => {
156
141
  const { renderingRequest } = body;
157
142
  let renderingRequestType = typeof renderingRequest;
@@ -164,7 +149,7 @@ const invalidRenderingRequestMessage = (body) => {
164
149
  else if (renderingRequest === '') {
165
150
  renderingRequestType = 'empty string';
166
151
  }
167
- const bodyKeys = Object.keys(body).filter((key) => key !== 'renderingRequest' && !SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
152
+ const bodyKeys = Object.keys(body).filter((key) => key !== 'renderingRequest' && !sensitiveKeys_js_1.SENSITIVE_REQUEST_BODY_KEYS.has(key.toLowerCase()));
168
153
  return [
169
154
  'Invalid "renderingRequest" field in render request.',
170
155
  'Expected a non-empty string of JavaScript to execute in the SSR VM.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-on-rails-pro-node-renderer",
3
- "version": "16.7.0-rc.3",
3
+ "version": "17.0.0-rc.0",
4
4
  "protocolVersion": "2.0.0",
5
5
  "description": "React on Rails Pro Node Renderer for server-side rendering",
6
6
  "main": "lib/ReactOnRailsProNodeRenderer.js",
@@ -74,7 +74,7 @@
74
74
  "sentry-testkit": "^5.0.6",
75
75
  "touch": "^3.1.0",
76
76
  "typescript": "^5.4.3",
77
- "react-on-rails": "16.7.0-rc.3"
77
+ "react-on-rails": "17.0.0-rc.0"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "@honeybadger-io/js": ">=4.0.0",