Skip to content

Commit a7d0cb1

Browse files
committed
docs(service-automation): README states the value-slot envelope and current_user
The published README's Expressions section taught `{$User.Id}` / `{$User.Email}` and single-brace field values as value bindings, all refused in a value slot. It now states the dialect as this change leaves it: a value slot computes with the CEL value envelope and reads a plain string as its literal text; `current_user` is the run's user, `null` with no user; `{$User.*}` is refused with its remedy; the date macros are still read until CEL can write them. The changeset gains the lint patch and both kit lines. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
1 parent ab04dda commit a7d0cb1

2 files changed

Lines changed: 25 additions & 7 deletions

File tree

‎.changeset/19939-flow-value-slot-run-user-refused.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
'@objectstack/spec': major
33
'@objectstack/service-automation': major
44
'@objectstack/cli': patch
5+
'@objectstack/lint': patch
56
---
67

78
A flow VALUE slot now refuses the run-user template token `{$User.<path>}` as well, and every CEL expression in a flow sees **`current_user`**, the run's user. `{$User.Id}` in a `create_record` / `update_record` `fields` value or an `assignment` value is refused at `objectstack validate`, at `registerFlow` and by the executor, naming `current_user.id` and, for a flow that can run without a user, its guard; every other `$User` path is refused saying it never resolved.
@@ -40,3 +41,5 @@ Clause-②: no (narrowing)
4041
- **The refusal.** `valueSlotTemplateRefusals` / `flowNodeValueTemplateRefusals` (`@objectstack/spec/automation`); the text-slot judge's run-user remedy (`textSlotTemplateRefusal`) now computes the id with the CEL envelope.
4142
- **The ledger.** The step-18 D3 entries `flow-value-slot-template-dialect-refused` (amended to refuse the run-user paths), `flow-text-slot-single-brace-refused` and `flow-text-slot-unbound-dollar-root-refused` (their run-user remedy). No key is removed, so there is no tombstone, and there is no D2 conversion.
4243
- **`@objectstack/cli`.** `os explain flow`'s example writes `current_user.id` and gates on `current_user != null`.
44+
- **`@objectstack/lint`.** `flow-bare-dollar-reference`'s hint for a bare `$name.path` in a value slot names the CEL envelope the value-slot refusal writes for it — `current_user.id` and its guard for `$User.Id`, the variable the reference names for any other — where it named `{source.id}` and `{$User.Id}`, both refused there. A text slot's hint keeps the `{{ }}` hole, and every other position keeps the single brace.
45+
- **`@objectstack/service-automation`'s README.** Its *Expressions* section states the value-slot envelope, `current_user`, and the date macros still read until CEL can write them.

‎packages/services/service-automation/README.md‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,24 +180,39 @@ This README deliberately does not keep a second copy of that per-node reference.
180180

181181
## Expressions
182182

183-
A flow mixes **two dialects**, and the rule is short: **every condition is CEL;
184-
braces are for values.**
183+
A flow's expressions follow its positions: **a condition is bare CEL, a value is
184+
a CEL value envelope, and text is a `{{ }}` template.**
185185

186186
| Where | Dialect | Write it like |
187187
|:---|:---|:---|
188188
| Start-node `condition` | CEL — bare, no braces | `record.amount > 500` |
189189
| Edge `condition` | CEL — bare, no braces | `record.status == 'open'` |
190190
| Decision `conditions[].expression` | CEL — bare, no braces | `order_amount > 10000` |
191-
| Field values in `create_record` / `update_record` | Interpolation — braces required | `'Follow up on {record.name}'`, `'{TODAY() + 7}'` |
191+
| Value slots — `create_record` / `update_record` `fields`, `assignment` values | CEL value envelope; a plain string is the literal text it spells | `{ dialect: 'cel', source: "'Follow up on ' + record.name" }`, `'open'` |
192192
| Text slots — `notify` `title` / `message`, `screen` `title` / `description`, `end` `message` | Template — `{{ }}` holes (ADR-0032 §3; a single-brace token is refused) | `'Deal won: {{ record.name }}'`, `'{{ record.amount \| currency }}'` |
193193

194-
Value bindings: `{var}`, `{var.path}`, `{$User.Id}`, `{$User.Email}`, `{NOW()}`,
195-
`{TODAY()}`, `{TODAY() + 90}`.
194+
A value slot refuses a `{…}` template token — `registerFlow()` and
195+
`objectstack validate` name its CEL spelling — except the date macros
196+
(`'{NOW()}'`, `'{TODAY()}'`, `'{TODAY() + 90}'`), which it still reads until CEL
197+
can write them: CEL's `now()` / `today()` are timestamps, not the text the
198+
macros write. Other value-like positions — a `filter`, `recipients`, an `http`
199+
payload, `subflow.input` — still read the single-brace dialect (`{record.id}`).
200+
201+
The run's user is **`current_user`** in every flow CEL expression: `id`,
202+
`positions`, `organizationId`, `isPlatformAdmin`, nothing more. In a run with no
203+
user (a schedule, a record change made by a system write) it is `null`, never a
204+
stand-in user. So `{$User.Id}` is refused in a value slot: write
205+
`{ dialect: 'cel', source: 'current_user.id' }`, or, in a flow that can run
206+
without a user, `current_user != null ? current_user.id : null` (with no user it
207+
writes `null`, which on `update_record` clears the stored value). Every other
208+
`{$User.<path>}` (`{$User.Email}`) never resolved and is refused too: read the
209+
user record by `current_user.id` with a `get_record` on `sys_user`.
196210

197211
The two failure modes to memorize:
198212

199-
1. **Braces missing in a field value** — `due_date: 'TODAY() + 7'` writes the
200-
literal text into the field. Write `'{TODAY() + 7}'`.
213+
1. **A plain string in a value slot** — `due_date: 'TODAY() + 7'` or
214+
`owner: 'current_user.id'` writes that text into the field. Write a date
215+
macro in braces (`'{TODAY() + 7}'`), anything else as a CEL envelope.
201216
2. **Braces put *into* a condition** — `'{record.amount} > 500'`. Since #4336
202217
conditions reject this loudly: `registerFlow()` / `objectstack validate`
203218
refuse the flow with a CEL error naming the reference. Before that they were

0 commit comments

Comments
 (0)