@sanity/workflow-engine 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/define.d.cts CHANGED
@@ -1,12 +1,14 @@
1
1
  import * as v from "valibot";
2
2
 
3
- declare type Action = ActionFields<Op>;
3
+ declare type Action = ActionFields<Op, string[]>;
4
4
 
5
- /** Type-mirror of {@link actionFields}, parameterised over the op grammar. */
6
- declare type ActionFields<TOp> = {
5
+ /** Type-mirror of {@link actionFields}, parameterised over the op and
6
+ * group-membership grammars. */
7
+ declare type ActionFields<TOp, TGroup> = {
7
8
  name: string;
8
9
  title?: string | undefined;
9
10
  description?: string | undefined;
11
+ group?: TGroup | undefined;
10
12
  filter?: string | undefined;
11
13
  params?: ActionParam[] | undefined;
12
14
  ops?: TOp[] | undefined;
@@ -53,7 +55,13 @@ declare const ActionParamSchema: v.StrictObjectSchema<
53
55
  undefined
54
56
  >;
55
57
 
56
- declare type Activity = ActivityFields<FieldEntry, Action, Op, ManualTarget>;
58
+ declare type Activity = ActivityFields<
59
+ FieldEntry,
60
+ Action,
61
+ Op,
62
+ ManualTarget,
63
+ string[]
64
+ >;
57
65
 
58
66
  declare const ACTIVITY_KINDS: readonly [
59
67
  "user",
@@ -63,11 +71,13 @@ declare const ACTIVITY_KINDS: readonly [
63
71
  "receive",
64
72
  ];
65
73
 
66
- /** Type-mirror of {@link activityFields}, parameterised over field/action/op/target. */
67
- declare type ActivityFields<TField, TAction, TOp, TTarget> = {
74
+ /** Type-mirror of {@link activityFields}, parameterised over field/action/op/target/group. */
75
+ declare type ActivityFields<TField, TAction, TOp, TTarget, TGroup> = {
68
76
  name: string;
69
77
  title?: string | undefined;
70
78
  description?: string | undefined;
79
+ groups?: Group[] | undefined;
80
+ group?: TGroup | undefined;
71
81
  kind?: ActivityKind | undefined;
72
82
  target?: TTarget | undefined;
73
83
  activation?: "auto" | "manual" | undefined;
@@ -90,7 +100,8 @@ declare type AuthoringActivity = ActivityFields<
90
100
  AuthoringFieldEntry,
91
101
  AuthoringAction,
92
102
  AuthoringOp,
93
- AuthoringManualTarget
103
+ AuthoringManualTarget,
104
+ GroupMembership
94
105
  >;
95
106
 
96
107
  declare type AuthoringEditable = v.InferOutput<typeof AuthoringEditableSchema>;
@@ -98,7 +109,7 @@ declare type AuthoringEditable = v.InferOutput<typeof AuthoringEditableSchema>;
98
109
  /**
99
110
  * Authoring editability adds the `role[]` convenience: a non-empty role list
100
111
  * desugars to the same `count($actor.roles[@ in [...]]) > 0` membership
101
- * predicate `action.roles` produces. `true` opens the slot to anyone in its
112
+ * predicate `action.roles` produces. `true` opens the field to anyone in its
102
113
  * window; a bare string is a raw predicate.
103
114
  */
104
115
  declare const AuthoringEditableSchema: v.UnionSchema<
@@ -150,6 +161,292 @@ declare const AuthoringFieldRefSchema: v.StrictObjectSchema<
150
161
  undefined
151
162
  >;
152
163
 
164
+ declare type AuthoringGuard = v.InferOutput<typeof AuthoringGuardSchema>;
165
+
166
+ declare const AuthoringGuardSchema: v.StrictObjectSchema<
167
+ {
168
+ name: v.SchemaWithPipe<
169
+ readonly [
170
+ v.StringSchema<undefined>,
171
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
172
+ ]
173
+ >;
174
+ title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
175
+ description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
176
+ match: v.StrictObjectSchema<
177
+ {
178
+ /** Subject `_type`(s); empty matches any type. */
179
+ types: v.OptionalSchema<
180
+ v.ArraySchema<
181
+ v.SchemaWithPipe<
182
+ readonly [
183
+ v.StringSchema<undefined>,
184
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
185
+ ]
186
+ >,
187
+ undefined
188
+ >,
189
+ undefined
190
+ >;
191
+ /** Target docs as field reads (or the instance itself), resolved at deploy to bare ids + the resource. */
192
+ idRefs: v.OptionalSchema<
193
+ v.ArraySchema<
194
+ v.VariantSchema<
195
+ "type",
196
+ [
197
+ v.StrictObjectSchema<
198
+ {
199
+ readonly type: v.LiteralSchema<"self", undefined>;
200
+ },
201
+ undefined
202
+ >,
203
+ v.StrictObjectSchema<
204
+ {
205
+ readonly type: v.LiteralSchema<"now", undefined>;
206
+ },
207
+ undefined
208
+ >,
209
+ v.StrictObjectSchema<
210
+ {
211
+ readonly type: v.LiteralSchema<"fieldRead", undefined>;
212
+ readonly field: v.SchemaWithPipe<
213
+ readonly [
214
+ v.StringSchema<undefined>,
215
+ v.RegexAction<string, string>,
216
+ ]
217
+ >;
218
+ readonly path: v.OptionalSchema<
219
+ v.SchemaWithPipe<
220
+ readonly [
221
+ v.SchemaWithPipe<
222
+ readonly [
223
+ v.StringSchema<undefined>,
224
+ v.MinLengthAction<
225
+ string,
226
+ 1,
227
+ "must be a non-empty string"
228
+ >,
229
+ ]
230
+ >,
231
+ v.CheckAction<
232
+ string,
233
+ "a guard read path cannot contain a line break"
234
+ >,
235
+ ]
236
+ >,
237
+ undefined
238
+ >;
239
+ },
240
+ undefined
241
+ >,
242
+ v.StrictObjectSchema<
243
+ {
244
+ readonly type: v.LiteralSchema<"effectsRead", undefined>;
245
+ readonly effect: v.SchemaWithPipe<
246
+ readonly [
247
+ v.SchemaWithPipe<
248
+ readonly [
249
+ v.StringSchema<undefined>,
250
+ v.MinLengthAction<
251
+ string,
252
+ 1,
253
+ "must be a non-empty string"
254
+ >,
255
+ ]
256
+ >,
257
+ v.CheckAction<
258
+ string,
259
+ "an effect name cannot contain `'`"
260
+ >,
261
+ ]
262
+ >;
263
+ readonly path: v.OptionalSchema<
264
+ v.SchemaWithPipe<
265
+ readonly [
266
+ v.SchemaWithPipe<
267
+ readonly [
268
+ v.StringSchema<undefined>,
269
+ v.MinLengthAction<
270
+ string,
271
+ 1,
272
+ "must be a non-empty string"
273
+ >,
274
+ ]
275
+ >,
276
+ v.CheckAction<
277
+ string,
278
+ "a guard read path cannot contain a line break"
279
+ >,
280
+ ]
281
+ >,
282
+ undefined
283
+ >;
284
+ },
285
+ undefined
286
+ >,
287
+ ],
288
+ undefined
289
+ >,
290
+ undefined
291
+ >,
292
+ undefined
293
+ >;
294
+ /** Glob id patterns (bare, resource-local). */
295
+ idPatterns: v.OptionalSchema<
296
+ v.ArraySchema<
297
+ v.SchemaWithPipe<
298
+ readonly [
299
+ v.StringSchema<undefined>,
300
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
301
+ ]
302
+ >,
303
+ undefined
304
+ >,
305
+ undefined
306
+ >;
307
+ actions: v.SchemaWithPipe<
308
+ readonly [
309
+ v.ArraySchema<
310
+ v.PicklistSchema<
311
+ readonly ["create", "update", "delete", "publish", "unpublish"],
312
+ `Invalid option: expected one of ${string}`
313
+ >,
314
+ undefined
315
+ >,
316
+ v.MinLengthAction<
317
+ ("create" | "update" | "delete" | "publish" | "unpublish")[],
318
+ 1,
319
+ "a guard must match at least one action"
320
+ >,
321
+ ]
322
+ >;
323
+ },
324
+ undefined
325
+ >;
326
+ /**
327
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
328
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
329
+ * `identity()`. Bare ids/fields only. Omitted or empty means
330
+ * UNCONDITIONAL DENY.
331
+ */
332
+ predicate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
333
+ /**
334
+ * Projected workflow fields the predicate reads as `guard.metadata.*` —
335
+ * the only bridge from the lake eval context (which cannot see `$fields`)
336
+ * to workflow fields. Each value is a deploy-time read — a typed
337
+ * {@link GuardRead} when authoring, the printed string spelling once
338
+ * stored — resolved into a bare value at deploy and re-synced by the
339
+ * post-field-op guard refresh.
340
+ */
341
+ metadata: v.OptionalSchema<
342
+ v.RecordSchema<
343
+ v.SchemaWithPipe<
344
+ readonly [
345
+ v.StringSchema<undefined>,
346
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
347
+ ]
348
+ >,
349
+ v.VariantSchema<
350
+ "type",
351
+ [
352
+ v.StrictObjectSchema<
353
+ {
354
+ readonly type: v.LiteralSchema<"self", undefined>;
355
+ },
356
+ undefined
357
+ >,
358
+ v.StrictObjectSchema<
359
+ {
360
+ readonly type: v.LiteralSchema<"now", undefined>;
361
+ },
362
+ undefined
363
+ >,
364
+ v.StrictObjectSchema<
365
+ {
366
+ readonly type: v.LiteralSchema<"fieldRead", undefined>;
367
+ readonly field: v.SchemaWithPipe<
368
+ readonly [
369
+ v.StringSchema<undefined>,
370
+ v.RegexAction<string, string>,
371
+ ]
372
+ >;
373
+ readonly path: v.OptionalSchema<
374
+ v.SchemaWithPipe<
375
+ readonly [
376
+ v.SchemaWithPipe<
377
+ readonly [
378
+ v.StringSchema<undefined>,
379
+ v.MinLengthAction<
380
+ string,
381
+ 1,
382
+ "must be a non-empty string"
383
+ >,
384
+ ]
385
+ >,
386
+ v.CheckAction<
387
+ string,
388
+ "a guard read path cannot contain a line break"
389
+ >,
390
+ ]
391
+ >,
392
+ undefined
393
+ >;
394
+ },
395
+ undefined
396
+ >,
397
+ v.StrictObjectSchema<
398
+ {
399
+ readonly type: v.LiteralSchema<"effectsRead", undefined>;
400
+ readonly effect: v.SchemaWithPipe<
401
+ readonly [
402
+ v.SchemaWithPipe<
403
+ readonly [
404
+ v.StringSchema<undefined>,
405
+ v.MinLengthAction<
406
+ string,
407
+ 1,
408
+ "must be a non-empty string"
409
+ >,
410
+ ]
411
+ >,
412
+ v.CheckAction<string, "an effect name cannot contain `'`">,
413
+ ]
414
+ >;
415
+ readonly path: v.OptionalSchema<
416
+ v.SchemaWithPipe<
417
+ readonly [
418
+ v.SchemaWithPipe<
419
+ readonly [
420
+ v.StringSchema<undefined>,
421
+ v.MinLengthAction<
422
+ string,
423
+ 1,
424
+ "must be a non-empty string"
425
+ >,
426
+ ]
427
+ >,
428
+ v.CheckAction<
429
+ string,
430
+ "a guard read path cannot contain a line break"
431
+ >,
432
+ ]
433
+ >,
434
+ undefined
435
+ >;
436
+ },
437
+ undefined
438
+ >,
439
+ ],
440
+ undefined
441
+ >,
442
+ undefined
443
+ >,
444
+ undefined
445
+ >;
446
+ },
447
+ undefined
448
+ >;
449
+
153
450
  declare type AuthoringManualTarget = v.InferOutput<
154
451
  typeof AuthoringManualTargetSchema
155
452
  >;
@@ -309,7 +606,12 @@ declare const AuthoringOpSchema: v.VariantSchema<
309
606
  },
310
607
  undefined
311
608
  >;
312
- readonly where: v.GenericSchema<OpPredicateInternal>;
609
+ readonly where: v.SchemaWithPipe<
610
+ readonly [
611
+ v.StringSchema<undefined>,
612
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
613
+ ]
614
+ >;
313
615
  readonly value: v.GenericSchema<ValueExprInternal>;
314
616
  },
315
617
  undefined
@@ -335,7 +637,12 @@ declare const AuthoringOpSchema: v.VariantSchema<
335
637
  },
336
638
  undefined
337
639
  >;
338
- readonly where: v.GenericSchema<OpPredicateInternal>;
640
+ readonly where: v.SchemaWithPipe<
641
+ readonly [
642
+ v.StringSchema<undefined>,
643
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
644
+ ]
645
+ >;
339
646
  },
340
647
  undefined
341
648
  >,
@@ -423,19 +730,26 @@ declare const AuthoringOpSchema: v.VariantSchema<
423
730
  * - `status` → a `status.set` op on the firing activity, appended **after**
424
731
  * the authored ops (deliberately never implied: a forgotten explicit
425
732
  * `status` is a visible stall, an implied default silently completes
426
- * claim-like actions).
733
+ * claim-like actions). Status is the health axis: a decision action
734
+ * (decline, send back) resolves `done` and writes the decision into a
735
+ * field the transition filter reads — `failed` is for work that
736
+ * genuinely could not complete.
427
737
  */
428
- declare type AuthoringRawAction = ActionFields<AuthoringOp> & {
738
+ declare type AuthoringRawAction = ActionFields<AuthoringOp, GroupMembership> & {
429
739
  roles?: string[] | undefined;
430
740
  status?: TerminalActivityStatus | undefined;
431
741
  };
432
742
 
433
- declare type AuthoringRawFieldEntry = FieldEntryFields<AuthoringEditable>;
743
+ declare type AuthoringRawFieldEntry = FieldEntryFields<
744
+ AuthoringEditable,
745
+ GroupMembership
746
+ >;
434
747
 
435
748
  declare type AuthoringStage = StageFields<
436
749
  AuthoringFieldEntry,
437
750
  AuthoringActivity,
438
751
  AuthoringTransition,
752
+ AuthoringGuard,
439
753
  AuthoringEditable
440
754
  >;
441
755
 
@@ -550,7 +864,12 @@ declare const AuthoringTransitionOpSchema: v.VariantSchema<
550
864
  },
551
865
  undefined
552
866
  >;
553
- readonly where: v.GenericSchema<OpPredicateInternal>;
867
+ readonly where: v.SchemaWithPipe<
868
+ readonly [
869
+ v.StringSchema<undefined>,
870
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
871
+ ]
872
+ >;
554
873
  readonly value: v.GenericSchema<ValueExprInternal>;
555
874
  },
556
875
  undefined
@@ -576,7 +895,12 @@ declare const AuthoringTransitionOpSchema: v.VariantSchema<
576
895
  },
577
896
  undefined
578
897
  >;
579
- readonly where: v.GenericSchema<OpPredicateInternal>;
898
+ readonly where: v.SchemaWithPipe<
899
+ readonly [
900
+ v.StringSchema<undefined>,
901
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
902
+ ]
903
+ >;
580
904
  },
581
905
  undefined
582
906
  >,
@@ -654,6 +978,7 @@ declare type ClaimAction = {
654
978
  name: string;
655
979
  title?: string | undefined;
656
980
  description?: string | undefined;
981
+ group?: GroupMembership | undefined;
657
982
  field: string | AuthoringFieldRef;
658
983
  roles?: string[] | undefined;
659
984
  filter?: string | undefined;
@@ -664,7 +989,7 @@ declare type ClaimAction = {
664
989
  /**
665
990
  * Authoring fields accept the raw entries plus the `claim` sugar type — the
666
991
  * field half of the mirrored claim pair. Expansion: an `actor` working-
667
- * memory slot (no `initialValue`; the claim action's op fills it), strictly
992
+ * memory field (no `initialValue`; the claim action's op fills it), strictly
668
993
  * within this entry.
669
994
  */
670
995
  declare type ClaimField = {
@@ -672,8 +997,67 @@ declare type ClaimField = {
672
997
  name: string;
673
998
  title?: string | undefined;
674
999
  description?: string | undefined;
1000
+ group?: GroupMembership | undefined;
675
1001
  };
676
1002
 
1003
+ /**
1004
+ * Every variable the engine binds for conditions, in one place. The
1005
+ * deploy-time shadow check ({@link RESERVED_CONDITION_VARS}) and the docs on
1006
+ * {@link Condition} derive from this list — extend it here when the engine
1007
+ * grows a binding, never in a comment elsewhere.
1008
+ */
1009
+ export declare const CONDITION_VARS: readonly ConditionVar[];
1010
+
1011
+ export declare interface ConditionVar {
1012
+ /** The GROQ param name, read as `$<name>`. */
1013
+ name: string;
1014
+ binding: ConditionVarBinding;
1015
+ description: string;
1016
+ /** Short human phrase for rendered explanations ("all activities in this
1017
+ * stage are finished") — consumer-facing, unlike `description`. */
1018
+ label: string;
1019
+ }
1020
+
1021
+ /**
1022
+ * The condition-variable inventory — the single source of truth for every
1023
+ * `$var` the engine binds when it evaluates a {@link Condition}.
1024
+ *
1025
+ * Three evaluation contexts read a definition's GROQ:
1026
+ *
1027
+ * 1. **Rendered condition scope** — every condition site in a definition
1028
+ * (transition filters, `completeWhen`/`failWhen`, action filters, effect
1029
+ * bindings, `subworkflows` reads, where-op `where`s, editability
1030
+ * predicates, author predicates). {@link CONDITION_VARS} is its inventory;
1031
+ * each entry's `binding` says when the var actually holds a value. The
1032
+ * where-op context is the one closed subset — its bound set is statically
1033
+ * fixed and deploy-enforced (see the op-where scope's param-name list in
1034
+ * the op applier).
1035
+ * 2. **Filter evaluation without a caller** — the engine's cascade evaluates
1036
+ * transition filters and the activity gates (`filter`, `completeWhen`,
1037
+ * `failWhen`) with no caller, so only the `'always'`-bound subset carries
1038
+ * values there ({@link FILTER_SCOPE_VARS}). Caller-bound vars fail closed —
1039
+ * `$assigned` binds its caller-free constant `false`, the rest evaluate to
1040
+ * `undefined` — and deploy rejects them at these sites: routing and gate
1041
+ * resolution must resolve identically no matter whose token triggers the
1042
+ * evaluation.
1043
+ * 3. **Guard predicates** — NOT conditions. A lake mutation guard's
1044
+ * `predicate` is groq-js **delta-mode** GROQ over a document mutation:
1045
+ * `before()`/`after()`/`identity()` are dialect natives, and the wire
1046
+ * format binds the identifiers in {@link GUARD_PREDICATE_VARS}. None of
1047
+ * the condition vars exist there.
1048
+ */
1049
+ /**
1050
+ * When a condition var holds a value:
1051
+ *
1052
+ * - `'always'` — bound in every condition evaluation, derived from the
1053
+ * instance and its snapshot.
1054
+ * - `'caller'` — rides the acting caller; without one the var is `undefined`
1055
+ * (conditions referencing it fail closed). Author predicates may not read
1056
+ * these — they pre-evaluate once per instance, caller-free.
1057
+ * - `'spawn'` — bound only at `subworkflows` sites (the per-row `$row`).
1058
+ */
1059
+ export declare type ConditionVarBinding = "always" | "caller" | "spawn";
1060
+
677
1061
  export declare function defineAction(action: AuthoringAction): AuthoringAction;
678
1062
 
679
1063
  export declare function defineActivity(
@@ -694,7 +1078,15 @@ export declare function defineField(
694
1078
  entry: AuthoringFieldEntry,
695
1079
  ): AuthoringFieldEntry;
696
1080
 
697
- export declare function defineGuard(guard: Guard): Guard;
1081
+ /**
1082
+ * Validate and return a group declaration — advisory "what belongs together"
1083
+ * metadata. Declared in a `groups` array (workflow root, stage, or activity);
1084
+ * fields, activities, and actions join via `group`. The engine stores and
1085
+ * deploy-checks groups but never acts on them.
1086
+ */
1087
+ export declare function defineGroup(group: Group): Group;
1088
+
1089
+ export declare function defineGuard(guard: AuthoringGuard): AuthoringGuard;
698
1090
 
699
1091
  export declare function defineOp(op: AuthoringOp): AuthoringOp;
700
1092
 
@@ -720,6 +1112,16 @@ export declare function defineWorkflow(
720
1112
  definition: AuthoringWorkflow,
721
1113
  ): WorkflowDefinition;
722
1114
 
1115
+ /**
1116
+ * Validate a deploy config — the binding of each definition's logical resource
1117
+ * handles to physical resources, per environment (tag). Throws a formatted,
1118
+ * path-prefixed error if the shape is invalid. The CLI hands the selected
1119
+ * deployment's {@link resourceAliasesToMap} map to {@link deployDefinitions}.
1120
+ */
1121
+ export declare function defineWorkflowConfig(
1122
+ config: WorkflowConfig,
1123
+ ): WorkflowConfig;
1124
+
723
1125
  declare type Editable = v.InferOutput<typeof StoredEditableSchema>;
724
1126
 
725
1127
  declare type Effect = v.InferOutput<typeof EffectSchema>;
@@ -775,6 +1177,26 @@ declare const EffectSchema: v.StrictObjectSchema<
775
1177
  v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>,
776
1178
  undefined
777
1179
  >;
1180
+ /**
1181
+ * The outputs this effect is allowed to produce, as typed {@link FieldShape}s
1182
+ * (each `name` is an output key, read downstream as `$effects['<name>'].<key>`;
1183
+ * an `array` output is an array of objects shaped by `of`).
1184
+ *
1185
+ * A STRICT allowlist: at completion the handler's returned `outputs` are
1186
+ * validated against these shapes and an undeclared key — or a value that
1187
+ * doesn't fit its shape — fails the completion (nothing is stored). Omitting
1188
+ * `outputs` is an EMPTY allowlist: the effect produces nothing, so any returned
1189
+ * output is rejected — the bound is universal, not opt-in.
1190
+ * Why strict: `effectsContext` lives on the instance document, so the allowlist
1191
+ * keeps it bounded — a handler can't accidentally spread a whole API response
1192
+ * into the instance — and the declared shapes let tooling (e.g. the simulator's
1193
+ * drain UI) suggest an effect's exact output keys. Declaring outputs also
1194
+ * powers the advisory deploy-time producer/consumer lint.
1195
+ */
1196
+ readonly outputs: v.OptionalSchema<
1197
+ v.ArraySchema<v.GenericSchema<FieldShape>, undefined>,
1198
+ undefined
1199
+ >;
778
1200
  },
779
1201
  undefined
780
1202
  >;
@@ -784,6 +1206,9 @@ declare const EffectSchema: v.StrictObjectSchema<
784
1206
  * reference kinds, the actor/assignee identities, and the two compositional
785
1207
  * kinds (`object` with named `fields`, `array` of objects shaped by `of`).
786
1208
  * This is also the set a nested {@link FieldShape} sub-field may use.
1209
+ *
1210
+ * Exported (module-level, not package API) for the model-surface gate's
1211
+ * enum-value coverage test.
787
1212
  */
788
1213
  declare const FIELD_VALUE_KINDS: readonly [
789
1214
  "doc.ref",
@@ -803,12 +1228,28 @@ declare const FIELD_VALUE_KINDS: readonly [
803
1228
  "array",
804
1229
  ];
805
1230
 
806
- declare type FieldEntry = FieldEntryFields<Editable>;
1231
+ /** Type-mirror of {@link fieldBase}, parameterised over the `editable` and
1232
+ * `group` grammars (stored membership is the canonical list form). */
1233
+ declare type FieldBase<TEditable, TGroup> = {
1234
+ name: string;
1235
+ title?: string | undefined;
1236
+ description?: string | undefined;
1237
+ group?: TGroup | undefined;
1238
+ required?: boolean | undefined;
1239
+ initialValue?: FieldSource | undefined;
1240
+ editable?: TEditable | undefined;
1241
+ };
1242
+
1243
+ declare type FieldEntry = FieldEntryFields<Editable, string[]>;
807
1244
 
808
1245
  /** Type-mirror of {@link fieldEntryFields}: a raw field entry of the given
809
- * editability grammar. */
810
- declare type FieldEntryFields<TEditable> = SlotFields<TEditable> & {
1246
+ * editability and group-membership grammars. */
1247
+ declare type FieldEntryFields<TEditable, TGroup> = FieldBase<
1248
+ TEditable,
1249
+ TGroup
1250
+ > & {
811
1251
  type: FieldValueKind;
1252
+ types?: string[] | undefined;
812
1253
  fields?: FieldShape[] | undefined;
813
1254
  of?: FieldShape[] | undefined;
814
1255
  };
@@ -847,6 +1288,13 @@ declare type FieldSourceInternal =
847
1288
  /** The union a value (or nested {@link FieldShape}) kind may take — see {@link FIELD_VALUE_KINDS}. */
848
1289
  declare type FieldValueKind = (typeof FIELD_VALUE_KINDS)[number];
849
1290
 
1291
+ /**
1292
+ * The subset that holds a value when the engine evaluates filters without a
1293
+ * caller (the cascade path: transition filters, activity `filter`/
1294
+ * `completeWhen`/`failWhen`).
1295
+ */
1296
+ export declare const FILTER_SCOPE_VARS: readonly string[];
1297
+
850
1298
  /**
851
1299
  * Hygienic GROQ interpolation for define-time condition building.
852
1300
  *
@@ -867,25 +1315,59 @@ export declare function groq(
867
1315
  ...values: unknown[]
868
1316
  ): string;
869
1317
 
1318
+ /** Type-mirror of {@link GroupSchema} — one declared group. */
1319
+ declare type Group = {
1320
+ name: string;
1321
+ title?: string | undefined;
1322
+ description?: string | undefined;
1323
+ kind?: GroupKind | undefined;
1324
+ };
1325
+
1326
+ declare const GROUP_KINDS: readonly ["core", "details"];
1327
+
1328
+ declare type GroupKind = (typeof GROUP_KINDS)[number];
1329
+
1330
+ /**
1331
+ * Group membership — the declared group(s) a node belongs to. A reference
1332
+ * resolves lexically up the node's enclosing chain (host activity → stage →
1333
+ * workflow; an activity's OWN membership sees stage → workflow — a node is
1334
+ * never a member of a group only it declares). An empty list is an author
1335
+ * error (it would name no groups) — omit `group` instead, and each group is
1336
+ * listed once. Authoring accepts a bare name as convenience; the STORED form
1337
+ * is always a list, so `'seo'` and `['seo']` hash identically under content
1338
+ * addressing and lake-side reads see one shape.
1339
+ */
1340
+ declare type GroupMembership = string | string[];
1341
+
870
1342
  declare type Guard = v.InferOutput<typeof GuardSchema>;
871
1343
 
1344
+ /**
1345
+ * The identifiers a lake mutation guard's `predicate` reads — the wire
1346
+ * dialect, not the condition scope (so no {@link ConditionVarBinding}: these
1347
+ * bind only when a guard evaluates a mutation). `before()`/`after()`/
1348
+ * `identity()` are groq-js delta-mode natives on top of these. Bound in one
1349
+ * place: `guardPredicateParams` in the guard evaluator.
1350
+ */
1351
+ export declare const GUARD_PREDICATE_VARS: readonly {
1352
+ name: string;
1353
+ description: string;
1354
+ }[];
1355
+
1356
+ /** Stored guards carry the printed string reads (the deploy resolver's input). */
872
1357
  declare const GuardSchema: v.StrictObjectSchema<
873
1358
  {
874
- readonly name: v.SchemaWithPipe<
1359
+ name: v.SchemaWithPipe<
875
1360
  readonly [
876
1361
  v.StringSchema<undefined>,
877
1362
  v.MinLengthAction<string, 1, "must be a non-empty string">,
878
1363
  ]
879
1364
  >;
880
- readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
881
- readonly description: v.OptionalSchema<
882
- v.StringSchema<undefined>,
883
- undefined
884
- >;
885
- readonly match: v.StrictObjectSchema<
1365
+ title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1366
+ description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1367
+ match: v.StrictObjectSchema<
886
1368
  {
887
1369
  /** Subject `_type`(s); empty matches any type. */
888
- readonly types: v.OptionalSchema<
1370
+ types: v.OptionalSchema<
889
1371
  v.ArraySchema<
890
1372
  v.SchemaWithPipe<
891
1373
  readonly [
@@ -897,8 +1379,8 @@ declare const GuardSchema: v.StrictObjectSchema<
897
1379
  >,
898
1380
  undefined
899
1381
  >;
900
- /** Target docs as `$fields` reads (or `"$self"`), resolved at deploy to bare ids + the resource. */
901
- readonly idRefs: v.OptionalSchema<
1382
+ /** Target docs as field reads (or the instance itself), resolved at deploy to bare ids + the resource. */
1383
+ idRefs: v.OptionalSchema<
902
1384
  v.ArraySchema<
903
1385
  v.SchemaWithPipe<
904
1386
  readonly [
@@ -911,7 +1393,7 @@ declare const GuardSchema: v.StrictObjectSchema<
911
1393
  undefined
912
1394
  >;
913
1395
  /** Glob id patterns (bare, resource-local). */
914
- readonly idPatterns: v.OptionalSchema<
1396
+ idPatterns: v.OptionalSchema<
915
1397
  v.ArraySchema<
916
1398
  v.SchemaWithPipe<
917
1399
  readonly [
@@ -923,7 +1405,7 @@ declare const GuardSchema: v.StrictObjectSchema<
923
1405
  >,
924
1406
  undefined
925
1407
  >;
926
- readonly actions: v.SchemaWithPipe<
1408
+ actions: v.SchemaWithPipe<
927
1409
  readonly [
928
1410
  v.ArraySchema<
929
1411
  v.PicklistSchema<
@@ -943,21 +1425,21 @@ declare const GuardSchema: v.StrictObjectSchema<
943
1425
  undefined
944
1426
  >;
945
1427
  /**
946
- * Lake GROQ predicate — a distinct eval context reading
947
- * `document.before`/`document.after`, `mutation`, `guard`, and
1428
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
1429
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
948
1430
  * `identity()`. Bare ids/fields only. Omitted or empty means
949
1431
  * UNCONDITIONAL DENY.
950
1432
  */
951
- readonly predicate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1433
+ predicate: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
952
1434
  /**
953
1435
  * Projected workflow fields the predicate reads as `guard.metadata.*` —
954
1436
  * the only bridge from the lake eval context (which cannot see `$fields`)
955
- * to workflow fields. Values are NOT GROQ: each is a deploy-time read in
956
- * the guard mini-language `"$self"`, `"$now"`, or
957
- * `"$fields.<name>[.path]"` — resolved into a bare value at deploy and
958
- * re-synced by the post-field-op guard refresh.
1437
+ * to workflow fields. Each value is a deploy-time read — a typed
1438
+ * {@link GuardRead} when authoring, the printed string spelling once
1439
+ * stored — resolved into a bare value at deploy and re-synced by the
1440
+ * post-field-op guard refresh.
959
1441
  */
960
- readonly metadata: v.OptionalSchema<
1442
+ metadata: v.OptionalSchema<
961
1443
  v.RecordSchema<
962
1444
  v.SchemaWithPipe<
963
1445
  readonly [
@@ -991,26 +1473,19 @@ declare type ManualTarget = v.InferOutput<typeof StoredManualTargetSchema>;
991
1473
  * { body, actor, at }` (the `actor`/`at` sub-fields match the `audit` op's
992
1474
  * stamp names, so it pairs with it). Never a stored kind.
993
1475
  */
994
- declare type NotesField = SlotFields<AuthoringEditable> & {
1476
+ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
995
1477
  type: "notes";
996
1478
  };
997
1479
 
998
1480
  declare type Op = v.InferOutput<typeof StoredOpSchema>;
999
1481
 
1000
- declare type OpPredicateInternal =
1001
- | {
1002
- type: "field";
1003
- field: string;
1004
- equals: ValueExpr;
1005
- }
1006
- | {
1007
- type: "all";
1008
- of: OpPredicateInternal[];
1009
- }
1010
- | {
1011
- type: "any";
1012
- of: OpPredicateInternal[];
1013
- };
1482
+ /**
1483
+ * Names an author's predicate may not use — engine-owned and author names
1484
+ * share one namespace, so a predicate redefining a binding would silently
1485
+ * shadow engine behaviour. Rejected at deploy; derived from
1486
+ * {@link CONDITION_VARS}.
1487
+ */
1488
+ export declare const RESERVED_CONDITION_VARS: readonly string[];
1014
1489
 
1015
1490
  declare type RoleAliases = v.InferOutput<typeof RoleAliasesSchema>;
1016
1491
 
@@ -1069,38 +1544,35 @@ declare const RoleAliasesSchema: v.RecordSchema<
1069
1544
  undefined
1070
1545
  >;
1071
1546
 
1072
- /** Type-mirror of {@link slotFields}, parameterised over the `editable` grammar. */
1073
- declare type SlotFields<TEditable> = {
1074
- name: string;
1075
- title?: string | undefined;
1076
- description?: string | undefined;
1077
- required?: boolean | undefined;
1078
- initialValue?: FieldSource | undefined;
1079
- editable?: TEditable | undefined;
1080
- };
1081
-
1082
- declare type Stage = StageFields<FieldEntry, Activity, Transition, Editable>;
1547
+ declare type Stage = StageFields<
1548
+ FieldEntry,
1549
+ Activity,
1550
+ Transition,
1551
+ Guard,
1552
+ Editable
1553
+ >;
1083
1554
 
1084
- /** Type-mirror of {@link stageFields}, parameterised over field/activity/transition/editable. */
1085
- declare type StageFields<TField, TActivity, TTransition, TEditable> = {
1555
+ /** Type-mirror of {@link stageFields}, parameterised over field/activity/transition/guard/editable. */
1556
+ declare type StageFields<TField, TActivity, TTransition, TGuard, TEditable> = {
1086
1557
  name: string;
1087
1558
  title?: string | undefined;
1088
1559
  description?: string | undefined;
1560
+ groups?: Group[] | undefined;
1089
1561
  activities?: TActivity[] | undefined;
1090
1562
  transitions?: TTransition[] | undefined;
1091
- guards?: Guard[] | undefined;
1563
+ guards?: TGuard[] | undefined;
1092
1564
  fields?: TField[] | undefined;
1093
1565
  editable?: Record<string, TEditable> | undefined;
1094
1566
  };
1095
1567
 
1096
1568
  /**
1097
- * Declared editability of a field slot — the generic edit seam's gate. Default
1098
- * (absent) is NOT editable: a slot is op-only engine working memory unless the
1569
+ * Declared editability of a field — the generic edit seam's gate. Default
1570
+ * (absent) is NOT editable: a field is op-only engine working memory unless the
1099
1571
  * modeler opens it. The stored form is `true` (editable by anyone within the
1100
- * slot's scope window) or a GROQ predicate over the rendered scope (`$actor`,
1572
+ * field's scope window) or an EDIT CONDITION rendered-scope GROQ (`$actor`,
1101
1573
  * `$can`, `$fields`, `$assigned`), checked like an action filter to decide
1102
1574
  * who-may-edit. ADVISORY like every engine gate — it disables the inline field
1103
- * and explains; real immutability needs a lake {@link Guard}.
1575
+ * and explains; a {@link Guard} declares the intended write-lock.
1104
1576
  */
1105
1577
  declare const StoredEditableSchema: v.UnionSchema<
1106
1578
  [
@@ -1210,7 +1682,12 @@ declare const StoredFieldOpSchema: v.VariantSchema<
1210
1682
  },
1211
1683
  undefined
1212
1684
  >;
1213
- readonly where: v.GenericSchema<OpPredicateInternal>;
1685
+ readonly where: v.SchemaWithPipe<
1686
+ readonly [
1687
+ v.StringSchema<undefined>,
1688
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
1689
+ ]
1690
+ >;
1214
1691
  readonly value: v.GenericSchema<ValueExprInternal>;
1215
1692
  },
1216
1693
  undefined
@@ -1233,7 +1710,12 @@ declare const StoredFieldOpSchema: v.VariantSchema<
1233
1710
  },
1234
1711
  undefined
1235
1712
  >;
1236
- readonly where: v.GenericSchema<OpPredicateInternal>;
1713
+ readonly where: v.SchemaWithPipe<
1714
+ readonly [
1715
+ v.StringSchema<undefined>,
1716
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
1717
+ ]
1718
+ >;
1237
1719
  },
1238
1720
  undefined
1239
1721
  >,
@@ -1368,7 +1850,12 @@ declare const StoredOpSchema: v.VariantSchema<
1368
1850
  },
1369
1851
  undefined
1370
1852
  >;
1371
- readonly where: v.GenericSchema<OpPredicateInternal>;
1853
+ readonly where: v.SchemaWithPipe<
1854
+ readonly [
1855
+ v.StringSchema<undefined>,
1856
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
1857
+ ]
1858
+ >;
1372
1859
  readonly value: v.GenericSchema<ValueExprInternal>;
1373
1860
  },
1374
1861
  undefined
@@ -1391,7 +1878,12 @@ declare const StoredOpSchema: v.VariantSchema<
1391
1878
  },
1392
1879
  undefined
1393
1880
  >;
1394
- readonly where: v.GenericSchema<OpPredicateInternal>;
1881
+ readonly where: v.SchemaWithPipe<
1882
+ readonly [
1883
+ v.StringSchema<undefined>,
1884
+ v.MinLengthAction<string, 1, "must be a non-empty string">,
1885
+ ]
1886
+ >;
1395
1887
  },
1396
1888
  undefined
1397
1889
  >,
@@ -1419,7 +1911,14 @@ declare type Subworkflows = v.InferOutput<typeof SubworkflowsSchema>;
1419
1911
 
1420
1912
  declare const SubworkflowsSchema: v.StrictObjectSchema<
1421
1913
  {
1422
- /** GROQ producing one row per subworkflow; each row binds as `$row`. */
1914
+ /**
1915
+ * GROQ producing one row per subworkflow; each row binds as `$row`. Every
1916
+ * row must carry an identity the engine can adopt against on re-entry:
1917
+ * `_key` ?? `_id` ?? GDR `id` for object rows (a GDR value — `{id, type}`
1918
+ * with a GDR-URI `id`, the rows a `doc.refs` field stores — keys on its
1919
+ * `id`; mint a `_key` in the projection for synthetic rows), the value
1920
+ * itself for scalar rows. A row without an identity fails the spawn.
1921
+ */
1423
1922
  readonly forEach: v.SchemaWithPipe<
1424
1923
  readonly [
1425
1924
  v.StringSchema<undefined>,
@@ -1495,6 +1994,23 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
1495
1994
  >,
1496
1995
  undefined
1497
1996
  >;
1997
+ /**
1998
+ * What happens to still-live children when their cohort's scope stops
1999
+ * applying — the spawning stage exits, or a re-entry's `forEach` no longer
2000
+ * discovers their row. `'detach'` (the default) lets them run to
2001
+ * completion outside the gate; `'abort'` kills them (recursively). The
2002
+ * engine never destroys in-flight work implicitly — `'abort'` is always
2003
+ * an authored choice. Note this governs only the CHILDREN's fate; whether
2004
+ * the parent may move at all is what gates (`completeWhen`, transition
2005
+ * filters over `$subworkflows`) decide.
2006
+ */
2007
+ readonly onExit: v.OptionalSchema<
2008
+ v.PicklistSchema<
2009
+ readonly ["detach", "abort"],
2010
+ `Invalid option: expected one of ${string}`
2011
+ >,
2012
+ undefined
2013
+ >;
1498
2014
  },
1499
2015
  undefined
1500
2016
  >;
@@ -1513,7 +2029,7 @@ declare type TerminalActivityStatus =
1513
2029
  * { label, status, assignee?, dueDate? }`; a plain checklist is this used with
1514
2030
  * `{label, status}` only (open ↔ done). Never a stored kind.
1515
2031
  */
1516
- declare type TodoListField = SlotFields<AuthoringEditable> & {
2032
+ declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
1517
2033
  type: "todoList";
1518
2034
  };
1519
2035
 
@@ -1534,8 +2050,6 @@ declare type TransitionFields<TOp> = {
1534
2050
 
1535
2051
  declare type TransitionOp = FieldOp;
1536
2052
 
1537
- declare type ValueExpr = ValueExprInternal;
1538
-
1539
2053
  declare type ValueExprInternal =
1540
2054
  | LiteralExpr
1541
2055
  | FieldReadExpr
@@ -1560,7 +2074,420 @@ declare type ValueExprInternal =
1560
2074
  fields: Record<string, ValueExprInternal>;
1561
2075
  };
1562
2076
 
1563
- declare const WORKFLOW_ROLES: readonly ["workflow", "child"];
2077
+ declare const WORKFLOW_LIFECYCLES: readonly ["standalone", "child"];
2078
+
2079
+ declare type WorkflowConfig = v.InferOutput<typeof WorkflowConfigSchema>;
2080
+
2081
+ declare const WorkflowConfigSchema: v.ObjectSchema<
2082
+ {
2083
+ readonly deployments: v.SchemaWithPipe<
2084
+ readonly [
2085
+ v.ArraySchema<
2086
+ v.ObjectSchema<
2087
+ {
2088
+ readonly name: v.SchemaWithPipe<
2089
+ readonly [
2090
+ v.StringSchema<undefined>,
2091
+ v.NonEmptyAction<string, "must not be empty">,
2092
+ ]
2093
+ >;
2094
+ readonly tag: v.SchemaWithPipe<
2095
+ readonly [
2096
+ v.StringSchema<undefined>,
2097
+ v.NonEmptyAction<string, undefined>,
2098
+ v.CheckAction<
2099
+ string,
2100
+ "invalid tag — lowercase letters, digits and dashes only, no leading dash, no dots"
2101
+ >,
2102
+ ]
2103
+ >;
2104
+ readonly workflowResource: v.VariantSchema<
2105
+ "type",
2106
+ [
2107
+ v.ObjectSchema<
2108
+ {
2109
+ readonly type: v.LiteralSchema<"dataset", undefined>;
2110
+ readonly id: v.SchemaWithPipe<
2111
+ readonly [
2112
+ v.SchemaWithPipe<
2113
+ readonly [
2114
+ v.StringSchema<undefined>,
2115
+ v.NonEmptyAction<string, "must not be empty">,
2116
+ ]
2117
+ >,
2118
+ v.CheckAction<
2119
+ string,
2120
+ 'invalid dataset resource id — expected "<projectId>.<dataset>"'
2121
+ >,
2122
+ ]
2123
+ >;
2124
+ },
2125
+ undefined
2126
+ >,
2127
+ v.ObjectSchema<
2128
+ {
2129
+ readonly type: v.LiteralSchema<"canvas", undefined>;
2130
+ readonly id: v.SchemaWithPipe<
2131
+ readonly [
2132
+ v.StringSchema<undefined>,
2133
+ v.NonEmptyAction<string, "must not be empty">,
2134
+ ]
2135
+ >;
2136
+ },
2137
+ undefined
2138
+ >,
2139
+ v.ObjectSchema<
2140
+ {
2141
+ readonly type: v.LiteralSchema<
2142
+ "media-library",
2143
+ undefined
2144
+ >;
2145
+ readonly id: v.SchemaWithPipe<
2146
+ readonly [
2147
+ v.StringSchema<undefined>,
2148
+ v.NonEmptyAction<string, "must not be empty">,
2149
+ ]
2150
+ >;
2151
+ },
2152
+ undefined
2153
+ >,
2154
+ v.ObjectSchema<
2155
+ {
2156
+ readonly type: v.LiteralSchema<"dashboard", undefined>;
2157
+ readonly id: v.SchemaWithPipe<
2158
+ readonly [
2159
+ v.StringSchema<undefined>,
2160
+ v.NonEmptyAction<string, "must not be empty">,
2161
+ ]
2162
+ >;
2163
+ },
2164
+ undefined
2165
+ >,
2166
+ ],
2167
+ undefined
2168
+ >;
2169
+ readonly resourceAliases: v.OptionalSchema<
2170
+ v.SchemaWithPipe<
2171
+ readonly [
2172
+ v.ArraySchema<
2173
+ v.ObjectSchema<
2174
+ {
2175
+ readonly name: v.SchemaWithPipe<
2176
+ readonly [
2177
+ v.SchemaWithPipe<
2178
+ readonly [
2179
+ v.StringSchema<undefined>,
2180
+ v.NonEmptyAction<string, "must not be empty">,
2181
+ ]
2182
+ >,
2183
+ v.CheckAction<
2184
+ string,
2185
+ "invalid resource handle name — lowercase letters, digits and dashes only, no leading dash"
2186
+ >,
2187
+ ]
2188
+ >;
2189
+ readonly resource: v.VariantSchema<
2190
+ "type",
2191
+ [
2192
+ v.ObjectSchema<
2193
+ {
2194
+ readonly type: v.LiteralSchema<
2195
+ "dataset",
2196
+ undefined
2197
+ >;
2198
+ readonly id: v.SchemaWithPipe<
2199
+ readonly [
2200
+ v.SchemaWithPipe<
2201
+ readonly [
2202
+ v.StringSchema<undefined>,
2203
+ v.NonEmptyAction<
2204
+ string,
2205
+ "must not be empty"
2206
+ >,
2207
+ ]
2208
+ >,
2209
+ v.CheckAction<
2210
+ string,
2211
+ 'invalid dataset resource id — expected "<projectId>.<dataset>"'
2212
+ >,
2213
+ ]
2214
+ >;
2215
+ },
2216
+ undefined
2217
+ >,
2218
+ v.ObjectSchema<
2219
+ {
2220
+ readonly type: v.LiteralSchema<
2221
+ "canvas",
2222
+ undefined
2223
+ >;
2224
+ readonly id: v.SchemaWithPipe<
2225
+ readonly [
2226
+ v.StringSchema<undefined>,
2227
+ v.NonEmptyAction<
2228
+ string,
2229
+ "must not be empty"
2230
+ >,
2231
+ ]
2232
+ >;
2233
+ },
2234
+ undefined
2235
+ >,
2236
+ v.ObjectSchema<
2237
+ {
2238
+ readonly type: v.LiteralSchema<
2239
+ "media-library",
2240
+ undefined
2241
+ >;
2242
+ readonly id: v.SchemaWithPipe<
2243
+ readonly [
2244
+ v.StringSchema<undefined>,
2245
+ v.NonEmptyAction<
2246
+ string,
2247
+ "must not be empty"
2248
+ >,
2249
+ ]
2250
+ >;
2251
+ },
2252
+ undefined
2253
+ >,
2254
+ v.ObjectSchema<
2255
+ {
2256
+ readonly type: v.LiteralSchema<
2257
+ "dashboard",
2258
+ undefined
2259
+ >;
2260
+ readonly id: v.SchemaWithPipe<
2261
+ readonly [
2262
+ v.StringSchema<undefined>,
2263
+ v.NonEmptyAction<
2264
+ string,
2265
+ "must not be empty"
2266
+ >,
2267
+ ]
2268
+ >;
2269
+ },
2270
+ undefined
2271
+ >,
2272
+ ],
2273
+ undefined
2274
+ >;
2275
+ },
2276
+ undefined
2277
+ >,
2278
+ undefined
2279
+ >,
2280
+ v.CheckAction<
2281
+ {
2282
+ name: string;
2283
+ resource:
2284
+ | {
2285
+ type: "dataset";
2286
+ id: string;
2287
+ }
2288
+ | {
2289
+ type: "canvas";
2290
+ id: string;
2291
+ }
2292
+ | {
2293
+ type: "media-library";
2294
+ id: string;
2295
+ }
2296
+ | {
2297
+ type: "dashboard";
2298
+ id: string;
2299
+ };
2300
+ }[],
2301
+ "duplicate resource handle name — each binding name must be unique within a deployment"
2302
+ >,
2303
+ ]
2304
+ >,
2305
+ undefined
2306
+ >;
2307
+ readonly definitions: v.SchemaWithPipe<
2308
+ readonly [
2309
+ v.ArraySchema<
2310
+ v.CustomSchema<
2311
+ {
2312
+ name: string;
2313
+ title: string;
2314
+ description?: string | undefined;
2315
+ groups?: Group[] | undefined;
2316
+ lifecycle?: WorkflowLifecycle | undefined;
2317
+ applicableWhen?: string | undefined;
2318
+ initialStage: string;
2319
+ fields?: FieldEntry[] | undefined;
2320
+ stages: Stage[];
2321
+ predicates?: Record<string, string> | undefined;
2322
+ roleAliases?: RoleAliases | undefined;
2323
+ },
2324
+ v.ErrorMessage<v.CustomIssue> | undefined
2325
+ >,
2326
+ undefined
2327
+ >,
2328
+ v.MinLengthAction<
2329
+ {
2330
+ name: string;
2331
+ title: string;
2332
+ description?: string | undefined;
2333
+ groups?: Group[] | undefined;
2334
+ lifecycle?: WorkflowLifecycle | undefined;
2335
+ applicableWhen?: string | undefined;
2336
+ initialStage: string;
2337
+ fields?: FieldEntry[] | undefined;
2338
+ stages: Stage[];
2339
+ predicates?: Record<string, string> | undefined;
2340
+ roleAliases?: RoleAliases | undefined;
2341
+ }[],
2342
+ 1,
2343
+ "a deployment needs at least one definition"
2344
+ >,
2345
+ ]
2346
+ >;
2347
+ },
2348
+ undefined
2349
+ >,
2350
+ undefined
2351
+ >,
2352
+ v.MinLengthAction<
2353
+ {
2354
+ name: string;
2355
+ tag: string;
2356
+ workflowResource:
2357
+ | {
2358
+ type: "dataset";
2359
+ id: string;
2360
+ }
2361
+ | {
2362
+ type: "canvas";
2363
+ id: string;
2364
+ }
2365
+ | {
2366
+ type: "media-library";
2367
+ id: string;
2368
+ }
2369
+ | {
2370
+ type: "dashboard";
2371
+ id: string;
2372
+ };
2373
+ resourceAliases?:
2374
+ | {
2375
+ name: string;
2376
+ resource:
2377
+ | {
2378
+ type: "dataset";
2379
+ id: string;
2380
+ }
2381
+ | {
2382
+ type: "canvas";
2383
+ id: string;
2384
+ }
2385
+ | {
2386
+ type: "media-library";
2387
+ id: string;
2388
+ }
2389
+ | {
2390
+ type: "dashboard";
2391
+ id: string;
2392
+ };
2393
+ }[]
2394
+ | undefined;
2395
+ definitions: {
2396
+ name: string;
2397
+ title: string;
2398
+ description?: string | undefined;
2399
+ groups?: Group[] | undefined;
2400
+ lifecycle?: WorkflowLifecycle | undefined;
2401
+ applicableWhen?: string | undefined;
2402
+ initialStage: string;
2403
+ fields?: FieldEntry[] | undefined;
2404
+ stages: Stage[];
2405
+ predicates?: Record<string, string> | undefined;
2406
+ roleAliases?: RoleAliases | undefined;
2407
+ }[];
2408
+ }[],
2409
+ 1,
2410
+ "a config needs at least one deployment"
2411
+ >,
2412
+ v.CheckAction<
2413
+ {
2414
+ name: string;
2415
+ tag: string;
2416
+ workflowResource:
2417
+ | {
2418
+ type: "dataset";
2419
+ id: string;
2420
+ }
2421
+ | {
2422
+ type: "canvas";
2423
+ id: string;
2424
+ }
2425
+ | {
2426
+ type: "media-library";
2427
+ id: string;
2428
+ }
2429
+ | {
2430
+ type: "dashboard";
2431
+ id: string;
2432
+ };
2433
+ resourceAliases?:
2434
+ | {
2435
+ name: string;
2436
+ resource:
2437
+ | {
2438
+ type: "dataset";
2439
+ id: string;
2440
+ }
2441
+ | {
2442
+ type: "canvas";
2443
+ id: string;
2444
+ }
2445
+ | {
2446
+ type: "media-library";
2447
+ id: string;
2448
+ }
2449
+ | {
2450
+ type: "dashboard";
2451
+ id: string;
2452
+ };
2453
+ }[]
2454
+ | undefined;
2455
+ definitions: {
2456
+ name: string;
2457
+ title: string;
2458
+ description?: string | undefined;
2459
+ groups?: Group[] | undefined;
2460
+ lifecycle?: WorkflowLifecycle | undefined;
2461
+ applicableWhen?: string | undefined;
2462
+ initialStage: string;
2463
+ fields?: FieldEntry[] | undefined;
2464
+ stages: Stage[];
2465
+ predicates?: Record<string, string> | undefined;
2466
+ roleAliases?: RoleAliases | undefined;
2467
+ }[];
2468
+ }[],
2469
+ "duplicate deployment tag — each deployment must use a unique tag"
2470
+ >,
2471
+ ]
2472
+ >;
2473
+ /**
2474
+ * Custom telemetry destination for the CLI. When set, the CLI's built-in
2475
+ * Sanity-intake shell is not constructed and none of its policy applies:
2476
+ * every event — the command trace and the engine vocabulary — flows to
2477
+ * this logger unconditionally (CI and `DO_NOT_TRACK` environments
2478
+ * included). Consent, environment suppression, transport, and destination
2479
+ * are wholly this implementation's business.
2480
+ */
2481
+ readonly telemetry: v.OptionalSchema<
2482
+ v.CustomSchema<
2483
+ WorkflowTelemetryLogger,
2484
+ v.ErrorMessage<v.CustomIssue> | undefined
2485
+ >,
2486
+ undefined
2487
+ >;
2488
+ },
2489
+ undefined
2490
+ >;
1564
2491
 
1565
2492
  declare type WorkflowDefinition = v.InferOutput<
1566
2493
  typeof WorkflowDefinitionSchema
@@ -1588,7 +2515,9 @@ declare type WorkflowFields<TField, TStage> = {
1588
2515
  name: string;
1589
2516
  title: string;
1590
2517
  description?: string | undefined;
1591
- role?: WorkflowRole | undefined;
2518
+ groups?: Group[] | undefined;
2519
+ lifecycle?: WorkflowLifecycle | undefined;
2520
+ applicableWhen?: string | undefined;
1592
2521
  initialStage: string;
1593
2522
  fields?: TField[] | undefined;
1594
2523
  stages: TStage[];
@@ -1596,7 +2525,40 @@ declare type WorkflowFields<TField, TStage> = {
1596
2525
  roleAliases?: RoleAliases | undefined;
1597
2526
  };
1598
2527
 
1599
- /** A definition's lifecycle role. `'child'` is spawn-only see {@link isStartableDefinition}. */
1600
- declare type WorkflowRole = (typeof WORKFLOW_ROLES)[number];
2528
+ /** How instances of a definition come to exist: started standalone (the
2529
+ * default) or spawned by a parent. `'child'` is spawn-only — see
2530
+ * {@link isStartableDefinition}. */
2531
+ declare type WorkflowLifecycle = (typeof WORKFLOW_LIFECYCLES)[number];
2532
+
2533
+ /**
2534
+ * A telemetry event descriptor — a structural mirror of `@sanity/telemetry`'s
2535
+ * `DefinedTelemetryLog`, so shells hand these straight to their store logger.
2536
+ */
2537
+ declare interface WorkflowTelemetryEvent<Data = void> {
2538
+ type: "log";
2539
+ /** Matched verbatim downstream — frozen once shipped. */
2540
+ name: string;
2541
+ /** Bumped on any payload shape change; the name never changes. */
2542
+ version: number;
2543
+ /** Optional to match the real package's event shape, so an event built
2544
+ * with the real `defineEvent` flows into this seam; the engine's own
2545
+ * vocabulary always sets it. */
2546
+ description?: string;
2547
+ /** Advisory volume cap enforced by the shell's store — at most one
2548
+ * submission per interval (ms). */
2549
+ maxSampleRate?: number;
2550
+ /** Type-level payload carrier — never set at runtime (the real package's
2551
+ * `defineEvent` leaves it unset the same way). */
2552
+ schema: Data;
2553
+ }
2554
+
2555
+ /**
2556
+ * The logger surface the engine emits through — the `log` subset of
2557
+ * `@sanity/telemetry`'s `TelemetryLogger`, so any real logger satisfies it.
2558
+ */
2559
+ declare interface WorkflowTelemetryLogger {
2560
+ log<Data>(event: WorkflowTelemetryEvent<Data>, data: Data): void;
2561
+ log(event: WorkflowTelemetryEvent<void>): void;
2562
+ }
1601
2563
 
1602
2564
  export {};