From 6b9be7b086dbe65ad17114d3b9a6df1b12eeda56 Mon Sep 17 00:00:00 2001 From: rabbitblood Date: Sun, 26 Apr 2026 06:05:47 -0700 Subject: [PATCH] docs(provisioning): clarify separator-safety contract for the serialized-node string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit simplify-review note: the |/,-delimited node string is brittle if a future string-typed field is added without sanitization. Document which fields are user-typed (name — already sanitized) vs primitive (id is UUID, runtime is a slug, provisionTimeoutMs is numeric) so the next field-add doesn't accidentally introduce an injection vector for the splitter. Skipped (false-positive review finding): the agent flagged the prop > runtime-profile order as inconsistent with the docstring, but the docstring explicitly lists the prop at #2 (between node and runtime-profile) — matches both the implementation AND the original behavior pre-#2054 (the prop was 'timeoutMs ?? runtime-profile'). Co-Authored-By: Claude Opus 4.7 (1M context) --- canvas/src/components/ProvisioningTimeout.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/canvas/src/components/ProvisioningTimeout.tsx b/canvas/src/components/ProvisioningTimeout.tsx index 39d8a1fc..2f2ee564 100644 --- a/canvas/src/components/ProvisioningTimeout.tsx +++ b/canvas/src/components/ProvisioningTimeout.tsx @@ -73,8 +73,11 @@ export function ProvisioningTimeout({ // runtimes — a single threshold would false-alarm on one or the other). // provisionTimeoutMs added by #2054 — server-declared per-workspace // override that wins over the runtime profile when present. - // Separator: `|` between fields, `,` between nodes. Names may contain - // anything the user typed; strip `|` and `,` so serialization round-trips. + // Separator: `|` between fields, `,` between nodes. Only `name` is + // user-typed (gets sanitized below); the other fields are + // primitive-typed (id is a UUID, runtime is a [a-z-]+ slug, + // provisionTimeoutMs is numeric). If a future field is string-typed, + // extend the sanitize step to strip `|` + `,` from it too. // Empty-string sentinels for missing values so split/index stays positional. const provisioningNodes = useCanvasStore((s) => { const result = s.nodes