@sanity/workflow-engine 0.14.0 → 0.16.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.ts CHANGED
@@ -1,16 +1,22 @@
1
1
  import * as v from "valibot";
2
2
 
3
- declare type Action = ActionFields<Op>;
3
+ declare type Action = ActionFields<Op, string[]> & {
4
+ roles?: string[] | undefined;
5
+ };
4
6
 
5
- /** Type-mirror of {@link actionFields}, parameterised over the op grammar. */
6
- declare type ActionFields<TOp> = {
7
+ /** Type-mirror of {@link actionFields}, parameterised over the op and
8
+ * group-membership grammars. */
9
+ declare type ActionFields<TOp, TGroup> = {
7
10
  name: string;
8
11
  title?: string | undefined;
9
12
  description?: string | undefined;
13
+ group?: TGroup | undefined;
14
+ when?: string | undefined;
10
15
  filter?: string | undefined;
11
16
  params?: ActionParam[] | undefined;
12
17
  ops?: TOp[] | undefined;
13
18
  effects?: Effect[] | undefined;
19
+ spawn?: Subworkflows | undefined;
14
20
  };
15
21
 
16
22
  declare type ActionParam = v.InferOutput<typeof ActionParamSchema>;
@@ -53,44 +59,34 @@ declare const ActionParamSchema: v.StrictObjectSchema<
53
59
  undefined
54
60
  >;
55
61
 
56
- declare type Activity = ActivityFields<FieldEntry, Action, Op, ManualTarget>;
57
-
58
- declare const ACTIVITY_KINDS: readonly [
59
- "user",
60
- "service",
61
- "script",
62
- "manual",
63
- "receive",
64
- ];
62
+ declare type Activity = ActivityFields<
63
+ FieldEntry,
64
+ Action,
65
+ ManualTarget,
66
+ string[]
67
+ >;
65
68
 
66
- /** Type-mirror of {@link activityFields}, parameterised over field/action/op/target. */
67
- declare type ActivityFields<TField, TAction, TOp, TTarget> = {
69
+ /** Type-mirror of {@link activityFields}, parameterised over field/action/target/group. */
70
+ declare type ActivityFields<TField, TAction, TTarget, TGroup> = {
68
71
  name: string;
69
72
  title?: string | undefined;
70
73
  description?: string | undefined;
71
- kind?: ActivityKind | undefined;
74
+ groups?: Group[] | undefined;
75
+ group?: TGroup | undefined;
72
76
  target?: TTarget | undefined;
73
- activation?: "auto" | "manual" | undefined;
74
77
  filter?: string | undefined;
75
78
  requirements?: Record<string, string> | undefined;
76
- completeWhen?: string | undefined;
77
- failWhen?: string | undefined;
78
- ops?: TOp[] | undefined;
79
- effects?: Effect[] | undefined;
80
79
  actions?: TAction[] | undefined;
81
- subworkflows?: Subworkflows | undefined;
82
80
  fields?: TField[] | undefined;
83
81
  };
84
82
 
85
- declare type ActivityKind = (typeof ACTIVITY_KINDS)[number];
86
-
87
83
  declare type AuthoringAction = AuthoringRawAction | ClaimAction;
88
84
 
89
85
  declare type AuthoringActivity = ActivityFields<
90
86
  AuthoringFieldEntry,
91
87
  AuthoringAction,
92
- AuthoringOp,
93
- AuthoringManualTarget
88
+ AuthoringManualTarget,
89
+ GroupMembership
94
90
  >;
95
91
 
96
92
  declare type AuthoringEditable = v.InferOutput<typeof AuthoringEditableSchema>;
@@ -313,8 +309,8 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
313
309
  undefined
314
310
  >;
315
311
  /**
316
- * Lake GROQ predicate — a distinct eval context reading
317
- * `document.before`/`document.after`, `mutation`, `guard`, and
312
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
313
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
318
314
  * `identity()`. Bare ids/fields only. Omitted or empty means
319
315
  * UNCONDITIONAL DENY.
320
316
  */
@@ -648,7 +644,7 @@ declare const AuthoringOpSchema: v.VariantSchema<
648
644
  undefined
649
645
  >;
650
646
  readonly status: v.PicklistSchema<
651
- readonly ["pending", "active", "done", "skipped", "failed"],
647
+ readonly ["active", "done", "skipped", "failed"],
652
648
  `Invalid option: expected one of ${string}`
653
649
  >;
654
650
  },
@@ -713,23 +709,32 @@ declare const AuthoringOpSchema: v.VariantSchema<
713
709
  * Authoring action — the stored fields plus two field sugars with one
714
710
  * defined expansion each:
715
711
  *
716
- * - `roles` a `count($actor.roles[@ in [...]]) > 0` membership condition
717
- * ANDed with the authored `filter`. The definition's `roleAliases`
718
- * ({@link RoleAliasesSchema}) widen that membership at desugar time.
712
+ * - `roles` on a fireAction-fired action (no `when`) it desugars to a
713
+ * `count($actor.roles[@ in [...]]) > 0` membership condition ANDed with
714
+ * the authored `filter` (for a caller, "not yours to fire" and "doesn't
715
+ * exist for you" are the same advisory answer). On a CASCADE-FIRED
716
+ * action it stores VERBATIM — the pin on which identities may execute
717
+ * the trigger; folding it into `filter` would make the action's
718
+ * existence depend on whose token happens to cascade. The definition's
719
+ * `roleAliases` ({@link RoleAliasesSchema}) widen the membership either
720
+ * way.
719
721
  * - `status` → a `status.set` op on the firing activity, appended **after**
720
722
  * the authored ops (deliberately never implied: a forgotten explicit
721
723
  * `status` is a visible stall, an implied default silently completes
722
724
  * claim-like actions). Status is the health axis: a decision action
723
725
  * (decline, send back) resolves `done` and writes the decision into a
724
- * field the transition filter reads — `failed` is for work that
726
+ * field the transition trigger reads — `failed` is for work that
725
727
  * genuinely could not complete.
726
728
  */
727
- declare type AuthoringRawAction = ActionFields<AuthoringOp> & {
729
+ declare type AuthoringRawAction = ActionFields<AuthoringOp, GroupMembership> & {
728
730
  roles?: string[] | undefined;
729
731
  status?: TerminalActivityStatus | undefined;
730
732
  };
731
733
 
732
- declare type AuthoringRawFieldEntry = FieldEntryFields<AuthoringEditable>;
734
+ declare type AuthoringRawFieldEntry = FieldEntryFields<
735
+ AuthoringEditable,
736
+ GroupMembership
737
+ >;
733
738
 
734
739
  declare type AuthoringStage = StageFields<
735
740
  AuthoringFieldEntry,
@@ -739,216 +744,24 @@ declare type AuthoringStage = StageFields<
739
744
  AuthoringEditable
740
745
  >;
741
746
 
742
- declare type AuthoringTransition = TransitionFields<AuthoringTransitionOp> & {
743
- filter?: string | undefined;
747
+ declare type AuthoringStartBlock = StartFields & {
748
+ kind?: StartKind | undefined;
744
749
  };
745
750
 
746
- declare type AuthoringTransitionOp = v.InferOutput<
747
- typeof AuthoringTransitionOpSchema
748
- >;
749
-
750
751
  /**
751
- * Authoring transitions may omit `filter`; desugar fills the safe,
752
- * overwhelmingly-common gate `"$allActivitiesDone"`. "Fire unconditionally"
753
- * stays spellable as an explicit `filter: "true"`.
752
+ * Authoring transitions may omit `when`; desugar fills the safe,
753
+ * overwhelmingly-common trigger `"$allActivitiesDone"`. "Fire unconditionally"
754
+ * stays spellable as an explicit `when: "true"`.
754
755
  */
755
- declare const AuthoringTransitionOpSchema: v.VariantSchema<
756
- "type",
757
- [
758
- v.StrictObjectSchema<
759
- {
760
- readonly type: v.LiteralSchema<"field.set", undefined>;
761
- readonly target: v.StrictObjectSchema<
762
- {
763
- readonly scope: v.OptionalSchema<
764
- v.PicklistSchema<
765
- readonly ["workflow", "stage", "activity"],
766
- `Invalid option: expected one of ${string}`
767
- >,
768
- undefined
769
- >;
770
- readonly field: v.SchemaWithPipe<
771
- readonly [
772
- v.StringSchema<undefined>,
773
- v.MinLengthAction<string, 1, "must be a non-empty string">,
774
- ]
775
- >;
776
- },
777
- undefined
778
- >;
779
- readonly value: v.GenericSchema<ValueExprInternal>;
780
- },
781
- undefined
782
- >,
783
- v.StrictObjectSchema<
784
- {
785
- readonly type: v.LiteralSchema<"field.unset", undefined>;
786
- readonly target: v.StrictObjectSchema<
787
- {
788
- readonly scope: v.OptionalSchema<
789
- v.PicklistSchema<
790
- readonly ["workflow", "stage", "activity"],
791
- `Invalid option: expected one of ${string}`
792
- >,
793
- undefined
794
- >;
795
- readonly field: v.SchemaWithPipe<
796
- readonly [
797
- v.StringSchema<undefined>,
798
- v.MinLengthAction<string, 1, "must be a non-empty string">,
799
- ]
800
- >;
801
- },
802
- undefined
803
- >;
804
- },
805
- undefined
806
- >,
807
- v.StrictObjectSchema<
808
- {
809
- readonly type: v.LiteralSchema<"field.append", undefined>;
810
- readonly target: v.StrictObjectSchema<
811
- {
812
- readonly scope: v.OptionalSchema<
813
- v.PicklistSchema<
814
- readonly ["workflow", "stage", "activity"],
815
- `Invalid option: expected one of ${string}`
816
- >,
817
- undefined
818
- >;
819
- readonly field: v.SchemaWithPipe<
820
- readonly [
821
- v.StringSchema<undefined>,
822
- v.MinLengthAction<string, 1, "must be a non-empty string">,
823
- ]
824
- >;
825
- },
826
- undefined
827
- >;
828
- readonly value: v.GenericSchema<ValueExprInternal>;
829
- },
830
- undefined
831
- >,
832
- v.StrictObjectSchema<
833
- {
834
- readonly type: v.LiteralSchema<"field.updateWhere", undefined>;
835
- readonly target: v.StrictObjectSchema<
836
- {
837
- readonly scope: v.OptionalSchema<
838
- v.PicklistSchema<
839
- readonly ["workflow", "stage", "activity"],
840
- `Invalid option: expected one of ${string}`
841
- >,
842
- undefined
843
- >;
844
- readonly field: v.SchemaWithPipe<
845
- readonly [
846
- v.StringSchema<undefined>,
847
- v.MinLengthAction<string, 1, "must be a non-empty string">,
848
- ]
849
- >;
850
- },
851
- undefined
852
- >;
853
- readonly where: v.SchemaWithPipe<
854
- readonly [
855
- v.StringSchema<undefined>,
856
- v.MinLengthAction<string, 1, "must be a non-empty string">,
857
- ]
858
- >;
859
- readonly value: v.GenericSchema<ValueExprInternal>;
860
- },
861
- undefined
862
- >,
863
- v.StrictObjectSchema<
864
- {
865
- readonly type: v.LiteralSchema<"field.removeWhere", undefined>;
866
- readonly target: v.StrictObjectSchema<
867
- {
868
- readonly scope: v.OptionalSchema<
869
- v.PicklistSchema<
870
- readonly ["workflow", "stage", "activity"],
871
- `Invalid option: expected one of ${string}`
872
- >,
873
- undefined
874
- >;
875
- readonly field: v.SchemaWithPipe<
876
- readonly [
877
- v.StringSchema<undefined>,
878
- v.MinLengthAction<string, 1, "must be a non-empty string">,
879
- ]
880
- >;
881
- },
882
- undefined
883
- >;
884
- readonly where: v.SchemaWithPipe<
885
- readonly [
886
- v.StringSchema<undefined>,
887
- v.MinLengthAction<string, 1, "must be a non-empty string">,
888
- ]
889
- >;
890
- },
891
- undefined
892
- >,
893
- v.StrictObjectSchema<
894
- {
895
- readonly type: v.LiteralSchema<"audit", undefined>;
896
- readonly target: v.StrictObjectSchema<
897
- {
898
- readonly scope: v.OptionalSchema<
899
- v.PicklistSchema<
900
- readonly ["workflow", "stage", "activity"],
901
- `Invalid option: expected one of ${string}`
902
- >,
903
- undefined
904
- >;
905
- readonly field: v.SchemaWithPipe<
906
- readonly [
907
- v.StringSchema<undefined>,
908
- v.MinLengthAction<string, 1, "must be a non-empty string">,
909
- ]
910
- >;
911
- },
912
- undefined
913
- >;
914
- readonly value: v.GenericSchema<ValueExprInternal>;
915
- readonly stampFields: v.OptionalSchema<
916
- v.StrictObjectSchema<
917
- {
918
- readonly actor: v.OptionalSchema<
919
- v.SchemaWithPipe<
920
- readonly [
921
- v.StringSchema<undefined>,
922
- v.MinLengthAction<string, 1, "must be a non-empty string">,
923
- ]
924
- >,
925
- undefined
926
- >;
927
- readonly at: v.OptionalSchema<
928
- v.SchemaWithPipe<
929
- readonly [
930
- v.StringSchema<undefined>,
931
- v.MinLengthAction<string, 1, "must be a non-empty string">,
932
- ]
933
- >,
934
- undefined
935
- >;
936
- },
937
- undefined
938
- >,
939
- undefined
940
- >;
941
- },
942
- undefined
943
- >,
944
- ],
945
- undefined
946
- >;
756
+ declare type AuthoringTransition = TransitionFields & {
757
+ when?: string | undefined;
758
+ };
947
759
 
948
760
  /** The authoring surface: stored primitives plus the define-time sugar. */
949
761
  declare type AuthoringWorkflow = WorkflowFields<
950
762
  AuthoringFieldEntry,
951
- AuthoringStage
763
+ AuthoringStage,
764
+ AuthoringStartBlock
952
765
  >;
953
766
 
954
767
  /**
@@ -964,6 +777,7 @@ declare type ClaimAction = {
964
777
  name: string;
965
778
  title?: string | undefined;
966
779
  description?: string | undefined;
780
+ group?: GroupMembership | undefined;
967
781
  field: string | AuthoringFieldRef;
968
782
  roles?: string[] | undefined;
969
783
  filter?: string | undefined;
@@ -982,6 +796,7 @@ declare type ClaimField = {
982
796
  name: string;
983
797
  title?: string | undefined;
984
798
  description?: string | undefined;
799
+ group?: GroupMembership | undefined;
985
800
  };
986
801
 
987
802
  /**
@@ -997,27 +812,39 @@ export declare interface ConditionVar {
997
812
  name: string;
998
813
  binding: ConditionVarBinding;
999
814
  description: string;
815
+ /** Short human phrase for rendered explanations ("all activities in this
816
+ * stage are finished") — consumer-facing, unlike `description`. */
817
+ label: string;
1000
818
  }
1001
819
 
1002
820
  /**
1003
821
  * The condition-variable inventory — the single source of truth for every
1004
822
  * `$var` the engine binds when it evaluates a {@link Condition}.
1005
823
  *
1006
- * Three evaluation contexts read a definition's GROQ:
824
+ * Four evaluation contexts read a definition's GROQ:
1007
825
  *
1008
826
  * 1. **Rendered condition scope** — every condition site in a definition
1009
- * (transition filters, `completeWhen`/`failWhen`, action filters, effect
1010
- * bindings, `subworkflows` reads, where-op `where`s, editability
1011
- * predicates, author predicates). {@link CONDITION_VARS} is its inventory;
1012
- * each entry's `binding` says when the var actually holds a value. The
827
+ * (transition `when`s, activity filters, action `when`s/filters, effect
828
+ * bindings, `spawn` reads, where-op `where`s, editability predicates,
829
+ * author predicates). {@link CONDITION_VARS} is its inventory; each
830
+ * entry's `binding` says when the var actually holds a value. The
1013
831
  * where-op context is the one closed subset — its bound set is statically
1014
832
  * fixed and deploy-enforced (see the op-where scope's param-name list in
1015
833
  * the op applier).
1016
- * 2. **Filter evaluation without a caller** — the engine's cascade evaluates
1017
- * transition filters and `completeWhen`/`failWhen` with no caller, so only
1018
- * the `'always'`-bound subset carries values there ({@link FILTER_SCOPE_VARS}).
1019
- * Caller-bound vars evaluate to `undefined` and fail closed.
1020
- * 3. **Guard predicates** NOT conditions. A lake mutation guard's
834
+ * 2. **Cascade gates** — transition `when`s, activity filters, and a
835
+ * cascade-fired action's `when`/`filter` must resolve identically no
836
+ * matter whose token drives the cascade, so only the `'always'`-bound
837
+ * subset carries values there ({@link FILTER_SCOPE_VARS}). Caller-bound
838
+ * vars fail closed`$assigned` binds its caller-free constant `false`,
839
+ * the rest evaluate to `undefined` — and deploy rejects them at these
840
+ * sites; a cascade-fired action's per-token gate is `roles`, never its
841
+ * conditions.
842
+ * 3. **The start-filter context** — a definition's `start.filter` evaluates
843
+ * against a CANDIDATE (no instance exists yet): the candidate document is
844
+ * the root, {@link START_FILTER_VARS} are the only bound vars, and
845
+ * `*[...]` reads the WORKFLOW resource's dataset. None of the rendered
846
+ * condition vars exist there.
847
+ * 4. **Guard predicates** — NOT conditions. A lake mutation guard's
1021
848
  * `predicate` is groq-js **delta-mode** GROQ over a document mutation:
1022
849
  * `before()`/`after()`/`identity()` are dialect natives, and the wire
1023
850
  * format binds the identifiers in {@link GUARD_PREDICATE_VARS}. None of
@@ -1031,7 +858,7 @@ export declare interface ConditionVar {
1031
858
  * - `'caller'` — rides the acting caller; without one the var is `undefined`
1032
859
  * (conditions referencing it fail closed). Author predicates may not read
1033
860
  * these — they pre-evaluate once per instance, caller-free.
1034
- * - `'spawn'` — bound only at `subworkflows` sites.
861
+ * - `'spawn'` — bound only at spawn sites (the per-row `$row`).
1035
862
  */
1036
863
  export declare type ConditionVarBinding = "always" | "caller" | "spawn";
1037
864
 
@@ -1055,6 +882,14 @@ export declare function defineField(
1055
882
  entry: AuthoringFieldEntry,
1056
883
  ): AuthoringFieldEntry;
1057
884
 
885
+ /**
886
+ * Validate and return a group declaration — advisory "what belongs together"
887
+ * metadata. Declared in a `groups` array (workflow root, stage, or activity);
888
+ * fields, activities, and actions join via `group`. The engine stores and
889
+ * deploy-checks groups but never acts on them.
890
+ */
891
+ export declare function defineGroup(group: Group): Group;
892
+
1058
893
  export declare function defineGuard(guard: AuthoringGuard): AuthoringGuard;
1059
894
 
1060
895
  export declare function defineOp(op: AuthoringOp): AuthoringOp;
@@ -1146,6 +981,27 @@ declare const EffectSchema: v.StrictObjectSchema<
1146
981
  v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>,
1147
982
  undefined
1148
983
  >;
984
+ /**
985
+ * The outputs this effect is allowed to produce, as typed {@link FieldShape}s
986
+ * (each `name` is an output key, read downstream as `$effects['<name>'].<key>`;
987
+ * an `array` output is an array of objects shaped by `of`).
988
+ *
989
+ * A STRICT allowlist: at completion the handler's returned `outputs` are
990
+ * validated against these shapes and an undeclared key — or a value that
991
+ * doesn't fit its shape — fails the completion (nothing is stored). Omitting
992
+ * `outputs` is an EMPTY allowlist: the effect produces nothing, so any returned
993
+ * output is rejected — the bound is universal, not opt-in.
994
+ * Why strict: outputs land on the instance document's `effectHistory`, so
995
+ * the allowlist keeps it bounded — a handler can't accidentally spread a
996
+ * whole API response
997
+ * into the instance — and the declared shapes let tooling (e.g. the simulator's
998
+ * drain UI) suggest an effect's exact output keys. Declaring outputs also
999
+ * powers the advisory deploy-time producer/consumer lint.
1000
+ */
1001
+ readonly outputs: v.OptionalSchema<
1002
+ v.ArraySchema<v.GenericSchema<FieldShape>, undefined>,
1003
+ undefined
1004
+ >;
1149
1005
  },
1150
1006
  undefined
1151
1007
  >;
@@ -1155,6 +1011,9 @@ declare const EffectSchema: v.StrictObjectSchema<
1155
1011
  * reference kinds, the actor/assignee identities, and the two compositional
1156
1012
  * kinds (`object` with named `fields`, `array` of objects shaped by `of`).
1157
1013
  * This is also the set a nested {@link FieldShape} sub-field may use.
1014
+ *
1015
+ * Exported (module-level, not package API) for the model-surface gate's
1016
+ * enum-value coverage test.
1158
1017
  */
1159
1018
  declare const FIELD_VALUE_KINDS: readonly [
1160
1019
  "doc.ref",
@@ -1174,28 +1033,32 @@ declare const FIELD_VALUE_KINDS: readonly [
1174
1033
  "array",
1175
1034
  ];
1176
1035
 
1177
- /** Type-mirror of {@link fieldBase}, parameterised over the `editable` grammar. */
1178
- declare type FieldBase<TEditable> = {
1036
+ /** Type-mirror of {@link fieldBase}, parameterised over the `editable` and
1037
+ * `group` grammars (stored membership is the canonical list form). */
1038
+ declare type FieldBase<TEditable, TGroup> = {
1179
1039
  name: string;
1180
1040
  title?: string | undefined;
1181
1041
  description?: string | undefined;
1042
+ group?: TGroup | undefined;
1182
1043
  required?: boolean | undefined;
1183
1044
  initialValue?: FieldSource | undefined;
1184
1045
  editable?: TEditable | undefined;
1185
1046
  };
1186
1047
 
1187
- declare type FieldEntry = FieldEntryFields<Editable>;
1048
+ declare type FieldEntry = FieldEntryFields<Editable, string[]>;
1188
1049
 
1189
1050
  /** Type-mirror of {@link fieldEntryFields}: a raw field entry of the given
1190
- * editability grammar. */
1191
- declare type FieldEntryFields<TEditable> = FieldBase<TEditable> & {
1051
+ * editability and group-membership grammars. */
1052
+ declare type FieldEntryFields<TEditable, TGroup> = FieldBase<
1053
+ TEditable,
1054
+ TGroup
1055
+ > & {
1192
1056
  type: FieldValueKind;
1057
+ types?: string[] | undefined;
1193
1058
  fields?: FieldShape[] | undefined;
1194
1059
  of?: FieldShape[] | undefined;
1195
1060
  };
1196
1061
 
1197
- declare type FieldOp = v.InferOutput<typeof StoredFieldOpSchema>;
1198
-
1199
1062
  declare type FieldReadExpr = {
1200
1063
  type: "fieldRead";
1201
1064
  scope?: "workflow" | "stage" | undefined;
@@ -1229,8 +1092,8 @@ declare type FieldSourceInternal =
1229
1092
  declare type FieldValueKind = (typeof FIELD_VALUE_KINDS)[number];
1230
1093
 
1231
1094
  /**
1232
- * The subset that holds a value when the engine evaluates filters without a
1233
- * caller (the cascade path: transition filters, `completeWhen`/`failWhen`).
1095
+ * The subset that holds a value in the cascade gates (transition `when`s,
1096
+ * activity filters, a cascade-fired action's `when`/`filter`).
1234
1097
  */
1235
1098
  export declare const FILTER_SCOPE_VARS: readonly string[];
1236
1099
 
@@ -1254,6 +1117,30 @@ export declare function groq(
1254
1117
  ...values: unknown[]
1255
1118
  ): string;
1256
1119
 
1120
+ /** Type-mirror of {@link GroupSchema} — one declared group. */
1121
+ declare type Group = {
1122
+ name: string;
1123
+ title?: string | undefined;
1124
+ description?: string | undefined;
1125
+ kind?: GroupKind | undefined;
1126
+ };
1127
+
1128
+ declare const GROUP_KINDS: readonly ["core", "details"];
1129
+
1130
+ declare type GroupKind = (typeof GROUP_KINDS)[number];
1131
+
1132
+ /**
1133
+ * Group membership — the declared group(s) a node belongs to. A reference
1134
+ * resolves lexically up the node's enclosing chain (host activity → stage →
1135
+ * workflow; an activity's OWN membership sees stage → workflow — a node is
1136
+ * never a member of a group only it declares). An empty list is an author
1137
+ * error (it would name no groups) — omit `group` instead, and each group is
1138
+ * listed once. Authoring accepts a bare name as convenience; the STORED form
1139
+ * is always a list, so `'seo'` and `['seo']` hash identically under content
1140
+ * addressing and lake-side reads see one shape.
1141
+ */
1142
+ declare type GroupMembership = string | string[];
1143
+
1257
1144
  declare type Guard = v.InferOutput<typeof GuardSchema>;
1258
1145
 
1259
1146
  /**
@@ -1340,8 +1227,8 @@ declare const GuardSchema: v.StrictObjectSchema<
1340
1227
  undefined
1341
1228
  >;
1342
1229
  /**
1343
- * Lake GROQ predicate — a distinct eval context reading
1344
- * `document.before`/`document.after`, `mutation`, `guard`, and
1230
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
1231
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
1345
1232
  * `identity()`. Bare ids/fields only. Omitted or empty means
1346
1233
  * UNCONDITIONAL DENY.
1347
1234
  */
@@ -1388,7 +1275,7 @@ declare type ManualTarget = v.InferOutput<typeof StoredManualTargetSchema>;
1388
1275
  * { body, actor, at }` (the `actor`/`at` sub-fields match the `audit` op's
1389
1276
  * stamp names, so it pairs with it). Never a stored kind.
1390
1277
  */
1391
- declare type NotesField = FieldBase<AuthoringEditable> & {
1278
+ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
1392
1279
  type: "notes";
1393
1280
  };
1394
1281
 
@@ -1472,6 +1359,7 @@ declare type StageFields<TField, TActivity, TTransition, TGuard, TEditable> = {
1472
1359
  name: string;
1473
1360
  title?: string | undefined;
1474
1361
  description?: string | undefined;
1362
+ groups?: Group[] | undefined;
1475
1363
  activities?: TActivity[] | undefined;
1476
1364
  transitions?: TTransition[] | undefined;
1477
1365
  guards?: TGuard[] | undefined;
@@ -1479,6 +1367,30 @@ declare type StageFields<TField, TActivity, TTransition, TGuard, TEditable> = {
1479
1367
  editable?: Record<string, TEditable> | undefined;
1480
1368
  };
1481
1369
 
1370
+ declare const START_KINDS: readonly ["interactive", "autonomous"];
1371
+
1372
+ declare type StartBlock = StartFields & {
1373
+ kind: StartKind;
1374
+ };
1375
+
1376
+ /** Type-mirror of {@link startFields}: how standalone runs of this workflow
1377
+ * begin. Stored requires `kind` (desugar fills the `'interactive'` default);
1378
+ * authoring may omit it — so each variant declares it. */
1379
+ declare type StartFields = {
1380
+ filter?: string | undefined;
1381
+ };
1382
+
1383
+ /**
1384
+ * Who initiates a standalone run of this workflow: a person picking it from a
1385
+ * start surface (`'interactive'`, the default) or a system reacting to a
1386
+ * document event (`'autonomous'`). PURE CLASSIFICATION — consumers use it to
1387
+ * shape their surfaces (hide autonomous workflows from human pickers, list
1388
+ * interactive ones for editors); `startInstance` is one verb and one code
1389
+ * path for every kind, and an interactive start of an autonomous workflow is
1390
+ * legal.
1391
+ */
1392
+ declare type StartKind = (typeof START_KINDS)[number];
1393
+
1482
1394
  /**
1483
1395
  * Declared editability of a field — the generic edit seam's gate. Default
1484
1396
  * (absent) is NOT editable: a field is op-only engine working memory unless the
@@ -1501,142 +1413,6 @@ declare const StoredEditableSchema: v.UnionSchema<
1501
1413
  undefined
1502
1414
  >;
1503
1415
 
1504
- /**
1505
- * The `field.*` subset — every mutation op EXCEPT `status.set`. Shared by the
1506
- * boundaries that write fields but must not set an activity status: a transition
1507
- * (its stage's activities are tearing down, so `status.set` has no coherent
1508
- * target) and an effect's completion (an effect is OUTSIDE the activity's own
1509
- * awaiting — it reports its result through fields, never by flipping a status;
1510
- * the activity/stage gate then reads those fields). The full {@link StoredOpSchema}
1511
- * (these plus `status.set`) is what actions and activity boundaries carry.
1512
- */
1513
- declare const StoredFieldOpSchema: v.VariantSchema<
1514
- "type",
1515
- [
1516
- v.StrictObjectSchema<
1517
- {
1518
- readonly type: v.LiteralSchema<"field.set", undefined>;
1519
- readonly target: v.StrictObjectSchema<
1520
- {
1521
- readonly scope: v.PicklistSchema<
1522
- readonly ["workflow", "stage", "activity"],
1523
- `Invalid option: expected one of ${string}`
1524
- >;
1525
- readonly field: v.SchemaWithPipe<
1526
- readonly [
1527
- v.StringSchema<undefined>,
1528
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1529
- ]
1530
- >;
1531
- },
1532
- undefined
1533
- >;
1534
- readonly value: v.GenericSchema<ValueExprInternal>;
1535
- },
1536
- undefined
1537
- >,
1538
- v.StrictObjectSchema<
1539
- {
1540
- readonly type: v.LiteralSchema<"field.unset", undefined>;
1541
- readonly target: v.StrictObjectSchema<
1542
- {
1543
- readonly scope: v.PicklistSchema<
1544
- readonly ["workflow", "stage", "activity"],
1545
- `Invalid option: expected one of ${string}`
1546
- >;
1547
- readonly field: v.SchemaWithPipe<
1548
- readonly [
1549
- v.StringSchema<undefined>,
1550
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1551
- ]
1552
- >;
1553
- },
1554
- undefined
1555
- >;
1556
- },
1557
- undefined
1558
- >,
1559
- v.StrictObjectSchema<
1560
- {
1561
- readonly type: v.LiteralSchema<"field.append", undefined>;
1562
- readonly target: v.StrictObjectSchema<
1563
- {
1564
- readonly scope: v.PicklistSchema<
1565
- readonly ["workflow", "stage", "activity"],
1566
- `Invalid option: expected one of ${string}`
1567
- >;
1568
- readonly field: v.SchemaWithPipe<
1569
- readonly [
1570
- v.StringSchema<undefined>,
1571
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1572
- ]
1573
- >;
1574
- },
1575
- undefined
1576
- >;
1577
- readonly value: v.GenericSchema<ValueExprInternal>;
1578
- },
1579
- undefined
1580
- >,
1581
- v.StrictObjectSchema<
1582
- {
1583
- readonly type: v.LiteralSchema<"field.updateWhere", undefined>;
1584
- readonly target: v.StrictObjectSchema<
1585
- {
1586
- readonly scope: v.PicklistSchema<
1587
- readonly ["workflow", "stage", "activity"],
1588
- `Invalid option: expected one of ${string}`
1589
- >;
1590
- readonly field: v.SchemaWithPipe<
1591
- readonly [
1592
- v.StringSchema<undefined>,
1593
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1594
- ]
1595
- >;
1596
- },
1597
- undefined
1598
- >;
1599
- readonly where: v.SchemaWithPipe<
1600
- readonly [
1601
- v.StringSchema<undefined>,
1602
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1603
- ]
1604
- >;
1605
- readonly value: v.GenericSchema<ValueExprInternal>;
1606
- },
1607
- undefined
1608
- >,
1609
- v.StrictObjectSchema<
1610
- {
1611
- readonly type: v.LiteralSchema<"field.removeWhere", undefined>;
1612
- readonly target: v.StrictObjectSchema<
1613
- {
1614
- readonly scope: v.PicklistSchema<
1615
- readonly ["workflow", "stage", "activity"],
1616
- `Invalid option: expected one of ${string}`
1617
- >;
1618
- readonly field: v.SchemaWithPipe<
1619
- readonly [
1620
- v.StringSchema<undefined>,
1621
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1622
- ]
1623
- >;
1624
- },
1625
- undefined
1626
- >;
1627
- readonly where: v.SchemaWithPipe<
1628
- readonly [
1629
- v.StringSchema<undefined>,
1630
- v.MinLengthAction<string, 1, "must be a non-empty string">,
1631
- ]
1632
- >;
1633
- },
1634
- undefined
1635
- >,
1636
- ],
1637
- undefined
1638
- >;
1639
-
1640
1416
  declare const StoredManualTargetSchema: v.VariantSchema<
1641
1417
  "type",
1642
1418
  [
@@ -1811,7 +1587,7 @@ declare const StoredOpSchema: v.VariantSchema<
1811
1587
  ]
1812
1588
  >;
1813
1589
  readonly status: v.PicklistSchema<
1814
- readonly ["pending", "active", "done", "skipped", "failed"],
1590
+ readonly ["active", "done", "skipped", "failed"],
1815
1591
  `Invalid option: expected one of ${string}`
1816
1592
  >;
1817
1593
  },
@@ -1825,7 +1601,14 @@ declare type Subworkflows = v.InferOutput<typeof SubworkflowsSchema>;
1825
1601
 
1826
1602
  declare const SubworkflowsSchema: v.StrictObjectSchema<
1827
1603
  {
1828
- /** GROQ producing one row per subworkflow; each row binds as `$row`. */
1604
+ /**
1605
+ * GROQ producing one row per subworkflow; each row binds as `$row`. Every
1606
+ * row must carry an identity the engine can adopt against on re-entry:
1607
+ * `_key` ?? `_id` ?? GDR `id` for object rows (a GDR value — `{id, type}`
1608
+ * with a GDR-URI `id`, the rows a `doc.refs` field stores — keys on its
1609
+ * `id`; mint a `_key` in the projection for synthetic rows), the value
1610
+ * itself for scalar rows. A row without an identity fails the spawn.
1611
+ */
1829
1612
  readonly forEach: v.SchemaWithPipe<
1830
1613
  readonly [
1831
1614
  v.StringSchema<undefined>,
@@ -1880,8 +1663,8 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
1880
1663
  >;
1881
1664
  /**
1882
1665
  * Extra values evaluated in the parent's rendered scope at spawn time and
1883
- * delivered into each subworkflow's `$effects` bag — the parent→child
1884
- * handoff, read exactly like an effect output.
1666
+ * delivered into each subworkflow's `$context` bag — the parent→child
1667
+ * handoff.
1885
1668
  */
1886
1669
  readonly context: v.OptionalSchema<
1887
1670
  v.RecordSchema<
@@ -1901,6 +1684,23 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
1901
1684
  >,
1902
1685
  undefined
1903
1686
  >;
1687
+ /**
1688
+ * What happens to still-live children when their cohort's scope stops
1689
+ * applying — the spawning stage exits, or a re-fire's `forEach` no longer
1690
+ * discovers their row. `'detach'` (the default) lets them run to
1691
+ * completion outside the gate; `'abort'` kills them (recursively). The
1692
+ * engine never destroys in-flight work implicitly — `'abort'` is always
1693
+ * an authored choice. Note this governs only the CHILDREN's fate; whether
1694
+ * the parent may move at all is what gates (conditions over
1695
+ * `$subworkflows`) decide.
1696
+ */
1697
+ readonly onExit: v.OptionalSchema<
1698
+ v.PicklistSchema<
1699
+ readonly ["detach", "abort"],
1700
+ `Invalid option: expected one of ${string}`
1701
+ >,
1702
+ undefined
1703
+ >;
1904
1704
  },
1905
1705
  undefined
1906
1706
  >;
@@ -1919,27 +1719,23 @@ declare type TerminalActivityStatus =
1919
1719
  * { label, status, assignee?, dueDate? }`; a plain checklist is this used with
1920
1720
  * `{label, status}` only (open ↔ done). Never a stored kind.
1921
1721
  */
1922
- declare type TodoListField = FieldBase<AuthoringEditable> & {
1722
+ declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
1923
1723
  type: "todoList";
1924
1724
  };
1925
1725
 
1926
- declare type Transition = TransitionFields<TransitionOp> & {
1927
- filter: string;
1726
+ declare type Transition = TransitionFields & {
1727
+ when: string;
1928
1728
  };
1929
1729
 
1930
- /** Type-mirror of {@link transitionFields} minus `filter` — stored requires it,
1730
+ /** Type-mirror of {@link transitionFields} minus `when` — stored requires it,
1931
1731
  * authoring omits it (desugar fills the default), so each variant declares it. */
1932
- declare type TransitionFields<TOp> = {
1732
+ declare type TransitionFields = {
1933
1733
  name: string;
1934
1734
  title?: string | undefined;
1935
1735
  description?: string | undefined;
1936
1736
  to: string;
1937
- ops?: TOp[] | undefined;
1938
- effects?: Effect[] | undefined;
1939
1737
  };
1940
1738
 
1941
- declare type TransitionOp = FieldOp;
1942
-
1943
1739
  declare type ValueExprInternal =
1944
1740
  | LiteralExpr
1945
1741
  | FieldReadExpr
@@ -2202,7 +1998,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2202
1998
  name: string;
2203
1999
  title: string;
2204
2000
  description?: string | undefined;
2001
+ groups?: Group[] | undefined;
2205
2002
  lifecycle?: WorkflowLifecycle | undefined;
2003
+ start?: StartBlock | undefined;
2206
2004
  initialStage: string;
2207
2005
  fields?: FieldEntry[] | undefined;
2208
2006
  stages: Stage[];
@@ -2218,7 +2016,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2218
2016
  name: string;
2219
2017
  title: string;
2220
2018
  description?: string | undefined;
2019
+ groups?: Group[] | undefined;
2221
2020
  lifecycle?: WorkflowLifecycle | undefined;
2021
+ start?: StartBlock | undefined;
2222
2022
  initialStage: string;
2223
2023
  fields?: FieldEntry[] | undefined;
2224
2024
  stages: Stage[];
@@ -2282,7 +2082,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2282
2082
  name: string;
2283
2083
  title: string;
2284
2084
  description?: string | undefined;
2085
+ groups?: Group[] | undefined;
2285
2086
  lifecycle?: WorkflowLifecycle | undefined;
2087
+ start?: StartBlock | undefined;
2286
2088
  initialStage: string;
2287
2089
  fields?: FieldEntry[] | undefined;
2288
2090
  stages: Stage[];
@@ -2340,7 +2142,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2340
2142
  name: string;
2341
2143
  title: string;
2342
2144
  description?: string | undefined;
2145
+ groups?: Group[] | undefined;
2343
2146
  lifecycle?: WorkflowLifecycle | undefined;
2147
+ start?: StartBlock | undefined;
2344
2148
  initialStage: string;
2345
2149
  fields?: FieldEntry[] | undefined;
2346
2150
  stages: Stage[];
@@ -2352,6 +2156,21 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2352
2156
  >,
2353
2157
  ]
2354
2158
  >;
2159
+ /**
2160
+ * Custom telemetry destination for the CLI. When set, the CLI's built-in
2161
+ * Sanity-intake shell is not constructed and none of its policy applies:
2162
+ * every event — the command trace and the engine vocabulary — flows to
2163
+ * this logger unconditionally (CI and `DO_NOT_TRACK` environments
2164
+ * included). Consent, environment suppression, transport, and destination
2165
+ * are wholly this implementation's business.
2166
+ */
2167
+ readonly telemetry: v.OptionalSchema<
2168
+ v.CustomSchema<
2169
+ WorkflowTelemetryLogger,
2170
+ v.ErrorMessage<v.CustomIssue> | undefined
2171
+ >,
2172
+ undefined
2173
+ >;
2355
2174
  },
2356
2175
  undefined
2357
2176
  >;
@@ -2374,15 +2193,17 @@ declare type WorkflowDefinition = v.InferOutput<
2374
2193
  * mints the next version.
2375
2194
  */
2376
2195
  declare const WorkflowDefinitionSchema: v.GenericSchema<
2377
- WorkflowFields<FieldEntry, Stage>
2196
+ WorkflowFields<FieldEntry, Stage, StartBlock>
2378
2197
  >;
2379
2198
 
2380
- /** Type-mirror of {@link workflowFields}, parameterised over field/stage. */
2381
- declare type WorkflowFields<TField, TStage> = {
2199
+ /** Type-mirror of {@link workflowFields}, parameterised over field/stage/start. */
2200
+ declare type WorkflowFields<TField, TStage, TStart> = {
2382
2201
  name: string;
2383
2202
  title: string;
2384
2203
  description?: string | undefined;
2204
+ groups?: Group[] | undefined;
2385
2205
  lifecycle?: WorkflowLifecycle | undefined;
2206
+ start?: TStart | undefined;
2386
2207
  initialStage: string;
2387
2208
  fields?: TField[] | undefined;
2388
2209
  stages: TStage[];
@@ -2395,4 +2216,35 @@ declare type WorkflowFields<TField, TStage> = {
2395
2216
  * {@link isStartableDefinition}. */
2396
2217
  declare type WorkflowLifecycle = (typeof WORKFLOW_LIFECYCLES)[number];
2397
2218
 
2219
+ /**
2220
+ * A telemetry event descriptor — a structural mirror of `@sanity/telemetry`'s
2221
+ * `DefinedTelemetryLog`, so shells hand these straight to their store logger.
2222
+ */
2223
+ declare interface WorkflowTelemetryEvent<Data = void> {
2224
+ type: "log";
2225
+ /** Matched verbatim downstream — frozen once shipped. */
2226
+ name: string;
2227
+ /** Bumped on any payload shape change; the name never changes. */
2228
+ version: number;
2229
+ /** Optional to match the real package's event shape, so an event built
2230
+ * with the real `defineEvent` flows into this seam; the engine's own
2231
+ * vocabulary always sets it. */
2232
+ description?: string;
2233
+ /** Advisory volume cap enforced by the shell's store — at most one
2234
+ * submission per interval (ms). */
2235
+ maxSampleRate?: number;
2236
+ /** Type-level payload carrier — never set at runtime (the real package's
2237
+ * `defineEvent` leaves it unset the same way). */
2238
+ schema: Data;
2239
+ }
2240
+
2241
+ /**
2242
+ * The logger surface the engine emits through — the `log` subset of
2243
+ * `@sanity/telemetry`'s `TelemetryLogger`, so any real logger satisfies it.
2244
+ */
2245
+ declare interface WorkflowTelemetryLogger {
2246
+ log<Data>(event: WorkflowTelemetryEvent<Data>, data: Data): void;
2247
+ log(event: WorkflowTelemetryEvent<void>): void;
2248
+ }
2249
+
2398
2250
  export {};