diff --git a/packages/spec/src/automation/flow-value-slot-template.test.ts b/packages/spec/src/automation/flow-value-slot-template.test.ts index 605c23497a..3d486fcbcc 100644 --- a/packages/spec/src/automation/flow-value-slot-template.test.ts +++ b/packages/spec/src/automation/flow-value-slot-template.test.ts @@ -198,7 +198,7 @@ describe('a head CEL claims is read through `vars`, the route a `$`-named head t expect(refusalOf('{record.true}')).not.toContain('the guarded form'); }); - it('an index anywhere in the path leaves it unguarded — `has()` refuses one at run time', () => { + it('an index in the path leaves it unguarded — a step-at-a-time guard would end a `has()` on it, which `has()` refuses at run time', () => { expect(refusalOf('{rows.0.name}')).toContain("source: 'rows[0].name' }"); expect(refusalOf('{rows.0.name}')).not.toContain('the guarded form'); }); diff --git a/packages/spec/src/automation/flow-value-slot-template.ts b/packages/spec/src/automation/flow-value-slot-template.ts index dbff1e7810..462c75fd91 100644 --- a/packages/spec/src/automation/flow-value-slot-template.ts +++ b/packages/spec/src/automation/flow-value-slot-template.ts @@ -315,10 +315,12 @@ type Write = (source: string) => string; /** * A `has()` guard for a path of keys — the absent-variable and absent-key - * remedy. `has()` takes a field selection over names alone: an index anywhere - * in its argument (`has(a[0].b)`, `has(vars["$x"].y)`) is refused when it - * runs, so a path with a numeric segment, a `$`-named head or a keyword - * segment gets no guard. + * remedy. `has()` refuses an index as the last step of its argument + * (`has(a[0])`, `has(vars["$x"])`) when it runs; an index before the last + * step is a presence test like any other (`has(a[0].b)`). The guard tests + * every step of the path, and a numeric segment, a `$`-named head or a keyword + * segment is read by index, so one of its tests would end on that index: such + * a path gets no guard. * * The guard tests one step at a time, from `vars`, which holds only the * variables the run has bound: `has(vars.source) && has(vars.source.id) ?