@sanity/workflow-engine 0.29.0 → 0.31.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.
@@ -55,79 +55,6 @@ function andConditions(parts) {
55
55
  if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
56
56
  }
57
57
 
58
- class WorkflowError extends Error {
59
- kind;
60
- constructor(kind, message, options) {
61
- super(message, options), this.kind = kind;
62
- }
63
- }
64
-
65
- class ContractViolationError extends WorkflowError {
66
- constructor(message) {
67
- super("contract-violation", message), this.name = "ContractViolationError";
68
- }
69
- }
70
-
71
- class InstanceNotFoundError extends WorkflowError {
72
- instanceId;
73
- constructor(args) {
74
- super("instance-not-found", `Workflow instance ${args.instanceId} not found${args.detail ? ` (${args.detail})` : ""}`),
75
- this.name = "InstanceNotFoundError", this.instanceId = args.instanceId;
76
- }
77
- }
78
-
79
- class DefinitionNotFoundError extends WorkflowError {
80
- definition;
81
- version;
82
- constructor(args) {
83
- super("definition-not-found", args.version !== void 0 ? `Workflow definition ${args.definition} v${args.version} not deployed` : `Workflow definition ${args.definition} has no deployed versions`),
84
- this.name = "DefinitionNotFoundError", this.definition = args.definition, args.version !== void 0 && (this.version = args.version);
85
- }
86
- }
87
-
88
- class SpawnContractsInvalidError extends WorkflowError {
89
- issues;
90
- constructor(args) {
91
- super("spawn-contracts-invalid", args.message), this.name = "SpawnContractsInvalidError",
92
- this.issues = args.issues;
93
- }
94
- }
95
-
96
- class DefinitionInUseError extends WorkflowError {
97
- definition;
98
- blockedBy;
99
- constructor(args) {
100
- super("definition-in-use", definitionInUseMessage(args.definition, args.blockedBy)),
101
- this.name = "DefinitionInUseError", this.definition = args.definition, this.blockedBy = args.blockedBy;
102
- }
103
- }
104
-
105
- function definitionInUseMessage(definition, blockedBy) {
106
- if (blockedBy.reason === "non-terminal-instances") {
107
- const head = blockedBy.instanceIds.slice(0, 3).join(", "), preview = blockedBy.instanceIds.length > 3 ? `${head}, …` : head;
108
- return `Cannot delete ${definition}: ${blockedBy.instanceIds.length} non-terminal instance(s) exist (${preview}). Pass cascade to abort them first — instances are aborted in place, never deleted.`;
109
- }
110
- const names = blockedBy.referrers.map(r => `${r.definition} v${r.version}`).join(", ");
111
- return `Cannot delete ${definition}: still spawn-referenced by deployed definition(s) ${names}. Delete or redeploy the referrer(s) first.`;
112
- }
113
-
114
- class EffectNotFoundError extends WorkflowError {
115
- instanceId;
116
- effectKey;
117
- settled;
118
- constructor(args) {
119
- super("effect-not-found", effectNotFoundMessage(args)), this.name = "EffectNotFoundError",
120
- this.instanceId = args.instanceId, this.effectKey = args.effectKey, args.settled !== void 0 && (this.settled = args.settled);
121
- }
122
- }
123
-
124
- function effectNotFoundMessage(args) {
125
- const base = `Pending effect "${args.effectKey}" not found on instance ${args.instanceId}`;
126
- if (args.settled === void 0) return base;
127
- const cause = args.settled.detail !== void 0 ? ` (${args.settled.detail})` : "";
128
- return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
129
- }
130
-
131
58
  const KNOWN_SCHEMES = /* @__PURE__ */ new Set([ "dataset", "canvas", "media-library", "dashboard" ]), KNOWN_SCHEMES_TEXT = [ ...KNOWN_SCHEMES ].join(", ");
132
59
 
133
60
  class VersionSpecificDatasetGdrError extends Error {
@@ -343,6 +270,79 @@ function isGdr(value) {
343
270
  return typeof value == "object" && value !== null && typeof value.id == "string" && typeof value.type == "string";
344
271
  }
345
272
 
273
+ class WorkflowError extends Error {
274
+ kind;
275
+ constructor(kind, message, options) {
276
+ super(message, options), this.kind = kind;
277
+ }
278
+ }
279
+
280
+ class ContractViolationError extends WorkflowError {
281
+ constructor(message) {
282
+ super("contract-violation", message), this.name = "ContractViolationError";
283
+ }
284
+ }
285
+
286
+ class InstanceNotFoundError extends WorkflowError {
287
+ instanceId;
288
+ constructor(args) {
289
+ super("instance-not-found", `Workflow instance ${args.instanceId} not found${args.detail ? ` (${args.detail})` : ""}`),
290
+ this.name = "InstanceNotFoundError", this.instanceId = args.instanceId;
291
+ }
292
+ }
293
+
294
+ class DefinitionNotFoundError extends WorkflowError {
295
+ definition;
296
+ version;
297
+ constructor(args) {
298
+ super("definition-not-found", args.version !== void 0 ? `Workflow definition ${args.definition} v${args.version} not deployed` : `Workflow definition ${args.definition} has no deployed versions`),
299
+ this.name = "DefinitionNotFoundError", this.definition = args.definition, args.version !== void 0 && (this.version = args.version);
300
+ }
301
+ }
302
+
303
+ class SpawnContractsInvalidError extends WorkflowError {
304
+ issues;
305
+ constructor(args) {
306
+ super("spawn-contracts-invalid", args.message), this.name = "SpawnContractsInvalidError",
307
+ this.issues = args.issues;
308
+ }
309
+ }
310
+
311
+ class DefinitionInUseError extends WorkflowError {
312
+ definition;
313
+ blockedBy;
314
+ constructor(args) {
315
+ super("definition-in-use", definitionInUseMessage(args.definition, args.blockedBy)),
316
+ this.name = "DefinitionInUseError", this.definition = args.definition, this.blockedBy = args.blockedBy;
317
+ }
318
+ }
319
+
320
+ function definitionInUseMessage(definition, blockedBy) {
321
+ if (blockedBy.reason === "non-terminal-instances") {
322
+ const head = blockedBy.instanceIds.slice(0, 3).join(", "), preview = blockedBy.instanceIds.length > 3 ? `${head}, …` : head;
323
+ return `Cannot delete ${definition}: ${blockedBy.instanceIds.length} non-terminal instance(s) exist (${preview}). Pass cascade to abort them first — instances are aborted in place, never deleted.`;
324
+ }
325
+ const names = blockedBy.referrers.map(r => `${r.definition} v${r.version}`).join(", ");
326
+ return `Cannot delete ${definition}: still spawn-referenced by deployed definition(s) ${names}. Delete or redeploy the referrer(s) first.`;
327
+ }
328
+
329
+ class EffectNotFoundError extends WorkflowError {
330
+ instanceId;
331
+ effectKey;
332
+ settled;
333
+ constructor(args) {
334
+ super("effect-not-found", effectNotFoundMessage(args)), this.name = "EffectNotFoundError",
335
+ this.instanceId = args.instanceId, this.effectKey = args.effectKey, args.settled !== void 0 && (this.settled = args.settled);
336
+ }
337
+ }
338
+
339
+ function effectNotFoundMessage(args) {
340
+ const base = `Pending effect "${args.effectKey}" not found on instance ${args.instanceId}`;
341
+ if (args.settled === void 0) return base;
342
+ const cause = args.settled.detail !== void 0 ? ` (${args.settled.detail})` : "";
343
+ return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
344
+ }
345
+
346
346
  const LAKE_ID_SEGMENT_RE = /^[a-z0-9][a-z0-9-]*$/, LAKE_ID_SEGMENT_GLOSS = "ASCII lowercase + digits + dashes, no leading dash, no dots";
347
347
 
348
348
  function validateTag(tag) {
@@ -668,6 +668,7 @@ function desugarFieldEntry({entry: entry, path: path, ctx: ctx}) {
668
668
  options: entry.options,
669
669
  validation: entry.validation,
670
670
  types: entry.types,
671
+ roles: entry.roles,
671
672
  fields: entry.fields,
672
673
  of: entry.of
673
674
  })
@@ -1289,10 +1290,18 @@ function refKindAcceptsTypes(kind) {
1289
1290
  return isSingleDocRefKind(kind) || kind === "doc.refs";
1290
1291
  }
1291
1292
 
1293
+ function assignmentKindAcceptsRoles(kind) {
1294
+ return kind === "assignee" || kind === "assignees";
1295
+ }
1296
+
1292
1297
  function isSingleDocRefEntry(entry) {
1293
1298
  return isSingleDocRefKind(entry._type);
1294
1299
  }
1295
1300
 
1301
+ function isAssignmentFieldEntry(entry) {
1302
+ return assignmentKindAcceptsRoles(entry._type);
1303
+ }
1304
+
1296
1305
  function isTodoListItem(row) {
1297
1306
  if (typeof row != "object" || row === null) return !1;
1298
1307
  const candidate = row, status = candidate.status;
@@ -1601,6 +1610,10 @@ function lakePrincipalId(args) {
1601
1610
  return args.localPrincipalId ?? args.actor.id;
1602
1611
  }
1603
1612
 
1613
+ function isRecord(value) {
1614
+ return typeof value == "object" && value !== null && !Array.isArray(value);
1615
+ }
1616
+
1604
1617
  class FieldValueShapeError extends WorkflowError {
1605
1618
  entryType;
1606
1619
  entryName;
@@ -1697,9 +1710,16 @@ const fieldValueSchemas = {
1697
1710
  query: v__namespace.any()
1698
1711
  };
1699
1712
 
1700
- function shapeValueSchema(shape, leaf) {
1701
- if (shape.type === "object") return objectSchema(shape.fields ?? [], leaf);
1702
- if (shape.type === "array") return v__namespace.array(objectSchema(shape.of ?? [], leaf));
1713
+ function shapeValueSchema(args) {
1714
+ const {shape: shape, leaf: leaf} = args;
1715
+ if (shape.type === "object") return objectSchema({
1716
+ fields: shape.fields ?? [],
1717
+ leaf: leaf
1718
+ });
1719
+ if (shape.type === "array") return v__namespace.array(objectSchema({
1720
+ fields: shape.of ?? [],
1721
+ leaf: leaf
1722
+ }));
1703
1723
  const schema = leaf[shape.type] ?? v__namespace.any();
1704
1724
  return constrainedScalarSchema({
1705
1725
  schema: schema,
@@ -1750,19 +1770,31 @@ function constrainedScalarSchema(args) {
1750
1770
  }) ?? [] ].join("; ")));
1751
1771
  }
1752
1772
 
1753
- function objectSchema(fields, leaf) {
1754
- const entries = /* @__PURE__ */ Object.create(null);
1755
- for (const f of fields) entries[f.name] = v__namespace.optional(shapeValueSchema(f, leaf));
1773
+ function objectSchema(args) {
1774
+ const {fields: fields, leaf: leaf} = args, entries = /* @__PURE__ */ Object.create(null);
1775
+ for (const f of fields) entries[f.name] = v__namespace.optional(shapeValueSchema({
1776
+ shape: f,
1777
+ leaf: leaf
1778
+ }));
1756
1779
  return v__namespace.looseObject(entries);
1757
1780
  }
1758
1781
 
1759
1782
  function wholeValueSchema(args) {
1760
1783
  const {entryType: entryType, shape: shape, leaf: leaf} = args;
1761
- return entryType === "object" ? v__namespace.union([ v__namespace.null(), objectSchema(shape.fields ?? [], leaf) ]) : entryType === "array" ? v__namespace.array(objectSchema(shape.of ?? [], leaf)) : leaf[entryType];
1784
+ return entryType === "object" ? v__namespace.union([ v__namespace.null(), objectSchema({
1785
+ fields: shape.fields ?? [],
1786
+ leaf: leaf
1787
+ }) ]) : entryType === "array" ? v__namespace.array(objectSchema({
1788
+ fields: shape.of ?? [],
1789
+ leaf: leaf
1790
+ })) : leaf[entryType];
1762
1791
  }
1763
1792
 
1764
1793
  function appendItemSchema(entryType, shape) {
1765
- if (entryType === "array") return objectSchema(shape.of ?? [], valueSchemas);
1794
+ if (entryType === "array") return objectSchema({
1795
+ fields: shape.of ?? [],
1796
+ leaf: valueSchemas
1797
+ });
1766
1798
  if (entryType === "doc.refs") return GdrShape;
1767
1799
  if (entryType === "assignees") return AssigneeWriteShape;
1768
1800
  }
@@ -1814,7 +1846,7 @@ function checkValueAgainst(args, leaf) {
1814
1846
  entryType: args.entryType,
1815
1847
  validation: args.validation,
1816
1848
  value: args.value
1817
- });
1849
+ }) ?? assignmentValueIssues(args, result.output);
1818
1850
  return postIssues !== void 0 ? {
1819
1851
  issues: postIssues
1820
1852
  } : {
@@ -1822,6 +1854,142 @@ function checkValueAgainst(args, leaf) {
1822
1854
  };
1823
1855
  }
1824
1856
 
1857
+ function assignmentIdentity(assignee) {
1858
+ return assignee.type === "user" ? `user:${assignee.id}` : `role:${assignee.role}`;
1859
+ }
1860
+
1861
+ function assignmentCandidate(value) {
1862
+ const parsed = v__namespace.safeParse(AssigneeShape, value);
1863
+ return parsed.success ? parsed.output : void 0;
1864
+ }
1865
+
1866
+ function assignmentValueIssues(args, value) {
1867
+ const retained = previousAssignmentIdentities(args), issues = [];
1868
+ return visitAssignmentEntries({
1869
+ entryType: args.entryType,
1870
+ value: value,
1871
+ roles: args.roles,
1872
+ fields: args.fields,
1873
+ of: args.of,
1874
+ path: "$"
1875
+ }, ({assignee: assignee, roles: roles, path: path}) => {
1876
+ consumeRetainedAssignment({
1877
+ retained: retained,
1878
+ path: path,
1879
+ identity: assignmentIdentity(assignee)
1880
+ }) || issues.push(...assignmentCandidateIssues({
1881
+ roles: roles,
1882
+ memberRoles: args.memberRoles,
1883
+ roleAliases: args.roleAliases
1884
+ }, assignee));
1885
+ }), issues.length === 0 ? void 0 : issues;
1886
+ }
1887
+
1888
+ function consumeRetainedAssignment(args) {
1889
+ const identities = args.retained.get(args.path), remaining = identities?.get(args.identity) ?? 0;
1890
+ return remaining === 0 || identities === void 0 ? !1 : (remaining === 1 ? identities.delete(args.identity) : identities.set(args.identity, remaining - 1),
1891
+ !0);
1892
+ }
1893
+
1894
+ function previousAssignmentIdentities(args) {
1895
+ const retained = /* @__PURE__ */ new Map;
1896
+ if (args.previousValue === void 0 || args.entryType === "assignee") return retained;
1897
+ const schema = wholeValueSchema({
1898
+ entryType: args.entryType,
1899
+ shape: args,
1900
+ leaf: valueSchemas
1901
+ });
1902
+ if (schema === void 0) return retained;
1903
+ const previous = v__namespace.safeParse(schema, args.previousValue);
1904
+ return previous.success && visitAssignmentEntries({
1905
+ entryType: args.entryType,
1906
+ value: previous.output,
1907
+ roles: args.roles,
1908
+ fields: args.fields,
1909
+ of: args.of,
1910
+ path: "$"
1911
+ }, ({assignee: assignee, path: path}) => {
1912
+ const identities = retained.get(path) ?? /* @__PURE__ */ new Map, identity = assignmentIdentity(assignee);
1913
+ identities.set(identity, (identities.get(identity) ?? 0) + 1), retained.set(path, identities);
1914
+ }), retained;
1915
+ }
1916
+
1917
+ function visitAssignmentEntries(args, visit) {
1918
+ if (assignmentKindAcceptsRoles(args.entryType)) {
1919
+ visitAssignmentCandidates(args, visit);
1920
+ return;
1921
+ }
1922
+ if (args.entryType === "object") {
1923
+ visitAssignmentFields({
1924
+ fields: args.fields,
1925
+ value: args.value,
1926
+ path: args.path
1927
+ }, visit);
1928
+ return;
1929
+ }
1930
+ if (!(args.entryType !== "array" || !Array.isArray(args.value))) for (const row of args.value) visitAssignmentFields({
1931
+ fields: args.of,
1932
+ value: row,
1933
+ path: `${args.path}[]`
1934
+ }, visit);
1935
+ }
1936
+
1937
+ function visitAssignmentCandidates(args, visit) {
1938
+ if (args.roles === void 0) return;
1939
+ const indexedValues = args.entryType === "assignees" && Array.isArray(args.value) ? args.value.map(value => ({
1940
+ value: value,
1941
+ path: args.path
1942
+ })) : [ {
1943
+ value: args.value,
1944
+ path: args.path
1945
+ } ];
1946
+ for (const {value: value, path: path} of indexedValues) {
1947
+ const assignee = assignmentCandidate(value);
1948
+ assignee !== void 0 && visit({
1949
+ assignee: assignee,
1950
+ roles: args.roles,
1951
+ path: path
1952
+ });
1953
+ }
1954
+ }
1955
+
1956
+ function visitAssignmentFields(args, visit) {
1957
+ if (!(args.fields === void 0 || !isRecord(args.value))) for (const field of args.fields) visitAssignmentShape({
1958
+ shape: field,
1959
+ value: args.value[field.name],
1960
+ path: `${args.path}.${field.name}`
1961
+ }, visit);
1962
+ }
1963
+
1964
+ function visitAssignmentShape(args, visit) {
1965
+ visitAssignmentEntries({
1966
+ entryType: args.shape.type,
1967
+ value: args.value,
1968
+ roles: args.shape.roles,
1969
+ fields: args.shape.fields,
1970
+ of: args.shape.of,
1971
+ path: args.path
1972
+ }, visit);
1973
+ }
1974
+
1975
+ function assignmentCandidateIssues(args, assignee) {
1976
+ if (assignee.type === "role") return collectiveRoleIssues(args, assignee.role);
1977
+ const held = args.memberRoles?.[assignee.id];
1978
+ return held === void 0 ? args.memberRoles === void 0 ? [] : [ `user "${assignee.id}" has no available project membership for role eligibility` ] : args.roles.some(required => actorFulfillsRole({
1979
+ actorRoles: held,
1980
+ required: required,
1981
+ aliases: args.roleAliases
1982
+ })) ? [] : [ `user "${assignee.id}" does not fulfill any eligible role: ${formatEligibleRoles(args.roles)}` ];
1983
+ }
1984
+
1985
+ function collectiveRoleIssues(args, role) {
1986
+ return args.roles.includes(role) ? [] : [ `collective role "${role}" is not eligible — this entry accepts ${formatEligibleRoles(args.roles)}` ];
1987
+ }
1988
+
1989
+ function formatEligibleRoles(roles) {
1990
+ return roles.map(role => `"${role}"`).join(", ");
1991
+ }
1992
+
1825
1993
  function issuesOf(check) {
1826
1994
  return "issues" in check ? check.issues : void 0;
1827
1995
  }
@@ -1881,6 +2049,20 @@ function validateFieldAppendItem(args) {
1881
2049
  issues: formatIssues(result.issues),
1882
2050
  mode: "item"
1883
2051
  });
2052
+ const assignmentArgs = {
2053
+ entryType: appendAssignmentEntryType(args.entryType),
2054
+ value: result.output,
2055
+ roles: args.roles,
2056
+ fields: args.entryType === "array" ? args.of : void 0,
2057
+ memberRoles: args.memberRoles,
2058
+ roleAliases: args.roleAliases
2059
+ }, assignmentIssues = assignmentValueIssues(assignmentArgs, result.output);
2060
+ if (assignmentIssues !== void 0) throw new FieldValueShapeError({
2061
+ entryType: args.entryType,
2062
+ entryName: args.entryName,
2063
+ issues: assignmentIssues,
2064
+ mode: "item"
2065
+ });
1884
2066
  const typeIssues = refTypeIssues({
1885
2067
  entryType: args.entryType,
1886
2068
  types: args.types,
@@ -1895,6 +2077,10 @@ function validateFieldAppendItem(args) {
1895
2077
  return result.output;
1896
2078
  }
1897
2079
 
2080
+ function appendAssignmentEntryType(entryType) {
2081
+ return entryType === "assignees" ? "assignee" : entryType === "array" ? "object" : entryType;
2082
+ }
2083
+
1898
2084
  function formatIssues(issues, formatMessage = issue => issue.message) {
1899
2085
  const formatOne = (issue, prefix) => {
1900
2086
  const keys = [ ...prefix, ...issue.path?.map(p => p.key) ?? [] ], sub = issue.issues?.filter(candidate => candidate.expected !== "null");
@@ -2087,16 +2273,17 @@ function compositeChecked(entries) {
2087
2273
  return v__namespace.pipe(v__namespace.strictObject(entries), v__namespace.check(input => compositeShapeOk(input), issue => compositeShapeMessage(issue.input)), v__namespace.check(input => duplicateSubfieldName(input) === void 0, issue => `duplicate sub-field name "${duplicateSubfieldName(issue.input)}" — sub-field names must be unique within \`fields\` / \`of\``));
2088
2274
  }
2089
2275
 
2090
- const FieldShapeSchema = v__namespace.lazy(() => v__namespace.pipe(compositeChecked({
2276
+ const AssignmentRolesSchema = v__namespace.pipe(v__namespace.array(NonEmpty), v__namespace.minLength(1, "declare at least one eligible role, or omit `roles`")), FieldShapeSchema = v__namespace.lazy(() => v__namespace.pipe(compositeChecked({
2091
2277
  type: FieldValueKindSchema,
2092
2278
  name: FieldEntryName,
2093
2279
  title: v__namespace.optional(v__namespace.string()),
2094
2280
  description: v__namespace.optional(v__namespace.string()),
2095
2281
  options: v__namespace.optional(ChoiceOptionsSchema),
2096
2282
  validation: v__namespace.optional(ScalarValidationSchema),
2283
+ roles: v__namespace.optional(AssignmentRolesSchema),
2097
2284
  fields: v__namespace.optional(v__namespace.array(FieldShapeSchema)),
2098
2285
  of: v__namespace.optional(v__namespace.array(FieldShapeSchema))
2099
- }), choiceOptionsCheck(), scalarValidationCheck())), StoredEditableSchema = v__namespace.union([ v__namespace.literal(!0), NonEmpty ]), AuthoringEditableSchema = v__namespace.union([ v__namespace.literal(!0), v__namespace.array(NonEmpty), NonEmpty ]);
2286
+ }), choiceOptionsCheck(), scalarValidationCheck(), assignmentRolesCheck())), StoredEditableSchema = v__namespace.union([ v__namespace.literal(!0), NonEmpty ]), AuthoringEditableSchema = v__namespace.union([ v__namespace.literal(!0), v__namespace.array(NonEmpty), NonEmpty ]);
2100
2287
 
2101
2288
  function fieldBase(editable, group) {
2102
2289
  return {
@@ -2117,6 +2304,7 @@ function fieldEntryFields({editable: editable, group: group, kind: kind = FieldK
2117
2304
  options: v__namespace.optional(ChoiceOptionsSchema),
2118
2305
  validation: v__namespace.optional(ScalarValidationSchema),
2119
2306
  types: v__namespace.optional(v__namespace.pipe(v__namespace.array(NonEmpty), v__namespace.minLength(1, "declare at least one accepted type, or omit `types` to accept any"))),
2307
+ roles: v__namespace.optional(AssignmentRolesSchema),
2120
2308
  fields: v__namespace.optional(v__namespace.array(FieldShapeSchema)),
2121
2309
  of: v__namespace.optional(v__namespace.array(FieldShapeSchema))
2122
2310
  };
@@ -2130,7 +2318,8 @@ function literalSeedIssues(entry) {
2130
2318
  fields: entry.fields,
2131
2319
  of: entry.of,
2132
2320
  options: entry.options,
2133
- validation: entry.validation
2321
+ validation: entry.validation,
2322
+ roles: entry.roles
2134
2323
  });
2135
2324
  }
2136
2325
 
@@ -2142,6 +2331,10 @@ function refTypesCheck() {
2142
2331
  return v__namespace.check(entry => entry.types === void 0 || refKindAcceptsTypes(entry.type), issue => `\`types\` is only valid on \`doc.ref\` / \`doc.refs\` / \`subject\` entries, not "${issue.input.type}"`);
2143
2332
  }
2144
2333
 
2334
+ function assignmentRolesCheck() {
2335
+ return v__namespace.check(entry => entry.roles === void 0 || assignmentKindAcceptsRoles(entry.type), issue => `\`roles\` is only valid on \`assignee\` / \`assignees\` entries, not "${issue.input.type}"`);
2336
+ }
2337
+
2145
2338
  function choiceOptionsCheck() {
2146
2339
  return v__namespace.check(entry => checkChoiceList({
2147
2340
  entryType: entry.type,
@@ -2176,11 +2369,11 @@ function scalarValidationDeclarationIssues(entry) {
2176
2369
  const FieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
2177
2370
  editable: StoredEditableSchema,
2178
2371
  group: StoredGroupMembershipSchema
2179
- })), refTypesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), RawAuthoringFieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
2372
+ })), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), RawAuthoringFieldEntrySchema = pinned()(v__namespace.pipe(compositeChecked(fieldEntryFields({
2180
2373
  editable: AuthoringEditableSchema,
2181
2374
  group: AuthoringGroupMembershipSchema,
2182
2375
  kind: AuthoringRawFieldKindSchema
2183
- })), refTypesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), ClaimFieldSchema = pinned()(v__namespace.strictObject({
2376
+ })), refTypesCheck(), assignmentRolesCheck(), choiceOptionsCheck(), scalarValidationCheck(), literalSeedCheck())), ClaimFieldSchema = pinned()(v__namespace.strictObject({
2184
2377
  type: v__namespace.literal("claim"),
2185
2378
  name: FieldEntryName,
2186
2379
  title: v__namespace.optional(v__namespace.string()),
@@ -3948,6 +4141,8 @@ exports.actorFulfillsRole = actorFulfillsRole;
3948
4141
 
3949
4142
  exports.andConditions = andConditions;
3950
4143
 
4144
+ exports.assignmentKindAcceptsRoles = assignmentKindAcceptsRoles;
4145
+
3951
4146
  exports.checkWorkflowInvariants = checkWorkflowInvariants;
3952
4147
 
3953
4148
  exports.choiceValueIssues = choiceValueIssues;
@@ -4012,6 +4207,8 @@ exports.groupMembershipNames = groupMembershipNames;
4012
4207
 
4013
4208
  exports.isAlwaysArrayFieldKind = isAlwaysArrayFieldKind;
4014
4209
 
4210
+ exports.isAssignmentFieldEntry = isAssignmentFieldEntry;
4211
+
4015
4212
  exports.isBareSeedId = isBareSeedId;
4016
4213
 
4017
4214
  exports.isCascadeFired = isCascadeFired;
@@ -4028,6 +4225,8 @@ exports.isNotesEntry = isNotesEntry;
4028
4225
 
4029
4226
  exports.isParseableInstant = isParseableInstant;
4030
4227
 
4228
+ exports.isRecord = isRecord;
4229
+
4031
4230
  exports.isSingleDocRefEntry = isSingleDocRefEntry;
4032
4231
 
4033
4232
  exports.isSingleDocRefKind = isSingleDocRefKind;