@sanity/workflow-engine 0.30.0 → 0.32.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.
@@ -1,6 +1,6 @@
1
1
  import * as v from "valibot";
2
2
 
3
- import { conditionOutcome, runGroq as runGroq$1, evaluateConditionOutcome as evaluateConditionOutcome$1 } from "@sanity/groq-condition-describe";
3
+ import { conditionOutcome, runGroq as runGroq$1, evaluateConditionOutcome as evaluateConditionOutcome$1, _exhaustiveOptions } from "@sanity/groq-condition-describe";
4
4
 
5
5
  import { parse } from "groq-js";
6
6
 
@@ -26,6 +26,37 @@ function driverKind(actor) {
26
26
  return actor.kind === "person" || actor.kind === "agent" ? actor.kind : "service";
27
27
  }
28
28
 
29
+ function isFilterScopedOut(entry) {
30
+ return entry.status === "skipped" && entry.startedAt === void 0;
31
+ }
32
+
33
+ function liveSubworkflows(host) {
34
+ return (host.subworkflows ?? []).filter(row => row.resolved === void 0);
35
+ }
36
+
37
+ function resolvedChildStatus(child) {
38
+ if (!(child.completedAt === void 0 || child.completedAt === null)) return child.abortedAt !== void 0 && child.abortedAt !== null ? "aborted" : "done";
39
+ }
40
+
41
+ function condemnedSubworkflows(host) {
42
+ return liveSubworkflows(host).filter(row => row.abortPending !== void 0);
43
+ }
44
+
45
+ function condemnSubworkflow(row, owed) {
46
+ row.abortPending !== void 0 || row.resolved !== void 0 || (row.abortPending = {
47
+ at: owed.at,
48
+ reason: owed.reason
49
+ });
50
+ }
51
+
52
+ function findOpenStageEntry(host) {
53
+ return host.stages.find(s => s.name === host.currentStage && s.exitedAt === void 0);
54
+ }
55
+
56
+ function findCurrentActivityEntry(host, activityName) {
57
+ return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
58
+ }
59
+
29
60
  function errorMessage(err) {
30
61
  return (err instanceof Error ? err.message : String(err)).replace(/[^\P{Cc}\n\t]/gu, "");
31
62
  }
@@ -485,8 +516,6 @@ function desugarWorkflow(authoring) {
485
516
  checkReservedRoleAliasKeys(authoring.roleAliases, issues);
486
517
  const roleAliases = normalizeRoleAliases(authoring.roleAliases), ctx = {
487
518
  issues: issues,
488
- claimFields: /* @__PURE__ */ new Map,
489
- claimedFields: /* @__PURE__ */ new Set,
490
519
  roleAliases: roleAliases
491
520
  }, workflowFields2 = desugarFieldEntries({
492
521
  entries: authoring.fields,
@@ -545,7 +574,7 @@ function desugarWorkflow(authoring) {
545
574
  } : {}
546
575
  };
547
576
  });
548
- return checkUnclaimedClaimFields(ctx), {
577
+ return {
549
578
  definition: {
550
579
  ...stripUndefined({
551
580
  name: authoring.name,
@@ -626,11 +655,6 @@ function desugarFieldEntries({entries: entries, path: path, ctx: ctx}) {
626
655
  }
627
656
 
628
657
  function desugarFieldEntry({entry: entry, path: path, ctx: ctx}) {
629
- if (entry.type === "claim") return desugarClaimField({
630
- entry: entry,
631
- path: path,
632
- ctx: ctx
633
- });
634
658
  if (entry.type === "todoList" || entry.type === "notes") return desugarListField({
635
659
  entry: entry,
636
660
  path: path,
@@ -661,22 +685,6 @@ function desugarFieldEntry({entry: entry, path: path, ctx: ctx}) {
661
685
  };
662
686
  }
663
687
 
664
- function desugarClaimField({entry: entry, path: path, ctx: ctx}) {
665
- const desugared = {
666
- ...stripUndefined({
667
- name: entry.name,
668
- title: entry.title,
669
- description: entry.description,
670
- group: normalizeGroup(entry.group)
671
- }),
672
- type: "actor"
673
- };
674
- return ctx.claimFields.set(desugared, {
675
- name: entry.name,
676
- path: path
677
- }), desugared;
678
- }
679
-
680
688
  function desugarListField({entry: entry, path: path, ctx: ctx}) {
681
689
  const editable = normalizeEditable({
682
690
  editable: entry.editable,
@@ -841,12 +849,6 @@ function desugarActionOps(args) {
841
849
  }
842
850
 
843
851
  function desugarAction({action: action, path: path, env: env, activityName: activityName, ctx: ctx}) {
844
- if ("type" in action) return desugarClaimAction({
845
- action: action,
846
- path: path,
847
- env: env,
848
- ctx: ctx
849
- });
850
852
  reportEmptyActionRoles({
851
853
  action: action,
852
854
  path: path,
@@ -883,67 +885,6 @@ function desugarAction({action: action, path: path, env: env, activityName: acti
883
885
  };
884
886
  }
885
887
 
886
- function desugarClaimAction({action: action, path: path, env: env, ctx: ctx}) {
887
- const ref = typeof action.field == "string" ? {
888
- field: action.field
889
- } : action.field, resolved = resolveRef({
890
- ref: ref,
891
- env: env,
892
- path: [ ...path, "field" ],
893
- ctx: ctx
894
- });
895
- if (resolved) {
896
- const entry = entryAt(env, resolved);
897
- entry && entry.type !== "actor" && ctx.issues.push({
898
- path: [ ...path, "field" ],
899
- message: `claim action "${action.name}" references "${resolved.field}" of kind "${entry.type}" — a claim pair needs an actor-valued entry (a "claim" or "actor" field declaration)`
900
- }), checkShadowedClaimTarget({
901
- actionName: action.name,
902
- field: ref.field,
903
- resolved: resolved,
904
- env: env,
905
- path: [ ...path, "field" ],
906
- ctx: ctx
907
- }), entry && ctx.claimedFields.add(entry);
908
- }
909
- const noSteal = `!defined($fields.${ref.field})`, filter = andConditions([ noSteal, rolesCondition(action.roles, ctx.roleAliases), action.filter ]), ops = resolved ? [ {
910
- type: "field.set",
911
- target: resolved,
912
- value: {
913
- type: "actor"
914
- }
915
- } ] : [];
916
- return {
917
- ...stripUndefined({
918
- name: action.name,
919
- title: action.title,
920
- description: action.description,
921
- group: normalizeGroup(action.group),
922
- params: action.params,
923
- effects: action.effects
924
- }),
925
- filter: filter,
926
- ...ops.length > 0 ? {
927
- ops: ops
928
- } : {}
929
- };
930
- }
931
-
932
- function checkShadowedClaimTarget({actionName: actionName, field: field, resolved: resolved, env: env, path: path, ctx: ctx}) {
933
- const nearest = env.layers.find(l => l.entries.has(field));
934
- nearest === void 0 || nearest.scope === resolved.scope || ctx.issues.push({
935
- path: path,
936
- message: `claim action "${actionName}" targets "${field}" at scope "${resolved.scope}", but a nearer ${nearest.scope}-scope entry of the same name shadows it in $fields — the no-steal filter would read the shadowing entry while the claim writes the "${resolved.scope}" one. Rename one of the entries or claim the nearer one`
937
- });
938
- }
939
-
940
- function checkUnclaimedClaimFields(ctx) {
941
- for (const [entry, {name: name, path: path}] of ctx.claimFields) ctx.claimedFields.has(entry) || ctx.issues.push({
942
- path: path,
943
- message: `claim field "${name}" is never referenced by a claim action — you announced the pattern and wrote half of it. Declare a defineAction({ type: "claim", field: "${name}" }) or use a raw actor entry`
944
- });
945
- }
946
-
947
888
  const DEFAULT_TRANSITION_WHEN = "$allActivitiesDone";
948
889
 
949
890
  function desugarTransition({transition: transition}) {
@@ -1243,13 +1184,23 @@ function walkAstNodes(node, visit) {
1243
1184
  }
1244
1185
  }
1245
1186
 
1246
- const ACTIVITY_STATUSES = [ "active", "done", "skipped", "failed" ], TERMINAL_ACTIVITY_STATUSES = [ "done", "skipped", "failed" ];
1187
+ const ACTIVITY_STATUSES = _exhaustiveOptions()([ "active", "done", "skipped", "failed" ]), TERMINAL_ACTIVITY_STATUSES = _exhaustiveOptions()([ "done", "skipped", "failed" ]);
1247
1188
 
1248
1189
  function isTerminalActivityStatus(status) {
1249
1190
  return TERMINAL_ACTIVITY_STATUSES.includes(status);
1250
1191
  }
1251
1192
 
1252
- const SIGNAL_SEMANTICS = [ "signal.positive", "signal.caution", "signal.critical" ], DECISION_SEMANTICS = [ "decision.accept", "decision.decline" ], ACTION_SEMANTICS = [ ...DECISION_SEMANTICS, ...SIGNAL_SEMANTICS ], FIELD_SCOPES = [ "workflow", "stage", "activity" ], DOCUMENT_VALUE_PERMISSIONS = [ "create", "read", "update" ], MUTATION_GUARD_ACTIONS = [ "create", "update", "delete", "publish", "unpublish" ], ACTIVITY_KINDS = [ "user", "service", "script", "manual", "receive" ], EXECUTOR_CLASSIFICATIONS = [ "autonomous", "interactive", "off-system", "hybrid" ], GROUP_KINDS = [ "core", "details" ], DRIVER_KINDS = [ "person", "agent", "service", "engine" ];
1193
+ const SIGNAL_SEMANTICS = [ "signal.positive", "signal.caution", "signal.critical" ], DECISION_SEMANTICS = [ "decision.accept", "decision.decline" ], ACTION_SEMANTICS = [ ...DECISION_SEMANTICS, ...SIGNAL_SEMANTICS ], FIELD_SCOPES = _exhaustiveOptions()([ "workflow", "stage", "activity" ]), DOCUMENT_VALUE_PERMISSIONS = [ "create", "manage", "read", "update" ], LAKE_MUTATION_GUARD_ACTIONS = _exhaustiveOptions()([ "create", "update", "delete" ]), MUTATION_GUARD_ACTIONS = _exhaustiveOptions()([ ...LAKE_MUTATION_GUARD_ACTIONS, "publish", "unpublish" ]), GUARD_ACTIONS_REQUIRED_MESSAGE = "a guard must match at least one action", MUTATION_GUARD_ID_SPACES = [ "authored", "edit", "published" ];
1194
+
1195
+ function mutationGuardActionIdSpace(action) {
1196
+ return action === "update" ? "edit" : action === "publish" || action === "unpublish" ? "published" : "authored";
1197
+ }
1198
+
1199
+ function mutationGuardRequiresSplitEmission(actions) {
1200
+ return new Set(actions.map(mutationGuardActionIdSpace)).size > 1;
1201
+ }
1202
+
1203
+ const ACTIVITY_KINDS = [ "user", "service", "script", "manual", "receive" ], EXECUTOR_CLASSIFICATIONS = [ "autonomous", "interactive", "off-system", "hybrid" ], GROUP_KINDS = [ "core", "details" ], DRIVER_KINDS = [ "person", "agent", "service", "engine" ];
1253
1204
 
1254
1205
  function releaseDocId(releaseName) {
1255
1206
  return `_.releases.${releaseName}`;
@@ -1265,7 +1216,7 @@ function releaseRef({res: res, releaseName: releaseName}) {
1265
1216
  }
1266
1217
 
1267
1218
  function isAlwaysArrayFieldKind(kind) {
1268
- return kind === "doc.refs" || kind === "assignees" || kind === "array";
1219
+ return kind === "doc.refs" || kind === "assignee" || kind === "assignees" || kind === "array";
1269
1220
  }
1270
1221
 
1271
1222
  function isSingleDocRefKind(kind) {
@@ -1420,6 +1371,9 @@ const CONDITION_VARS = [ {
1420
1371
  label: "the start's input fields",
1421
1372
  description: "The caller's input entries by name (`initialFields` — at `startInstance`, the values the start would seed; at a pre-flight, the values gathered so far, so a read of a not-yet-supplied entry is GROQ null). Document references bind as GDR envelopes — `$fields.<entry>.id` is the GDR URI, never a string authors assemble — a singular `doc.ref` or `subject` included (nothing hydrates at the gate or the pre-flight). Pathed reads are deploy-checked against these envelope shapes."
1422
1373
  } ], GUARD_PREDICATE_VARS = [ {
1374
+ name: "document",
1375
+ description: "The attempted mutation images, exposed as `document.before` and `document.after`."
1376
+ }, {
1423
1377
  name: "guard",
1424
1378
  description: "The guard document itself (its `metadata` carries deploy-time resolved values)."
1425
1379
  }, {
@@ -1553,7 +1507,65 @@ function documentIdOf(doc) {
1553
1507
  return "(unknown id)";
1554
1508
  }
1555
1509
 
1556
- const ACTOR_KINDS = [ "person", "agent", "system" ], ANONYMOUS_IDENTITY = "<anonymous>", SYSTEM_IDENTITY = "<system>", E_PREFIXED_PROJECT_ID = /^e-(.+)$/;
1510
+ const ACTOR_KINDS = [ "person", "agent", "system" ];
1511
+
1512
+ function normalizeAssignmentMembers(value) {
1513
+ return value === null ? [] : Array.isArray(value) ? value : [ value ];
1514
+ }
1515
+
1516
+ function assignmentMembers(entries) {
1517
+ return entries.flatMap(entry => isAssignmentFieldEntry(entry) ? normalizeAssignmentMembers(entry.value) : []);
1518
+ }
1519
+
1520
+ function assignmentState(members) {
1521
+ return members.length === 0 ? "unrouted" : members.some(member => member.type === "user") ? "held" : "routed";
1522
+ }
1523
+
1524
+ function activeAssignmentMembers(members) {
1525
+ const users = members.filter(member => member.type === "user");
1526
+ return users.length > 0 ? users : members;
1527
+ }
1528
+
1529
+ function assignmentMatch(members, identity) {
1530
+ const active = activeAssignmentMembers(members);
1531
+ return active.some(member => member.type === "user" && member.id === identity.userId) ? "user" : active.some(member => member.type === "role" && identity.roles.includes(member.role)) ? "role" : void 0;
1532
+ }
1533
+
1534
+ function identityMatchesAssignment(members, identity) {
1535
+ return assignmentMatch(members, identity) !== void 0;
1536
+ }
1537
+
1538
+ function assignmentStateCounts(assignments, identity) {
1539
+ const counts = {
1540
+ unrouted: 0,
1541
+ routed: 0,
1542
+ held: 0
1543
+ };
1544
+ for (const members of assignments) {
1545
+ const state = assignmentState(members);
1546
+ state === "unrouted" ? counts.unrouted += 1 : identityMatchesAssignment(members, identity) && (counts[state] += 1);
1547
+ }
1548
+ return counts;
1549
+ }
1550
+
1551
+ function openActivityAssignments(instance) {
1552
+ return (findOpenStageEntry(instance)?.activities ?? []).filter(activity => activity.status === "active").map(activity => assignmentMembers(activity.fields ?? []));
1553
+ }
1554
+
1555
+ function instanceAssignmentStateCounts(instance, identity) {
1556
+ return assignmentStateCounts(openActivityAssignments(instance), identity);
1557
+ }
1558
+
1559
+ function actorMatchesAssignment(args) {
1560
+ const actor = args.actor;
1561
+ return actor === void 0 ? !1 : activeAssignmentMembers(args.members).some(member => member.type === "user" ? member.id === actor.id : actorFulfillsRole({
1562
+ actorRoles: actor.roles,
1563
+ required: member.role,
1564
+ aliases: args.roleAliases
1565
+ }));
1566
+ }
1567
+
1568
+ const ANONYMOUS_IDENTITY = "<anonymous>", SYSTEM_IDENTITY = "<system>", E_PREFIXED_PROJECT_ID = /^e-(.+)$/;
1557
1569
 
1558
1570
  function classifyPrincipalId(id) {
1559
1571
  if (id === ANONYMOUS_IDENTITY || id === SYSTEM_IDENTITY) return {
@@ -1630,7 +1642,7 @@ const GdrUriSchema = v.custom(s => typeof s == "string" && isGdrUri(s), "must be
1630
1642
  }), tolerantObject()({
1631
1643
  type: v.literal("role"),
1632
1644
  role: NonEmptyString
1633
- }) ]), NullableString = v.union([ v.null(), v.string() ]), NullableNumber = v.union([ v.null(), v.number() ]), NullableBoolean = v.union([ v.null(), v.boolean() ]), NullableProgress = v.union([ v.null(), v.pipe(v.number(), v.finite("progress must be a finite number"), v.minValue(0, "progress must be at least 0"), v.maxValue(100, "progress must be at most 100")) ]), NullableDateTime = v.union([ v.null(), IsoTimestamp ]), NullableDate = v.union([ v.null(), v.pipe(v.string(), v.regex(/^\d{4}-\d{2}-\d{2}$/, "must be a `YYYY-MM-DD` date")) ]), NullableUrl = NullableString, CHOICE_KINDS = /* @__PURE__ */ new Set([ "string", "text", "number", "url", "date", "dueDate", "datetime", "dueDatetime", "dateTime" ]);
1645
+ }) ]), AssigneeListShape = v.pipe(v.union([ v.null(), AssigneeShape, v.array(AssigneeShape) ]), v.transform(normalizeAssignmentMembers)), NullableString = v.union([ v.null(), v.string() ]), NullableNumber = v.union([ v.null(), v.number() ]), NullableBoolean = v.union([ v.null(), v.boolean() ]), NullableProgress = v.union([ v.null(), v.pipe(v.number(), v.finite("progress must be a finite number"), v.minValue(0, "progress must be at least 0"), v.maxValue(100, "progress must be at most 100")) ]), NullableDateTime = v.union([ v.null(), IsoTimestamp ]), NullableDate = v.union([ v.null(), v.pipe(v.string(), v.regex(/^\d{4}-\d{2}-\d{2}$/, "must be a `YYYY-MM-DD` date")) ]), NullableUrl = NullableString, CHOICE_KINDS = /* @__PURE__ */ new Set([ "string", "text", "number", "url", "date", "dueDate", "datetime", "dueDatetime", "dateTime" ]);
1634
1646
 
1635
1647
  function normalizedChoiceKind(kind) {
1636
1648
  return kind === "dateTime" ? "datetime" : kind;
@@ -1670,7 +1682,7 @@ const fieldValueSchemas = {
1670
1682
  dueDatetime: NullableDateTime,
1671
1683
  url: NullableUrl,
1672
1684
  actor: v.union([ v.null(), ActorShape ]),
1673
- assignee: v.union([ v.null(), AssigneeShape ]),
1685
+ assignee: AssigneeListShape,
1674
1686
  assignees: v.array(AssigneeShape)
1675
1687
  }, WritePrincipalId = v.pipe(NonEmptyString, v.rawTransform(({dataset: dataset, addIssue: addIssue}) => {
1676
1688
  const classified = classifyPrincipalId(dataset.value);
@@ -1682,16 +1694,16 @@ const fieldValueSchemas = {
1682
1694
  id: WritePrincipalId,
1683
1695
  roles: v.exactOptional(v.array(v.string())),
1684
1696
  onBehalfOf: v.exactOptional(v.string())
1685
- }), AssigneeWriteShape = v.union([ tolerantObject()({
1697
+ }), AssigneePrincipalId = v.pipe(WritePrincipalId, v.check(id => classifyPrincipalId(id).namespace !== "robot", "robot principals cannot be assignment members")), AssigneeWriteShape = v.union([ tolerantObject()({
1686
1698
  type: v.literal("user"),
1687
- id: WritePrincipalId
1699
+ id: AssigneePrincipalId
1688
1700
  }), tolerantObject()({
1689
1701
  type: v.literal("role"),
1690
1702
  role: NonEmptyString
1691
- }) ]), valueSchemas = {
1703
+ }) ]), SingularAssigneeWriteShape = v.pipe(v.union([ AssigneeWriteShape, v.array(AssigneeWriteShape) ]), v.transform(normalizeAssignmentMembers), v.check(members => members.filter(member => member.type === "user").length <= 1, "must contain at most one user member")), valueSchemas = {
1692
1704
  ...fieldValueSchemas,
1693
1705
  actor: v.nullable(ActorWriteShape),
1694
- assignee: v.nullable(AssigneeWriteShape),
1706
+ assignee: SingularAssigneeWriteShape,
1695
1707
  assignees: v.array(AssigneeWriteShape),
1696
1708
  query: v.any()
1697
1709
  };
@@ -1782,7 +1794,7 @@ function appendItemSchema(entryType, shape) {
1782
1794
  leaf: valueSchemas
1783
1795
  });
1784
1796
  if (entryType === "doc.refs") return GdrShape;
1785
- if (entryType === "assignees") return AssigneeWriteShape;
1797
+ if (entryType === "assignee" || entryType === "assignees") return AssigneeWriteShape;
1786
1798
  }
1787
1799
 
1788
1800
  function rejectedRefTypes(args) {
@@ -1879,7 +1891,7 @@ function consumeRetainedAssignment(args) {
1879
1891
 
1880
1892
  function previousAssignmentIdentities(args) {
1881
1893
  const retained = /* @__PURE__ */ new Map;
1882
- if (args.previousValue === void 0 || args.entryType === "assignee") return retained;
1894
+ if (args.previousValue === void 0) return retained;
1883
1895
  const schema = wholeValueSchema({
1884
1896
  entryType: args.entryType,
1885
1897
  shape: args,
@@ -1922,7 +1934,7 @@ function visitAssignmentEntries(args, visit) {
1922
1934
 
1923
1935
  function visitAssignmentCandidates(args, visit) {
1924
1936
  if (args.roles === void 0) return;
1925
- const indexedValues = args.entryType === "assignees" && Array.isArray(args.value) ? args.value.map(value => ({
1937
+ const indexedValues = Array.isArray(args.value) ? args.value.map(value => ({
1926
1938
  value: value,
1927
1939
  path: args.path
1928
1940
  })) : [ {
@@ -1991,14 +2003,22 @@ function validateFieldValue(args) {
1991
2003
  return check.output;
1992
2004
  }
1993
2005
 
1994
- const BARE_ID_SOURCE = "[A-Za-z0-9_][A-Za-z0-9._-]*", BARE_ID_RE = new RegExp(`^${BARE_ID_SOURCE}$`), ALIAS_REF_RE = new RegExp(`^@${RESOURCE_ALIAS_NAME_SOURCE}:${BARE_ID_SOURCE}$`);
2006
+ const BARE_ID_SOURCE = "[A-Za-z0-9_][A-Za-z0-9._-]{0,127}", BARE_ID_RE = new RegExp(`^${BARE_ID_SOURCE}$`), ALIAS_REF_RE = new RegExp(`^@${RESOURCE_ALIAS_NAME_SOURCE}:${BARE_ID_SOURCE}$`);
2007
+
2008
+ function isBareDocumentId(id) {
2009
+ return BARE_ID_RE.test(id) && !id.includes("..");
2010
+ }
1995
2011
 
1996
2012
  function isAuthoringRefId(id) {
1997
- return id.startsWith("@") ? ALIAS_REF_RE.test(id) : id.includes(":") ? isGdrUri(id) : BARE_ID_RE.test(id);
2013
+ if (id.startsWith("@")) {
2014
+ const separator = id.indexOf(":");
2015
+ return ALIAS_REF_RE.test(id) && isBareDocumentId(id.slice(separator + 1));
2016
+ }
2017
+ return id.includes(":") ? isGdrUri(id) : isBareDocumentId(id);
1998
2018
  }
1999
2019
 
2000
2020
  function isBareSeedId(id) {
2001
- return BARE_ID_RE.test(id);
2021
+ return isBareDocumentId(id);
2002
2022
  }
2003
2023
 
2004
2024
  const AuthoringRefId = v.pipe(v.string(), v.check(isAuthoringRefId, "must be a bare document id, a GDR URI, or a portable `@<alias>:<id>` reference")), AuthoringGdrShape = v.looseObject({
@@ -2064,7 +2084,7 @@ function validateFieldAppendItem(args) {
2064
2084
  }
2065
2085
 
2066
2086
  function appendAssignmentEntryType(entryType) {
2067
- return entryType === "assignees" ? "assignee" : entryType === "array" ? "object" : entryType;
2087
+ return entryType === "assignee" || entryType === "assignees" ? "assignee" : entryType === "array" ? "object" : entryType;
2068
2088
  }
2069
2089
 
2070
2090
  function formatIssues(issues, formatMessage = issue => issue.message) {
@@ -2089,10 +2109,6 @@ function invalidOptionMessage(options) {
2089
2109
  return `Invalid option: expected one of ${options.map(option => `"${option}"`).join("|")}`;
2090
2110
  }
2091
2111
 
2092
- function exhaustiveOptions() {
2093
- return options => options;
2094
- }
2095
-
2096
2112
  function pinned() {
2097
2113
  return (schema, ..._exact) => schema;
2098
2114
  }
@@ -2152,7 +2168,7 @@ function manualTargetSchema(ref) {
2152
2168
  }) ]);
2153
2169
  }
2154
2170
 
2155
- const StoredManualTargetSchema = manualTargetSchema(StoredFieldRefSchema), AuthoringManualTargetSchema = manualTargetSchema(v.union([ NonEmpty, AuthoringFieldRefSchema ])), ConditionSchema = NonEmpty;
2171
+ const StoredManualTargetSchema = pinned()(manualTargetSchema(StoredFieldRefSchema)), AuthoringManualTargetSchema = pinned()(manualTargetSchema(v.union([ NonEmpty, AuthoringFieldRefSchema ]))), ConditionSchema = NonEmpty;
2156
2172
 
2157
2173
  function opSchemas(targetSchema) {
2158
2174
  return [ v.strictObject({
@@ -2190,11 +2206,11 @@ function opSchemas(targetSchema) {
2190
2206
  }) ];
2191
2207
  }
2192
2208
 
2193
- const StoredFieldOpSchema = v.variant("type", [ ...opSchemas(StoredFieldRefSchema) ]), StoredOpSchema = v.variant("type", [ ...opSchemas(StoredFieldRefSchema), v.strictObject({
2209
+ const StoredFieldOpSchema = pinned()(v.variant("type", [ ...opSchemas(StoredFieldRefSchema) ])), StoredOpSchema = pinned()(v.variant("type", [ ...opSchemas(StoredFieldRefSchema), v.strictObject({
2194
2210
  type: v.literal("status.set"),
2195
2211
  activity: NonEmpty,
2196
2212
  status: picklist(ACTIVITY_STATUSES)
2197
- }) ]), AuditOpSchema = v.strictObject({
2213
+ }) ])), AuditOpSchema = v.strictObject({
2198
2214
  type: v.literal("audit"),
2199
2215
  target: AuthoringFieldRefSchema,
2200
2216
  value: ValueExprSchema,
@@ -2202,11 +2218,11 @@ const StoredFieldOpSchema = v.variant("type", [ ...opSchemas(StoredFieldRefSchem
2202
2218
  actor: v.optional(NonEmpty),
2203
2219
  at: v.optional(NonEmpty)
2204
2220
  }))
2205
- }), AuthoringOpSchema = v.variant("type", [ ...opSchemas(AuthoringFieldRefSchema), v.strictObject({
2221
+ }), AuthoringOpSchema = pinned()(v.variant("type", [ ...opSchemas(AuthoringFieldRefSchema), v.strictObject({
2206
2222
  type: v.literal("status.set"),
2207
2223
  activity: v.optional(NonEmpty),
2208
2224
  status: picklist(ACTIVITY_STATUSES)
2209
- }), AuditOpSchema ]), GroupName = v.pipe(v.string(), v.regex(GROQ_IDENTIFIER, "must be an identifier (letters, digits, underscore; not starting with a digit)")), GroupSchema = pinned()(v.strictObject({
2225
+ }), AuditOpSchema ])), GroupName = v.pipe(v.string(), v.regex(GROQ_IDENTIFIER, "must be an identifier (letters, digits, underscore; not starting with a digit)")), GroupSchema = pinned()(v.strictObject({
2210
2226
  name: GroupName,
2211
2227
  title: v.optional(v.string()),
2212
2228
  description: v.optional(v.string()),
@@ -2217,7 +2233,7 @@ function groupMembershipNames(group) {
2217
2233
  return group === void 0 ? [] : typeof group == "string" ? [ group ] : [ ...group ];
2218
2234
  }
2219
2235
 
2220
- const FIELD_VALUE_KINDS = [ "doc.ref", "doc.refs", "subject", "release.ref", "string", "text", "number", "progress", "boolean", "date", "dueDate", "datetime", "dueDatetime", "url", "actor", "assignee", "assignees", "object", "array" ], FieldValueKindSchema = picklist(FIELD_VALUE_KINDS), FieldKindSchema = picklist(FIELD_VALUE_KINDS), AUTHORING_FIELD_SUGAR_KINDS = exhaustiveOptions()([ "claim", "todoList", "notes" ]), AUTHORING_FIELD_KINDS = [ ...FIELD_VALUE_KINDS, ...AUTHORING_FIELD_SUGAR_KINDS ], AuthoringRawFieldKindSchema = v.picklist(FIELD_VALUE_KINDS, issue => `${invalidOptionMessage(AUTHORING_FIELD_KINDS)} but received ${JSON.stringify(issue.input)}`), FieldEntryName = groqIdentifier("`$fields.<name>`"), FiniteNumber = v.pipe(v.number(), v.finite("must be finite")), ScalarValidationSchema = v.pipe(v.strictObject({
2236
+ const FIELD_VALUE_KINDS = [ "doc.ref", "doc.refs", "subject", "release.ref", "string", "text", "number", "progress", "boolean", "date", "dueDate", "datetime", "dueDatetime", "url", "actor", "assignee", "assignees", "object", "array" ], FieldValueKindSchema = picklist(FIELD_VALUE_KINDS), FieldKindSchema = picklist(FIELD_VALUE_KINDS), AUTHORING_FIELD_SUGAR_KINDS = _exhaustiveOptions()([ "todoList", "notes" ]), AUTHORING_FIELD_KINDS = [ ...FIELD_VALUE_KINDS, ...AUTHORING_FIELD_SUGAR_KINDS ], AuthoringRawFieldKindSchema = v.picklist(FIELD_VALUE_KINDS, issue => `${invalidOptionMessage(AUTHORING_FIELD_KINDS)} but received ${JSON.stringify(issue.input)}`), FieldEntryName = groqIdentifier("`$fields.<name>`"), FiniteNumber = v.pipe(v.number(), v.finite("must be finite")), ScalarValidationSchema = v.pipe(v.strictObject({
2221
2237
  min: v.optional(FiniteNumber),
2222
2238
  max: v.optional(FiniteNumber)
2223
2239
  }), v.check(validation => validation.min !== void 0 || validation.max !== void 0, "declare at least one bound, or omit `validation`"), v.check(validation => validation.min === void 0 || validation.max === void 0 || validation.min <= validation.max, "`min` must be less than or equal to `max`")), ChoiceOptionsSchema = v.strictObject({
@@ -2269,7 +2285,7 @@ const AssignmentRolesSchema = v.pipe(v.array(NonEmpty), v.minLength(1, "declare
2269
2285
  roles: v.optional(AssignmentRolesSchema),
2270
2286
  fields: v.optional(v.array(FieldShapeSchema)),
2271
2287
  of: v.optional(v.array(FieldShapeSchema))
2272
- }), choiceOptionsCheck(), scalarValidationCheck(), assignmentRolesCheck())), StoredEditableSchema = v.union([ v.literal(!0), NonEmpty ]), AuthoringEditableSchema = v.union([ v.literal(!0), v.array(NonEmpty), NonEmpty ]);
2288
+ }), choiceOptionsCheck(), scalarValidationCheck(), assignmentRolesCheck())), StoredEditableSchema = pinned()(v.union([ v.literal(!0), NonEmpty ])), AuthoringEditableSchema = pinned()(v.union([ v.literal(!0), v.array(NonEmpty), NonEmpty ]));
2273
2289
 
2274
2290
  function fieldBase(editable, group) {
2275
2291
  return {
@@ -2359,13 +2375,7 @@ const FieldEntrySchema = pinned()(v.pipe(compositeChecked(fieldEntryFields({
2359
2375
  editable: AuthoringEditableSchema,
2360
2376
  group: AuthoringGroupMembershipSchema,
2361
2377
  kind: AuthoringRawFieldKindSchema
2362
- })), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), ClaimFieldSchema = pinned()(v.strictObject({
2363
- type: v.literal("claim"),
2364
- name: FieldEntryName,
2365
- title: v.optional(v.string()),
2366
- description: v.optional(v.string()),
2367
- group: v.optional(AuthoringGroupMembershipSchema)
2368
- }));
2378
+ })), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck()));
2369
2379
 
2370
2380
  function listSugarFields(type) {
2371
2381
  return {
@@ -2376,7 +2386,7 @@ function listSugarFields(type) {
2376
2386
 
2377
2387
  const TodoListFieldSchema = pinned()(v.strictObject(listSugarFields("todoList"))), NotesFieldSchema = pinned()(v.strictObject(listSugarFields("notes"))), AuthoringFieldEntrySchema = pinned()(v.lazy(input => {
2378
2388
  const type = asShape(input).type;
2379
- return type === "claim" ? ClaimFieldSchema : type === "todoList" ? TodoListFieldSchema : type === "notes" ? NotesFieldSchema : RawAuthoringFieldEntrySchema;
2389
+ return type === "todoList" ? TodoListFieldSchema : type === "notes" ? NotesFieldSchema : RawAuthoringFieldEntrySchema;
2380
2390
  })), EffectSchema = v.strictObject({
2381
2391
  name: NonEmpty,
2382
2392
  title: v.optional(v.string()),
@@ -2441,18 +2451,7 @@ const StoredActionSchema = pinned()(v.strictObject({
2441
2451
  ...actionFields(AuthoringOpSchema, AuthoringGroupMembershipSchema),
2442
2452
  roles: v.optional(v.array(NonEmpty)),
2443
2453
  status: v.optional(TerminalActivityStatus)
2444
- })), ClaimActionSchema = pinned()(v.strictObject({
2445
- type: v.literal("claim"),
2446
- name: NonEmpty,
2447
- title: v.optional(v.string()),
2448
- description: v.optional(v.string()),
2449
- group: v.optional(AuthoringGroupMembershipSchema),
2450
- field: v.union([ NonEmpty, AuthoringFieldRefSchema ]),
2451
- roles: v.optional(v.array(NonEmpty)),
2452
- filter: v.optional(ConditionSchema),
2453
- params: v.optional(v.array(ActionParamSchema)),
2454
- effects: v.optional(v.array(EffectSchema))
2455
- })), AuthoringActionSchema = pinned()(v.lazy(input => typeof input == "object" && input !== null && "type" in input ? ClaimActionSchema : RawAuthoringActionSchema)), requirementBase = {
2454
+ })), AuthoringActionSchema = pinned()(RawAuthoringActionSchema), requirementBase = {
2456
2455
  name: NonEmpty,
2457
2456
  title: v.optional(v.string()),
2458
2457
  description: v.optional(v.string())
@@ -2503,7 +2502,7 @@ function transitionFields(when) {
2503
2502
  };
2504
2503
  }
2505
2504
 
2506
- const StoredTransitionSchema = pinned()(v.strictObject(transitionFields(ConditionSchema))), AuthoringTransitionSchema = pinned()(v.strictObject(transitionFields(v.optional(ConditionSchema)))), GuardActionSchema = picklist(MUTATION_GUARD_ACTIONS), GuardReadPath = v.pipe(NonEmpty, v.check(path => !/[\r\n\u2028\u2029]/.test(path), "a guard read path cannot contain a line break")), GuardReadSchema = v.variant("type", [ v.strictObject({
2505
+ const StoredTransitionSchema = pinned()(v.strictObject(transitionFields(ConditionSchema))), AuthoringTransitionSchema = pinned()(v.strictObject(transitionFields(v.optional(ConditionSchema)))), GuardActionSchema = picklist(MUTATION_GUARD_ACTIONS), GuardActionsSchema = v.array(GuardActionSchema), NonEmptyGuardActionsSchema = v.pipe(GuardActionsSchema, v.minLength(1, GUARD_ACTIONS_REQUIRED_MESSAGE)), GuardReadPath = v.pipe(NonEmpty, v.check(path => !/[\r\n\u2028\u2029]/.test(path), "a guard read path cannot contain a line break")), GuardReadSchema = pinned()(v.variant("type", [ v.strictObject({
2507
2506
  type: v.literal("self")
2508
2507
  }), v.strictObject({
2509
2508
  type: v.literal("now")
@@ -2515,29 +2514,29 @@ const StoredTransitionSchema = pinned()(v.strictObject(transitionFields(Conditio
2515
2514
  type: v.literal("effectsRead"),
2516
2515
  effect: v.pipe(NonEmpty, v.check(name => !name.includes("'"), "an effect name cannot contain `'`")),
2517
2516
  path: v.optional(GuardReadPath)
2518
- }) ]);
2517
+ }) ]));
2519
2518
 
2520
- function guardMatchFields(read) {
2519
+ function guardMatchFields(read, actions) {
2521
2520
  return {
2522
2521
  types: v.optional(v.array(NonEmpty)),
2523
2522
  idRefs: v.optional(v.array(read)),
2524
2523
  idPatterns: v.optional(v.array(NonEmpty)),
2525
- actions: v.pipe(v.array(GuardActionSchema), v.minLength(1, "a guard must match at least one action"))
2524
+ actions: actions
2526
2525
  };
2527
2526
  }
2528
2527
 
2529
- function guardFields(read) {
2528
+ function guardFields(read, actions) {
2530
2529
  return {
2531
2530
  name: NonEmpty,
2532
2531
  title: v.optional(v.string()),
2533
2532
  description: v.optional(v.string()),
2534
- match: v.strictObject(guardMatchFields(read)),
2533
+ match: v.strictObject(guardMatchFields(read, actions)),
2535
2534
  predicate: v.optional(v.string()),
2536
2535
  metadata: v.optional(v.record(NonEmpty, read))
2537
2536
  };
2538
2537
  }
2539
2538
 
2540
- const GuardSchema = v.strictObject(guardFields(NonEmpty)), AuthoringGuardSchema = v.strictObject(guardFields(GuardReadSchema));
2539
+ const GuardSchema = v.strictObject(guardFields(NonEmpty, GuardActionsSchema)), AuthoringGuardSchema = v.strictObject(guardFields(GuardReadSchema, NonEmptyGuardActionsSchema));
2541
2540
 
2542
2541
  function stageFields({field: field, activity: activity, transition: transition, guard: guard, editable: editable}) {
2543
2542
  return {
@@ -2566,7 +2565,7 @@ const StoredStageSchema = pinned()(v.strictObject(stageFields({
2566
2565
  transition: AuthoringTransitionSchema,
2567
2566
  guard: AuthoringGuardSchema,
2568
2567
  editable: AuthoringEditableSchema
2569
- }))), RoleAliasesSchema = v.record(NonEmpty, v.pipe(v.array(NonEmpty), v.minLength(1, "a role alias must list at least one fulfilling role"))), WORKFLOW_LIFECYCLES = [ "standalone", "child" ], START_KINDS = [ "interactive", "autonomous" ];
2568
+ }))), RoleAliasesSchema = pinned()(v.record(NonEmpty, v.pipe(v.array(NonEmpty), v.minLength(1, "a role alias must list at least one fulfilling role")))), WORKFLOW_LIFECYCLES = _exhaustiveOptions()([ "standalone", "child" ]), START_KINDS = _exhaustiveOptions()([ "interactive", "autonomous" ]);
2570
2569
 
2571
2570
  function startFields(kind) {
2572
2571
  return {
@@ -4017,4 +4016,4 @@ function checkWorkflowInvariants(def) {
4017
4016
  checkStoredRolesPlacement(def, issues), checkGroups(def, issues), issues;
4018
4017
  }
4019
4018
 
4020
- export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_STATUSES, ACTOR_KINDS, ANONYMOUS_IDENTITY, ActorShape, AuthoringActionSchema, AuthoringActivitySchema, AuthoringFieldEntrySchema, AuthoringGuardSchema, AuthoringOpSchema, AuthoringStageSchema, AuthoringTransitionSchema, AuthoringWorkflowSchema, CALLER_BOUND_VARS, CONDITION_VARS, ContractViolationError, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, DOCUMENT_VALUE_PERMISSIONS, DRIVER_KINDS, DefinitionInUseError, DefinitionNotFoundError, EFFECTS_READ, EXECUTOR_CLASSIFICATIONS, EffectNotFoundError, EffectSchema, FIELD_READ, FIELD_SCOPES, FIELD_VALUE_KINDS, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GUARD_PREDICATE_VARS, GdrShape, GroupSchema, InstanceNotFoundError, IsoTimestamp, MUTATION_GUARD_ACTIONS, NonEmptyString, PersistedDocShapeError, RESERVED_CONDITION_VARS, RESOURCE_ALIAS_NAME_SOURCE, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StoredFieldOpSchema, VersionSpecificDatasetGdrError, WORKFLOW_DEFINITION_TYPE, WorkflowConfigSchema, WorkflowError, actorFulfillsRole, andConditions, assignmentKindAcceptsRoles, checkWorkflowInvariants, choiceValueIssues, classifyPrincipalId, clientConfigFromResource, conditionEffectReads, conditionFieldReadNames, conditionParameterNames, conditionSyntaxIssues, datasetResourceParts, definitionDocId, deriveActivityKind, deriveExecutorClassification, desugarWorkflow, directoryBridgeId, driverKind, errorMessage, evaluateCondition, evaluateConditionOutcome, evaluatePredicates, extractDocumentId, fieldValueSchemas, firstCarriedGlobalId, formatIssuePath, formatIssues, formatValidationError, gdrFromResource, gdrRef, gdrResourcePrefix, gdrUri, groq, groupMembershipNames, isAlwaysArrayFieldKind, isAssignmentFieldEntry, isBareSeedId, isCascadeFired, isGdr, isGdrUri, isGuardReadExpr, isInputSourced, isNotesEntry, isParseableInstant, isRecord, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTerminalActivityStatus, isTodoListEntry, isTodoListItem, isUnevaluable, labelFor, lakePrincipalId, parseFieldValue, parseGdr, parseOrThrow, parsePersistedDoc, parseResourceGdr, parseStoredDefinition, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refTypeIssues, rejectedRefTypes, releaseDocId, releaseRef, resourceAliasesToMap, resourceFromGdrUri, resourceFromParsed, resourceGdr, rethrowWithContext, runGroq, sameResource, scalarValidationIssues, schemaTreeShape, selfGdr, startKindOf, tagScopeFilter, toBareId, toPhysicalGdr, tolerantEntries, tolerantObject, tryParseGdr, validateFieldAppendItem, validateFieldValue, validateResourceAliasName, validateTag };
4019
+ export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_STATUSES, ACTOR_KINDS, ANONYMOUS_IDENTITY, ActorShape, AuthoringActionSchema, AuthoringActivitySchema, AuthoringFieldEntrySchema, AuthoringGuardSchema, AuthoringOpSchema, AuthoringStageSchema, AuthoringTransitionSchema, AuthoringWorkflowSchema, CALLER_BOUND_VARS, CONDITION_VARS, ContractViolationError, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, DOCUMENT_VALUE_PERMISSIONS, DRIVER_KINDS, DefinitionInUseError, DefinitionNotFoundError, EFFECTS_READ, EXECUTOR_CLASSIFICATIONS, EffectNotFoundError, EffectSchema, FIELD_READ, FIELD_SCOPES, FIELD_VALUE_KINDS, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GUARD_ACTIONS_REQUIRED_MESSAGE, GUARD_PREDICATE_VARS, GdrShape, GroupSchema, InstanceNotFoundError, IsoTimestamp, LAKE_MUTATION_GUARD_ACTIONS, MUTATION_GUARD_ACTIONS, MUTATION_GUARD_ID_SPACES, NonEmptyString, PersistedDocShapeError, RESERVED_CONDITION_VARS, RESOURCE_ALIAS_NAME_SOURCE, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StoredFieldOpSchema, UNIVERSAL_ROLE_ALIAS_KEY, VersionSpecificDatasetGdrError, WORKFLOW_DEFINITION_TYPE, WorkflowConfigSchema, WorkflowError, activeAssignmentMembers, actorFulfillsRole, actorMatchesAssignment, andConditions, assignmentKindAcceptsRoles, assignmentMatch, assignmentMembers, assignmentState, assignmentStateCounts, checkWorkflowInvariants, choiceValueIssues, classifyPrincipalId, clientConfigFromResource, condemnSubworkflow, condemnedSubworkflows, conditionEffectReads, conditionFieldReadNames, conditionParameterNames, conditionSyntaxIssues, datasetResourceParts, definitionDocId, deriveActivityKind, deriveExecutorClassification, desugarWorkflow, directoryBridgeId, driverKind, errorMessage, evaluateCondition, evaluateConditionOutcome, evaluatePredicates, extractDocumentId, fieldValueSchemas, findCurrentActivityEntry, findOpenStageEntry, firstCarriedGlobalId, formatIssuePath, formatIssues, formatValidationError, gdrFromResource, gdrRef, gdrResourcePrefix, gdrUri, groq, groupMembershipNames, identityMatchesAssignment, instanceAssignmentStateCounts, isAlwaysArrayFieldKind, isAssignmentFieldEntry, isBareDocumentId, isBareSeedId, isCascadeFired, isFilterScopedOut, isGdr, isGdrUri, isGuardReadExpr, isInputSourced, isNotesEntry, isParseableInstant, isRecord, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTerminalActivityStatus, isTodoListEntry, isTodoListItem, isUnevaluable, labelFor, lakePrincipalId, liveSubworkflows, mutationGuardActionIdSpace, mutationGuardRequiresSplitEmission, normalizeAssignmentMembers, openActivityAssignments, parseFieldValue, parseGdr, parseOrThrow, parsePersistedDoc, parseResourceGdr, parseStoredDefinition, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refTypeIssues, rejectedRefTypes, releaseDocId, releaseRef, resolvedChildStatus, resourceAliasesToMap, resourceFromGdrUri, resourceFromParsed, resourceGdr, rethrowWithContext, runGroq, sameResource, scalarValidationIssues, schemaTreeShape, selfGdr, startKindOf, tagScopeFilter, toBareId, toPhysicalGdr, tolerantEntries, tolerantObject, tryParseGdr, validateFieldAppendItem, validateFieldValue, validateResourceAliasName, validateTag };