#7

planToJs renders non-identifier arg keys as invalid JS

Openbeardthelionopened 2mo ago

Summary

planToJs in apps/web/lib/plan-to-js.ts renders call-step args object keys unquoted. A validated script whose args carry a non-identifier key (space, dot, or hyphen) renders as syntactically invalid JavaScript.

Details

args are validated by jsonValueSchema = z.record(z.string(), ...) in packages/callscript/src/schema.ts, so any string key is legal in a stored plan. But argsToJs emits object entries as `${k}: ${argsToJs(v)}` — the key raw. For example, args: { "foo bar": 1 } renders as:

const a = await svc.echo({ foo bar: 1 }, { reason: "r" });

which is a SyntaxError (Unexpected identifier 'bar'). Keys with dots (a.b) or hyphens (a-b) break the same way. Identifier keys (ok), numeric-string keys ("123"), reserved words (class), and unicode identifiers (ünï) are fine.

Impact

Low severity: planToJs is a display/authoring renderer (converts a stored plan back to its JS surface). It has no callers in the app today and its output is never executed. But the renderer's contract is to produce the readable JS form of any stored plan, and it produces garbage for a class of legal inputs — a latent correctness bug if the output is ever shown to a model or pasted back into an editor.

Fix

Quote keys that are not valid identifier names (reserved words are legal property names, so only identifier grammar needs checking). A fix is in progress on branch fix/plan-to-js-quote-non-identifier-keys in a fork.

Test coverage note

apps/web has no vitest wiring, so this renderer had no regression coverage. The fix adds a vitest seam and a regression test asserting planToJs output always parses as valid JS and round-trips non-identifier keys to the original value.

Activity

0

No activity yet.