docs: add workflow automation recipes#12
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces integration recipes and documentation for using Neuron-JS as a deterministic decision node in n8n and LangGraph workflows, including new runnable examples, tests, and updated AI-readable documentation. The feedback highlights two critical issues across the newly added code and documentation snippets: a potential runtime TypeError when spreading potentially undefined errors arrays during validation failures, and a prototype pollution vulnerability in the readStatePath helper function that lacks guards against keys like __proto__ or constructor.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| "Invalid string comparison input", | ||
| ]); | ||
| } | ||
|
|
||
| if (comp !== "=" && comp !== "!=") { | ||
| return new ExecutionResult(false, context, false, [ | ||
| `Unsupported string comparator: ${comp}`, | ||
| ]); | ||
| } | ||
|
|
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
if (!scriptValidation.ok || !contextValidation.ok) {
console.error(
JSON.stringify(
{ ok: false, errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])] },
null,
2,
),
);
process.exit(1);
}| if (!scriptValidation.ok || !contextValidation.ok) { | ||
| console.error( | ||
| JSON.stringify( | ||
| { ok: false, errors: [...scriptValidation.errors, ...contextValidation.errors] }, | ||
| null, | ||
| 2, | ||
| ), | ||
| ); | ||
| process.exit(1); | ||
| } |
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
if (!scriptValidation.ok || !contextValidation.ok) {
console.error(
JSON.stringify(
{ ok: false, errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])] },
null,
2,
),
);
process.exit(1);
}| function readStatePath(context: ExecutionContext, path: string): unknown { | ||
| return path.split(".").reduce<unknown>((current, segment) => { | ||
| if (current && typeof current === "object" && segment in current) { | ||
| return (current as Record<string, unknown>)[segment]; | ||
| } | ||
| return undefined; | ||
| }, context.state); | ||
| } |
There was a problem hiding this comment.
The readStatePath helper splits the path by . and traverses the object. If the path contains keys like __proto__, constructor, or prototype, it can lead to prototype traversal or unexpected behavior. Guard against these special keys to ensure safe object property resolution.
function readStatePath(context: ExecutionContext, path: string): unknown {
return path.split(".").reduce<unknown>((current, segment) => {
if (segment === "__proto__" || segment === "constructor" || segment === "prototype") {
return undefined;
}
if (current && typeof current === "object" && segment in current) {
return (current as Record<string, unknown>)[segment];
}
return undefined;
}, context.state);
}| function readStatePath(context: ExecutionContext, path: string): unknown { | ||
| return path.split(".").reduce<unknown>((current, segment) => { | ||
| if (current && typeof current === "object" && segment in current) { | ||
| return (current as Record<string, unknown>)[segment]; | ||
| } | ||
| return undefined; | ||
| }, context.state); | ||
| } |
There was a problem hiding this comment.
The readStatePath helper splits the path by . and traverses the object. If the path contains keys like __proto__, constructor, or prototype, it can lead to prototype traversal or unexpected behavior. Guard against these special keys to ensure safe object property resolution.
function readStatePath(context: ExecutionContext, path: string): unknown {
return path.split(".").reduce<unknown>((current, segment) => {
if (segment === "__proto__" || segment === "constructor" || segment === "prototype") {
return undefined;
}
if (current && typeof current === "object" && segment in current) {
return (current as Record<string, unknown>)[segment];
}
return undefined;
}, context.state);
}| const contextValidation = validateExecutionContext(context); | ||
|
|
||
| if (!scriptValidation.ok || !contextValidation.ok) { | ||
| return { ...state, neuronDecision: { ok: false, errors: [...scriptValidation.errors, ...contextValidation.errors] } }; |
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
| return { ...state, neuronDecision: { ok: false, errors: [...scriptValidation.errors, ...contextValidation.errors] } }; | |
| return { ...state, neuronDecision: { ok: false, errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])] } }; |
| const contextValidation = validateExecutionContext(context); | ||
|
|
||
| if (!scriptValidation.ok || !contextValidation.ok) { | ||
| return [{ json: { ok: false, errors: [...scriptValidation.errors, ...contextValidation.errors] } }]; |
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
| return [{ json: { ok: false, errors: [...scriptValidation.errors, ...contextValidation.errors] } }]; | |
| return [{ json: { ok: false, errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])] } }]; |
| if (!scriptValidation.ok || !contextValidation.ok) { | ||
| return { | ||
| ...state, | ||
| neuronDecision: { | ||
| ok: false, | ||
| errors: [...scriptValidation.errors, ...contextValidation.errors], | ||
| }, | ||
| }; | ||
| } |
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
| if (!scriptValidation.ok || !contextValidation.ok) { | |
| return { | |
| ...state, | |
| neuronDecision: { | |
| ok: false, | |
| errors: [...scriptValidation.errors, ...contextValidation.errors], | |
| }, | |
| }; | |
| } | |
| if (!scriptValidation.ok || !contextValidation.ok) { | |
| return { | |
| ...state, | |
| neuronDecision: { | |
| ok: false, | |
| errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])], | |
| }, | |
| }; | |
| } |
| if (!scriptValidation.ok || !contextValidation.ok) { | ||
| return [{ | ||
| json: { | ||
| ok: false, | ||
| errors: [...scriptValidation.errors, ...contextValidation.errors], | ||
| }, | ||
| }]; | ||
| } |
There was a problem hiding this comment.
If only one of the validations fails (e.g., scriptValidation.ok is true but contextValidation.ok is false), then scriptValidation.errors will be undefined. Attempting to spread undefined using the spread operator (...scriptValidation.errors) will throw a runtime TypeError: Spread syntax requires all elements to be iterable. Use the nullish coalescing operator (?? []) to safely default to an empty array.
| if (!scriptValidation.ok || !contextValidation.ok) { | |
| return [{ | |
| json: { | |
| ok: false, | |
| errors: [...scriptValidation.errors, ...contextValidation.errors], | |
| }, | |
| }]; | |
| } | |
| if (!scriptValidation.ok || !contextValidation.ok) { | |
| return [{ | |
| json: { | |
| ok: false, | |
| errors: [...(scriptValidation.errors ?? []), ...(contextValidation.errors ?? [])], | |
| }, | |
| }]; | |
| } |
Implements NJS-GROWTH-06. Adds n8n and LangGraph deterministic decision recipes, runnable examples, docs navigation, AI-readable discovery links, and contract tests.
Validation:
Release policy:
Do not merge automatically; Sebastián will verify.