@sanity/workflow-engine 0.31.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.
- package/CHANGELOG.md +130 -0
- package/DATAMODEL.md +79 -1
- package/dist/_chunks-cjs/invariants.cjs +194 -147
- package/dist/_chunks-es/invariants.js +148 -149
- package/dist/define.d.cts +263 -966
- package/dist/define.d.ts +263 -966
- package/dist/index.cjs +1795 -785
- package/dist/index.d.cts +711 -1583
- package/dist/index.d.ts +711 -1583
- package/dist/index.js +1691 -709
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: !0
|
|
5
5
|
});
|
|
6
6
|
|
|
7
|
-
var invariants = require("./_chunks-cjs/invariants.cjs"), groqConditionDescribe = require("@sanity/groq-condition-describe"), groqJs = require("groq-js"), v = require("valibot");
|
|
7
|
+
var invariants = require("./_chunks-cjs/invariants.cjs"), groqConditionDescribe = require("@sanity/groq-condition-describe"), groqJs = require("groq-js"), idUtils = require("@sanity/id-utils"), v = require("valibot");
|
|
8
8
|
|
|
9
9
|
function _interopNamespaceCompat(e) {
|
|
10
10
|
if (e && typeof e == "object" && "default" in e) return e;
|
|
@@ -24,37 +24,6 @@ function _interopNamespaceCompat(e) {
|
|
|
24
24
|
|
|
25
25
|
var v__namespace = /* @__PURE__ */ _interopNamespaceCompat(v);
|
|
26
26
|
|
|
27
|
-
function isFilterScopedOut(entry) {
|
|
28
|
-
return entry.status === "skipped" && entry.startedAt === void 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function liveSubworkflows(host) {
|
|
32
|
-
return (host.subworkflows ?? []).filter(row => row.resolved === void 0);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function resolvedChildStatus(child) {
|
|
36
|
-
if (!(child.completedAt === void 0 || child.completedAt === null)) return child.abortedAt !== void 0 && child.abortedAt !== null ? "aborted" : "done";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function condemnedSubworkflows(host) {
|
|
40
|
-
return liveSubworkflows(host).filter(row => row.abortPending !== void 0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function condemnSubworkflow(row, owed) {
|
|
44
|
-
row.abortPending !== void 0 || row.resolved !== void 0 || (row.abortPending = {
|
|
45
|
-
at: owed.at,
|
|
46
|
-
reason: owed.reason
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function findOpenStageEntry(host) {
|
|
51
|
-
return host.stages.find(s => s.name === host.currentStage && s.exitedAt === void 0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function findCurrentActivityEntry(host, activityName) {
|
|
55
|
-
return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
27
|
const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
|
|
59
28
|
|
|
60
29
|
function terminalState(instance) {
|
|
@@ -189,7 +158,7 @@ function fieldWindowOpen(instance, site) {
|
|
|
189
158
|
if (site.scope !== "activity") return {
|
|
190
159
|
open: !0
|
|
191
160
|
};
|
|
192
|
-
const status = findCurrentActivityEntry(instance, site.activity)?.status;
|
|
161
|
+
const status = invariants.findCurrentActivityEntry(instance, site.activity)?.status;
|
|
193
162
|
return status === "active" ? {
|
|
194
163
|
open: !0
|
|
195
164
|
} : {
|
|
@@ -208,7 +177,7 @@ function resolveFieldEntry$1(instance, site) {
|
|
|
208
177
|
|
|
209
178
|
function fieldEntryHost(instance, site) {
|
|
210
179
|
if (site.scope === "workflow") return instance.fields;
|
|
211
|
-
const stageEntry = findOpenStageEntry(instance);
|
|
180
|
+
const stageEntry = invariants.findOpenStageEntry(instance);
|
|
212
181
|
return site.scope === "stage" ? stageEntry?.fields : stageEntry?.activities.find(t => t.name === site.activity)?.fields;
|
|
213
182
|
}
|
|
214
183
|
|
|
@@ -390,7 +359,7 @@ function instanceStartedDataFor(args) {
|
|
|
390
359
|
}
|
|
391
360
|
|
|
392
361
|
function stageTransitionedData(args) {
|
|
393
|
-
const stageIndex = name => args.definition.stages.findIndex(stage => stage.name === name), openEntry = findOpenStageEntry(args.instance), dwellMs = openEntry !== void 0 ? Date.parse(args.at) - Date.parse(openEntry.enteredAt) : Number.NaN;
|
|
362
|
+
const stageIndex = name => args.definition.stages.findIndex(stage => stage.name === name), openEntry = invariants.findOpenStageEntry(args.instance), dwellMs = openEntry !== void 0 ? Date.parse(args.at) - Date.parse(openEntry.enteredAt) : Number.NaN;
|
|
394
363
|
return {
|
|
395
364
|
...definitionHashFragment(args.instance.pinnedContentHash),
|
|
396
365
|
instanceId: args.instance._id,
|
|
@@ -472,6 +441,11 @@ function rolesGateOf(atom) {
|
|
|
472
441
|
if (!(count.type !== "FuncCall" || count.name !== "count" || count.args.length !== 1)) return rolesFilterList(count.args[0]);
|
|
473
442
|
}
|
|
474
443
|
|
|
444
|
+
function isAssignedGate(atom) {
|
|
445
|
+
const node = groqConditionDescribe.atomNode(atom);
|
|
446
|
+
return !atom.negated && node.type === "Parameter" && node.name === "assigned";
|
|
447
|
+
}
|
|
448
|
+
|
|
475
449
|
function rolesFilterList(node) {
|
|
476
450
|
if (node.type !== "Filter") return;
|
|
477
451
|
const base = node.base;
|
|
@@ -1760,27 +1734,38 @@ function startContextSyntaxIssues({groq: groq, vars: vars, context: context, ski
|
|
|
1760
1734
|
return [ ...invariants.conditionParameterNames(groq) ].filter(name => !bound.has(name) && name !== skip).map(name => `reads $${name}, which the ${context} context does not bind (an unbound variable is GROQ null, so the predicate silently misevaluates — failing closed or passing vacuously by shape). Bound here: ` + vars.map(v2 => `$${v2.name}`).join(", "));
|
|
1761
1735
|
}
|
|
1762
1736
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1737
|
+
const GUARD_DOC_TYPE = "temp.system.guard";
|
|
1738
|
+
|
|
1739
|
+
class MutationGuardDeniedError extends invariants.WorkflowError {
|
|
1740
|
+
denied;
|
|
1741
|
+
documentId;
|
|
1742
|
+
action;
|
|
1743
|
+
constructor(args) {
|
|
1744
|
+
const ids = args.denied.map(d => d.guardId).join(", ");
|
|
1745
|
+
super("mutation-guard-denied", `Mutation on "${args.documentId}" (${args.action}) denied by guard(s) [${ids}]`),
|
|
1746
|
+
this.name = "MutationGuardDeniedError", this.denied = args.denied, this.documentId = args.documentId,
|
|
1747
|
+
this.action = args.action;
|
|
1748
|
+
}
|
|
1749
|
+
static fromGuards(args) {
|
|
1750
|
+
return new MutationGuardDeniedError({
|
|
1751
|
+
documentId: args.documentId,
|
|
1752
|
+
action: args.action,
|
|
1753
|
+
denied: deniedGuardRefs(args.guards)
|
|
1754
|
+
});
|
|
1768
1755
|
}
|
|
1769
|
-
return current;
|
|
1770
1756
|
}
|
|
1771
1757
|
|
|
1772
|
-
function
|
|
1773
|
-
return
|
|
1758
|
+
function deniedGuardRefs(guards) {
|
|
1759
|
+
return guards.map(g => ({
|
|
1760
|
+
guardId: g._id,
|
|
1761
|
+
...g.name !== void 0 ? {
|
|
1762
|
+
name: g.name
|
|
1763
|
+
} : {}
|
|
1764
|
+
}));
|
|
1774
1765
|
}
|
|
1775
1766
|
|
|
1776
|
-
function
|
|
1777
|
-
|
|
1778
|
-
for (const part of path.split(".")) {
|
|
1779
|
-
if (current == null || typeof current != "object") return;
|
|
1780
|
-
if (isReferenceObject(current) && !Object.hasOwn(current, part)) throw new Error(`cannot read "${part}" through the nested reference "${current._ref}" — the workflow only loads references it declares. Declare it as a doc.ref field entry to read through it.`);
|
|
1781
|
-
current = current[part];
|
|
1782
|
-
}
|
|
1783
|
-
return current;
|
|
1767
|
+
function deniedGuardLabels(denied) {
|
|
1768
|
+
return denied.map(d => d.name ?? d.guardId);
|
|
1784
1769
|
}
|
|
1785
1770
|
|
|
1786
1771
|
function mapJsonStrings(value, transform) {
|
|
@@ -1849,205 +1834,664 @@ function overlayInstanceInSnapshot(snapshot, instance) {
|
|
|
1849
1834
|
};
|
|
1850
1835
|
}
|
|
1851
1836
|
|
|
1852
|
-
function
|
|
1853
|
-
|
|
1854
|
-
if (invariants.isSingleDocRefKind(kind)) {
|
|
1855
|
-
if (!invariants.isGdr(value)) return null;
|
|
1856
|
-
if (path === void 0 && targetKind !== void 0 && invariants.isSingleDocRefKind(targetKind)) return value;
|
|
1857
|
-
const base = derefBase(value, snapshot);
|
|
1858
|
-
return path === void 0 ? base : walkDocPath(base, path);
|
|
1859
|
-
}
|
|
1860
|
-
return path !== void 0 ? getPath(value, path) : value;
|
|
1837
|
+
function lakeGuardId(args) {
|
|
1838
|
+
return `${GUARD_DOC_TYPE}.${args.instanceDocId}.${args.guardName}`;
|
|
1861
1839
|
}
|
|
1862
1840
|
|
|
1863
|
-
function
|
|
1864
|
-
return
|
|
1865
|
-
_id: ref.id,
|
|
1866
|
-
_type: ref.type
|
|
1867
|
-
};
|
|
1841
|
+
function lakeActionsFor(action) {
|
|
1842
|
+
return action === "publish" ? [ "create", "update" ] : action === "unpublish" ? [ "delete" ] : [ action ];
|
|
1868
1843
|
}
|
|
1869
1844
|
|
|
1870
|
-
function
|
|
1871
|
-
const
|
|
1872
|
-
return
|
|
1873
|
-
self: invariants.selfGdr(instance),
|
|
1874
|
-
fields: renderedFields(instance.fields ?? [], snapshot),
|
|
1875
|
-
parent: parentRef(instance)?.id ?? null,
|
|
1876
|
-
ancestors: instance.ancestors.map(a => a.id),
|
|
1877
|
-
stage: instance.currentStage,
|
|
1878
|
-
now: now,
|
|
1879
|
-
context: contextMap(instance),
|
|
1880
|
-
effects: effectOutputsMap(instance),
|
|
1881
|
-
effectStatus: effectStatusMap(instance),
|
|
1882
|
-
activities: currentActivities2,
|
|
1883
|
-
subworkflows: subworkflowVarRows(instance, snapshot),
|
|
1884
|
-
...activityGateParams(currentActivities2),
|
|
1885
|
-
...extra
|
|
1886
|
-
};
|
|
1845
|
+
function lakeGuardActions(actions) {
|
|
1846
|
+
const requested = new Set(actions.flatMap(lakeActionsFor));
|
|
1847
|
+
return invariants.LAKE_MUTATION_GUARD_ACTIONS.filter(action => requested.has(action));
|
|
1887
1848
|
}
|
|
1888
1849
|
|
|
1889
|
-
function
|
|
1890
|
-
|
|
1891
|
-
return (instance.subworkflows ?? []).map(row => ({
|
|
1892
|
-
_id: invariants.toBareId(row.ref.id),
|
|
1893
|
-
rowKey: row.rowKey,
|
|
1894
|
-
activity: row.activity,
|
|
1895
|
-
action: row.action,
|
|
1896
|
-
definition: row.definition,
|
|
1897
|
-
current: row.stageEntry === openKey,
|
|
1898
|
-
...childState(row, snapshot),
|
|
1899
|
-
spawnedAt: row.spawnedAt
|
|
1900
|
-
}));
|
|
1850
|
+
function publishedId(id) {
|
|
1851
|
+
return idUtils.getPublishedId(id);
|
|
1901
1852
|
}
|
|
1902
1853
|
|
|
1903
|
-
function
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1854
|
+
function draftId(id) {
|
|
1855
|
+
return idUtils.getDraftId(id);
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
function versionPatternTranslation(pattern) {
|
|
1859
|
+
const documentSeparator = pattern.indexOf(".", 9);
|
|
1860
|
+
if (documentSeparator === -1) return {
|
|
1861
|
+
issue: `id pattern "${pattern}" does not identify a versioned document`
|
|
1907
1862
|
};
|
|
1908
|
-
const
|
|
1909
|
-
return
|
|
1910
|
-
|
|
1911
|
-
status: "active"
|
|
1863
|
+
const documentPattern = pattern.slice(documentSeparator + 1);
|
|
1864
|
+
return /^\*+$/.test(documentPattern) ? {
|
|
1865
|
+
issue: `id pattern "${pattern}" cannot be translated from a release version to a draft or published document without broadening it to every document`
|
|
1912
1866
|
} : {
|
|
1913
|
-
|
|
1914
|
-
status: resolvedChildStatus(doc) ?? "active"
|
|
1867
|
+
documentPattern: documentPattern
|
|
1915
1868
|
};
|
|
1916
1869
|
}
|
|
1917
1870
|
|
|
1918
|
-
function
|
|
1919
|
-
return
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1871
|
+
function publishedPattern(pattern) {
|
|
1872
|
+
if (pattern.startsWith("drafts.")) return pattern.slice(7);
|
|
1873
|
+
if (!pattern.startsWith("versions.")) return pattern;
|
|
1874
|
+
const translated = versionPatternTranslation(pattern);
|
|
1875
|
+
if (translated.issue !== void 0) throw new Error(translated.issue);
|
|
1876
|
+
return translated.documentPattern;
|
|
1923
1877
|
}
|
|
1924
1878
|
|
|
1925
|
-
function
|
|
1926
|
-
|
|
1927
|
-
for (const entry of entries) out[entry.name] = renderedValue(entry, snapshot);
|
|
1928
|
-
return out;
|
|
1879
|
+
function draftPattern(pattern) {
|
|
1880
|
+
return `drafts.${publishedPattern(pattern)}`;
|
|
1929
1881
|
}
|
|
1930
1882
|
|
|
1931
|
-
function
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
value: entry.value,
|
|
1935
|
-
path: void 0,
|
|
1936
|
-
snapshot: snapshot
|
|
1937
|
-
});
|
|
1883
|
+
function idsInSpace(args) {
|
|
1884
|
+
const {ids: ids, space: space, sourceInstanceId: sourceInstanceId} = args;
|
|
1885
|
+
return space === "authored" ? ids : space === "published" ? [ ...new Set(ids.map(publishedId)) ] : [ ...new Set(ids.map(id => publishedId(id) === sourceInstanceId ? publishedId(id) : draftId(id))) ];
|
|
1938
1886
|
}
|
|
1939
1887
|
|
|
1940
|
-
function
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1888
|
+
function patternsInSpace(patterns, space) {
|
|
1889
|
+
if (space === "authored") return patterns;
|
|
1890
|
+
const convert = space === "edit" ? draftPattern : publishedPattern;
|
|
1891
|
+
return [ ...new Set(patterns.map(convert)) ];
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
function matchInSpace(args) {
|
|
1895
|
+
const {match: match, actions: actions, space: space, sourceInstanceId: sourceInstanceId} = args;
|
|
1944
1896
|
return {
|
|
1945
|
-
...
|
|
1946
|
-
...
|
|
1897
|
+
...match,
|
|
1898
|
+
...match.idRefs !== void 0 ? {
|
|
1899
|
+
idRefs: idsInSpace({
|
|
1900
|
+
ids: match.idRefs,
|
|
1901
|
+
space: space,
|
|
1902
|
+
sourceInstanceId: sourceInstanceId
|
|
1903
|
+
})
|
|
1904
|
+
} : {},
|
|
1905
|
+
...match.idPatterns !== void 0 ? {
|
|
1906
|
+
idPatterns: patternsInSpace(match.idPatterns, space)
|
|
1907
|
+
} : {},
|
|
1908
|
+
actions: lakeGuardActions(actions)
|
|
1947
1909
|
};
|
|
1948
1910
|
}
|
|
1949
1911
|
|
|
1950
|
-
function
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1912
|
+
function guardPartitions(id, actions) {
|
|
1913
|
+
return invariants.MUTATION_GUARD_ID_SPACES.flatMap(space => {
|
|
1914
|
+
const matchingActions = actions.filter(action => invariants.mutationGuardActionIdSpace(action) === space);
|
|
1915
|
+
return matchingActions.length > 0 ? [ {
|
|
1916
|
+
space: space,
|
|
1917
|
+
actions: matchingActions
|
|
1918
|
+
} ] : [];
|
|
1919
|
+
}).map((partition, index) => ({
|
|
1920
|
+
...partition,
|
|
1921
|
+
id: index === 0 ? id : `${id}.${partition.space}`
|
|
1957
1922
|
}));
|
|
1958
1923
|
}
|
|
1959
1924
|
|
|
1960
|
-
function
|
|
1961
|
-
|
|
1962
|
-
if (entry === void 0) return {};
|
|
1963
|
-
const out = {};
|
|
1964
|
-
for (const run of instance.effectHistory) run.stageEntryKey === entry._key && (out[run.name] = run.status);
|
|
1965
|
-
return out;
|
|
1925
|
+
function compiledGuardIds(args) {
|
|
1926
|
+
return guardPartitions(args.id, args.actions).map(partition => partition.id);
|
|
1966
1927
|
}
|
|
1967
1928
|
|
|
1968
|
-
function
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1929
|
+
function lakeGuardDocument(args) {
|
|
1930
|
+
return {
|
|
1931
|
+
_id: args.id,
|
|
1932
|
+
_type: GUARD_DOC_TYPE,
|
|
1933
|
+
resourceType: args.resourceType,
|
|
1934
|
+
resourceId: args.resourceId,
|
|
1935
|
+
owner: args.owner,
|
|
1936
|
+
sourceInstanceId: args.sourceInstanceId,
|
|
1937
|
+
sourceDefinition: args.sourceDefinition,
|
|
1938
|
+
sourceStage: args.sourceStage,
|
|
1939
|
+
...args.name !== void 0 ? {
|
|
1940
|
+
name: args.name
|
|
1941
|
+
} : {},
|
|
1942
|
+
...args.description !== void 0 ? {
|
|
1943
|
+
description: args.description
|
|
1944
|
+
} : {},
|
|
1945
|
+
match: args.match,
|
|
1946
|
+
predicate: args.predicate,
|
|
1947
|
+
metadata: args.metadata
|
|
1948
|
+
};
|
|
1972
1949
|
}
|
|
1973
1950
|
|
|
1974
|
-
function
|
|
1975
|
-
const
|
|
1976
|
-
|
|
1977
|
-
|
|
1951
|
+
function compileGuards(args) {
|
|
1952
|
+
const [first, ...remaining] = guardPartitions(args.id, args.match.actions);
|
|
1953
|
+
if (first === void 0) throw new Error("cannot compile a guard without an action");
|
|
1954
|
+
const compilePartition = ({space: space, actions: actions, id: id}) => lakeGuardDocument({
|
|
1955
|
+
...args,
|
|
1956
|
+
id: id,
|
|
1957
|
+
match: matchInSpace({
|
|
1958
|
+
match: args.match,
|
|
1959
|
+
actions: actions,
|
|
1960
|
+
space: space,
|
|
1961
|
+
sourceInstanceId: args.sourceInstanceId
|
|
1962
|
+
})
|
|
1963
|
+
});
|
|
1964
|
+
return [ compilePartition(first), ...remaining.map(compilePartition) ];
|
|
1978
1965
|
}
|
|
1979
1966
|
|
|
1980
|
-
function
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
invariants.rethrowWithContext(err, `context entry "${entry.name}" holds unparseable JSON`);
|
|
1985
|
-
}
|
|
1967
|
+
function globMatch(pattern, value) {
|
|
1968
|
+
if (!pattern.includes("*")) return pattern === value;
|
|
1969
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1970
|
+
return new RegExp(`^${escaped}$`).test(value);
|
|
1986
1971
|
}
|
|
1987
1972
|
|
|
1988
|
-
function
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
parent: typeof params.parent == "string" ? invariants.toBareId(params.parent) : params.parent,
|
|
1993
|
-
ancestors: Array.isArray(params.ancestors) ? params.ancestors.map(a => typeof a == "string" ? invariants.toBareId(a) : a) : params.ancestors,
|
|
1994
|
-
fields: stripFieldsForLake(params.fields)
|
|
1995
|
-
};
|
|
1973
|
+
function guardIdPatternIssue(pattern, actions) {
|
|
1974
|
+
const representativeId = pattern.replaceAll("*", "x");
|
|
1975
|
+
if (!invariants.isBareDocumentId(representativeId)) return `id pattern "${pattern}" is not a valid resource-local document-id glob; use document-id characters (letters, digits, \`_\`, \`-\`, \`.\`) and \`*\` wildcards`;
|
|
1976
|
+
if (actions?.some(action => invariants.mutationGuardActionIdSpace(action) !== "authored") && pattern.startsWith("versions.")) return versionPatternTranslation(pattern).issue;
|
|
1996
1977
|
}
|
|
1997
1978
|
|
|
1998
|
-
function
|
|
1999
|
-
return
|
|
1979
|
+
function parseGuardPredicate(predicate) {
|
|
1980
|
+
return groqJs.parse(predicate, {
|
|
1981
|
+
mode: "delta"
|
|
1982
|
+
});
|
|
2000
1983
|
}
|
|
2001
1984
|
|
|
2002
|
-
function
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
return
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
1985
|
+
function guardPredicateSyntaxIssue(predicate) {
|
|
1986
|
+
try {
|
|
1987
|
+
parseGuardPredicate(predicate);
|
|
1988
|
+
return;
|
|
1989
|
+
} catch (error) {
|
|
1990
|
+
return invariants.errorMessage(error);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
2009
1993
|
|
|
2010
|
-
|
|
2011
|
-
|
|
1994
|
+
function lakeDocumentIdForAction(id, action) {
|
|
1995
|
+
return invariants.mutationGuardActionIdSpace(action) === "published" ? publishedId(id) : id;
|
|
1996
|
+
}
|
|
2012
1997
|
|
|
2013
|
-
|
|
2014
|
-
|
|
1998
|
+
function legacyLifecycleActionFor(action, documentId) {
|
|
1999
|
+
if (publishedId(documentId) === documentId) {
|
|
2000
|
+
if (action === "create" || action === "update") return "publish";
|
|
2001
|
+
if (action === "delete") return "unpublish";
|
|
2015
2002
|
}
|
|
2016
2003
|
}
|
|
2017
2004
|
|
|
2018
|
-
function
|
|
2019
|
-
const
|
|
2020
|
-
|
|
2005
|
+
function guardMatches({guard: guard, doc: doc, action: action}) {
|
|
2006
|
+
const m = guard.match, documentId = lakeDocumentIdForAction(doc.id, action), legacyLifecycleAction = legacyLifecycleActionFor(action, documentId);
|
|
2007
|
+
if (![ action, ...lakeActionsFor(action), legacyLifecycleAction ].some(candidate => candidate !== void 0 && m.actions.includes(candidate)) || m.types && m.types.length > 0 && !(doc.type !== void 0 && m.types.includes(doc.type))) return !1;
|
|
2008
|
+
if (m.idRefs && m.idRefs.length > 0 || m.idPatterns && m.idPatterns.length > 0) {
|
|
2009
|
+
const byRef = m.idRefs?.includes(documentId) ?? !1, byPattern = m.idPatterns?.some(p => globMatch(p, documentId)) ?? !1;
|
|
2010
|
+
if (!byRef && !byPattern) return !1;
|
|
2011
|
+
}
|
|
2012
|
+
return !0;
|
|
2021
2013
|
}
|
|
2022
2014
|
|
|
2023
|
-
function
|
|
2024
|
-
return
|
|
2015
|
+
function guardPredicateRoot(args) {
|
|
2016
|
+
return {
|
|
2017
|
+
document: {
|
|
2018
|
+
before: args.context.before,
|
|
2019
|
+
after: args.context.after
|
|
2020
|
+
},
|
|
2021
|
+
guard: args.guard,
|
|
2022
|
+
mutation: {
|
|
2023
|
+
action: args.context.action
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2025
2026
|
}
|
|
2026
2027
|
|
|
2027
|
-
function
|
|
2028
|
-
|
|
2029
|
-
return value == null ? value : invariants.isSingleDocRefKind(entryType) || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
|
|
2030
|
-
row: value,
|
|
2031
|
-
shapes: fields ?? [],
|
|
2032
|
-
mapRef: mapRef
|
|
2033
|
-
}) : entryType === "array" ? mapItems(value, row => mapRowRefValues({
|
|
2034
|
-
row: row,
|
|
2035
|
-
shapes: of ?? [],
|
|
2036
|
-
mapRef: mapRef
|
|
2037
|
-
})) : value;
|
|
2028
|
+
function lakeShapedSnapshotDocument(doc) {
|
|
2029
|
+
return mapJsonStrings(doc, (value, key) => key === "_id" || key === "_ref" ? invariants.toBareId(value) : value);
|
|
2038
2030
|
}
|
|
2039
2031
|
|
|
2040
|
-
function
|
|
2041
|
-
return
|
|
2032
|
+
function snapshotGuardDereference(args) {
|
|
2033
|
+
return ({_ref: _ref}) => {
|
|
2034
|
+
const lookupId = invariants.isGdrUri(_ref) ? _ref : invariants.gdrFromResource(args.resource, _ref), found = findSnapshotDoc(args.snapshot, lookupId);
|
|
2035
|
+
return Promise.resolve(found === void 0 ? null : lakeShapedSnapshotDocument(found));
|
|
2036
|
+
};
|
|
2042
2037
|
}
|
|
2043
2038
|
|
|
2044
|
-
function
|
|
2045
|
-
const {
|
|
2046
|
-
if (
|
|
2047
|
-
const
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2039
|
+
async function evaluateMutationGuard(args) {
|
|
2040
|
+
const {guard: guard, context: context, dereference: dereference} = args;
|
|
2041
|
+
if (guard.predicate === "") return !1;
|
|
2042
|
+
const root = guardPredicateRoot({
|
|
2043
|
+
guard: guard,
|
|
2044
|
+
context: context
|
|
2045
|
+
});
|
|
2046
|
+
let dereferenceFailed = !1;
|
|
2047
|
+
const guardedDereference = dereference === void 0 ? void 0 : async ref => {
|
|
2048
|
+
try {
|
|
2049
|
+
return await dereference(ref);
|
|
2050
|
+
} catch (error) {
|
|
2051
|
+
throw dereferenceFailed = !0, error;
|
|
2052
|
+
}
|
|
2053
|
+
};
|
|
2054
|
+
try {
|
|
2055
|
+
const tree = parseGuardPredicate(guard.predicate);
|
|
2056
|
+
return await (await groqJs.evaluate(tree, {
|
|
2057
|
+
root: root,
|
|
2058
|
+
before: context.before,
|
|
2059
|
+
after: context.after,
|
|
2060
|
+
...guardedDereference !== void 0 ? {
|
|
2061
|
+
dataset: [],
|
|
2062
|
+
dereference: guardedDereference
|
|
2063
|
+
} : {},
|
|
2064
|
+
...context.identity !== void 0 ? {
|
|
2065
|
+
identity: context.identity
|
|
2066
|
+
} : {}
|
|
2067
|
+
})).get() === !0;
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
if (dereferenceFailed) throw error;
|
|
2070
|
+
return !1;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
async function denyingGuards(args) {
|
|
2075
|
+
const {guards: guards, doc: doc, context: context, dereference: dereference} = args, denied = [];
|
|
2076
|
+
for (const guard of guards) guardMatches({
|
|
2077
|
+
guard: guard,
|
|
2078
|
+
doc: doc,
|
|
2079
|
+
action: context.action
|
|
2080
|
+
}) && (await evaluateMutationGuard({
|
|
2081
|
+
guard: guard,
|
|
2082
|
+
context: context,
|
|
2083
|
+
...dereference !== void 0 ? {
|
|
2084
|
+
dereference: dereference
|
|
2085
|
+
} : {}
|
|
2086
|
+
}) || denied.push(guard));
|
|
2087
|
+
return denied;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
async function documentActionDenials(args) {
|
|
2091
|
+
const {mutation: mutation, resource: resource, guards: guards, identity: identity, dereference: dereference} = args, document = mutation.after ?? mutation.before;
|
|
2092
|
+
if (document === null) throw new Error("a concrete Lake mutation requires a before or after image");
|
|
2093
|
+
const enforceable = guards.filter(g => g.resourceType === resource.type && g.resourceId === resource.id);
|
|
2094
|
+
return enforceable.length === 0 ? [] : denyingGuards({
|
|
2095
|
+
guards: enforceable,
|
|
2096
|
+
doc: {
|
|
2097
|
+
id: document._id,
|
|
2098
|
+
type: document._type
|
|
2099
|
+
},
|
|
2100
|
+
context: {
|
|
2101
|
+
...mutation,
|
|
2102
|
+
...identity !== void 0 ? {
|
|
2103
|
+
identity: identity
|
|
2104
|
+
} : {}
|
|
2105
|
+
},
|
|
2106
|
+
...dereference !== void 0 ? {
|
|
2107
|
+
dereference: dereference
|
|
2108
|
+
} : {}
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
async function instanceWriteDenials(args) {
|
|
2113
|
+
const {instance: instance, guards: guards, identity: identity, dereference: dereference} = args;
|
|
2114
|
+
return documentActionDenials({
|
|
2115
|
+
mutation: {
|
|
2116
|
+
before: instance,
|
|
2117
|
+
after: instance,
|
|
2118
|
+
action: "update"
|
|
2119
|
+
},
|
|
2120
|
+
resource: instance.workflowResource,
|
|
2121
|
+
guards: guards,
|
|
2122
|
+
dereference: dereference,
|
|
2123
|
+
...identity !== void 0 ? {
|
|
2124
|
+
identity: identity
|
|
2125
|
+
} : {}
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
async function assertInstanceWriteAllowed(args) {
|
|
2130
|
+
const denied = await instanceWriteDenials(args);
|
|
2131
|
+
if (denied.length !== 0) throw MutationGuardDeniedError.fromGuards({
|
|
2132
|
+
documentId: args.instance._id,
|
|
2133
|
+
action: "update",
|
|
2134
|
+
guards: denied
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
const ASSIGNMENT_LIST_MODEL = 9;
|
|
2139
|
+
|
|
2140
|
+
function isAssignmentListModel(modelVersion) {
|
|
2141
|
+
return modelVersion >= ASSIGNMENT_LIST_MODEL;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
function definitionAssignmentModel(instance) {
|
|
2145
|
+
if (typeof instance.definitionSnapshot != "string") return 0;
|
|
2146
|
+
const modelVersion = parseDefinitionSnapshotValue({
|
|
2147
|
+
_id: instance._id,
|
|
2148
|
+
definitionSnapshot: instance.definitionSnapshot
|
|
2149
|
+
}).modelVersion;
|
|
2150
|
+
return typeof modelVersion == "number" ? modelVersion : 0;
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
function writesSingularAssignmentLists(instance) {
|
|
2154
|
+
return isAssignmentListModel(definitionAssignmentModel(instance));
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
function legacyAssigneeValue(entry) {
|
|
2158
|
+
return legacyAssignmentValue(entry.value, entry.name);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
function legacyAssignmentValue(value, path) {
|
|
2162
|
+
if (!Array.isArray(value)) return value;
|
|
2163
|
+
if (value.length === 0) return null;
|
|
2164
|
+
if (value.length === 1) return value[0];
|
|
2165
|
+
throw new invariants.ContractViolationError(`legacy assignee field "${path}" cannot persist ${value.length} members; redeploy the definition at the assignment-list reader model before writing a role pool`);
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
function mapShapeValues(args) {
|
|
2169
|
+
const {value: value, shapes: shapes, mapAssignee: mapAssignee, parentPath: parentPath} = args;
|
|
2170
|
+
if (typeof value != "object" || value === null || Array.isArray(value)) return value;
|
|
2171
|
+
const source = value, next = {
|
|
2172
|
+
...source
|
|
2173
|
+
};
|
|
2174
|
+
for (const shape of shapes) {
|
|
2175
|
+
if (!Object.hasOwn(source, shape.name)) continue;
|
|
2176
|
+
const path = `${parentPath}.${shape.name}`, member = source[shape.name], mapped = mappedShapeValue({
|
|
2177
|
+
shape: shape,
|
|
2178
|
+
member: member,
|
|
2179
|
+
mapAssignee: mapAssignee,
|
|
2180
|
+
path: path
|
|
2181
|
+
});
|
|
2182
|
+
mapped.found && defineOwnValue(next, {
|
|
2183
|
+
name: shape.name,
|
|
2184
|
+
value: mapped.value
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
return next;
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
function mappedShapeValue(args) {
|
|
2191
|
+
const {shape: shape, member: member, mapAssignee: mapAssignee, path: path} = args;
|
|
2192
|
+
return shape.type === "assignee" ? {
|
|
2193
|
+
found: !0,
|
|
2194
|
+
value: mapAssignee(member, path)
|
|
2195
|
+
} : shape.type === "object" ? {
|
|
2196
|
+
found: !0,
|
|
2197
|
+
value: mapShapeValues({
|
|
2198
|
+
value: member,
|
|
2199
|
+
shapes: shape.fields ?? [],
|
|
2200
|
+
mapAssignee: mapAssignee,
|
|
2201
|
+
parentPath: path
|
|
2202
|
+
})
|
|
2203
|
+
} : shape.type !== "array" || !Array.isArray(member) ? {
|
|
2204
|
+
found: !1
|
|
2205
|
+
} : {
|
|
2206
|
+
found: !0,
|
|
2207
|
+
value: member.map((row, index) => mapShapeValues({
|
|
2208
|
+
value: row,
|
|
2209
|
+
shapes: shape.of ?? [],
|
|
2210
|
+
mapAssignee: mapAssignee,
|
|
2211
|
+
parentPath: `${path}[${index}]`
|
|
2212
|
+
}))
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
function defineOwnValue(target, property) {
|
|
2217
|
+
Object.defineProperty(target, property.name, {
|
|
2218
|
+
configurable: !0,
|
|
2219
|
+
enumerable: !0,
|
|
2220
|
+
value: property.value,
|
|
2221
|
+
writable: !0
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
function mapNestedAssignmentValues(entry, mapAssignee) {
|
|
2226
|
+
return entry._type === "object" ? mapShapeValues({
|
|
2227
|
+
value: entry.value,
|
|
2228
|
+
shapes: entry.fields,
|
|
2229
|
+
mapAssignee: mapAssignee,
|
|
2230
|
+
parentPath: entry.name
|
|
2231
|
+
}) : entry.value.map((row, index) => mapShapeValues({
|
|
2232
|
+
value: row,
|
|
2233
|
+
shapes: entry.of,
|
|
2234
|
+
mapAssignee: mapAssignee,
|
|
2235
|
+
parentPath: `${entry.name}[${index}]`
|
|
2236
|
+
}));
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
function normalizeNestedAssignmentValues(entry) {
|
|
2240
|
+
return entry._type !== "object" && entry._type !== "array" ? entry : {
|
|
2241
|
+
...entry,
|
|
2242
|
+
value: mapNestedAssignmentValues(entry, invariants.normalizeAssignmentMembers)
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
function assignmentFieldsForWrite(fields, listModel) {
|
|
2247
|
+
return listModel ? fields : fields.map(entry => entry._type === "assignee" ? {
|
|
2248
|
+
...entry,
|
|
2249
|
+
value: legacyAssigneeValue(entry)
|
|
2250
|
+
} : entry._type === "object" || entry._type === "array" ? {
|
|
2251
|
+
...entry,
|
|
2252
|
+
value: mapNestedAssignmentValues(entry, legacyAssignmentValue)
|
|
2253
|
+
} : entry);
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
function activityForWrite(activity, listModel) {
|
|
2257
|
+
return {
|
|
2258
|
+
...activity,
|
|
2259
|
+
...activity.fields === void 0 ? {} : {
|
|
2260
|
+
fields: assignmentFieldsForWrite(activity.fields, listModel)
|
|
2261
|
+
}
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
function assignmentStagesForWrite(stages, listModel) {
|
|
2266
|
+
return stages.map(stage => ({
|
|
2267
|
+
...stage,
|
|
2268
|
+
fields: assignmentFieldsForWrite(stage.fields ?? [], listModel),
|
|
2269
|
+
activities: stage.activities.map(activity => activityForWrite(activity, listModel))
|
|
2270
|
+
}));
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
function getPath(value, path) {
|
|
2274
|
+
let current = value;
|
|
2275
|
+
for (const part of path.split(".")) {
|
|
2276
|
+
if (current == null || typeof current != "object") return;
|
|
2277
|
+
current = current[part];
|
|
2278
|
+
}
|
|
2279
|
+
return current;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
function isReferenceObject(value) {
|
|
2283
|
+
return typeof value._ref == "string";
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
function walkDocPath(value, path) {
|
|
2287
|
+
let current = value;
|
|
2288
|
+
for (const part of path.split(".")) {
|
|
2289
|
+
if (current == null || typeof current != "object") return;
|
|
2290
|
+
if (isReferenceObject(current) && !Object.hasOwn(current, part)) throw new Error(`cannot read "${part}" through the nested reference "${current._ref}" — the workflow only loads references it declares. Declare it as a doc.ref field entry to read through it.`);
|
|
2291
|
+
current = current[part];
|
|
2292
|
+
}
|
|
2293
|
+
return current;
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
function resolveFieldRead(args) {
|
|
2297
|
+
const {kind: kind, value: value, path: path, snapshot: snapshot, targetKind: targetKind} = args;
|
|
2298
|
+
if (invariants.isSingleDocRefKind(kind)) {
|
|
2299
|
+
if (!invariants.isGdr(value)) return null;
|
|
2300
|
+
if (path === void 0 && targetKind !== void 0 && invariants.isSingleDocRefKind(targetKind)) return value;
|
|
2301
|
+
const base = derefBase(value, snapshot);
|
|
2302
|
+
return path === void 0 ? base : walkDocPath(base, path);
|
|
2303
|
+
}
|
|
2304
|
+
return path !== void 0 ? getPath(value, path) : value;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
function derefBase(ref, snapshot) {
|
|
2308
|
+
return (snapshot !== void 0 ? findSnapshotDoc(snapshot, ref.id) : void 0) ?? {
|
|
2309
|
+
_id: ref.id,
|
|
2310
|
+
_type: ref.type
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
function buildParams(args) {
|
|
2315
|
+
const {instance: instance, now: now, snapshot: snapshot, extra: extra} = args, currentActivities2 = invariants.findOpenStageEntry(instance)?.activities ?? [];
|
|
2316
|
+
return {
|
|
2317
|
+
self: invariants.selfGdr(instance),
|
|
2318
|
+
fields: renderedFields(instance.fields ?? [], snapshot),
|
|
2319
|
+
parent: parentRef(instance)?.id ?? null,
|
|
2320
|
+
ancestors: instance.ancestors.map(a => a.id),
|
|
2321
|
+
stage: instance.currentStage,
|
|
2322
|
+
now: now,
|
|
2323
|
+
context: contextMap(instance),
|
|
2324
|
+
effects: effectOutputsMap(instance),
|
|
2325
|
+
effectStatus: effectStatusMap(instance),
|
|
2326
|
+
activities: currentActivities2,
|
|
2327
|
+
subworkflows: subworkflowVarRows(instance, snapshot),
|
|
2328
|
+
...activityGateParams(currentActivities2),
|
|
2329
|
+
...extra
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
function subworkflowVarRows(instance, snapshot) {
|
|
2334
|
+
const openKey = invariants.findOpenStageEntry(instance)?._key;
|
|
2335
|
+
return (instance.subworkflows ?? []).map(row => ({
|
|
2336
|
+
_id: invariants.toBareId(row.ref.id),
|
|
2337
|
+
rowKey: row.rowKey,
|
|
2338
|
+
activity: row.activity,
|
|
2339
|
+
action: row.action,
|
|
2340
|
+
definition: row.definition,
|
|
2341
|
+
current: row.stageEntry === openKey,
|
|
2342
|
+
...childState(row, snapshot),
|
|
2343
|
+
spawnedAt: row.spawnedAt
|
|
2344
|
+
}));
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
function childState(row, snapshot) {
|
|
2348
|
+
if (row.resolved !== void 0) return {
|
|
2349
|
+
stage: row.resolved.stage ?? null,
|
|
2350
|
+
status: row.resolved.aborted === !0 ? "aborted" : "done"
|
|
2351
|
+
};
|
|
2352
|
+
const doc = snapshot === void 0 ? void 0 : findSnapshotDoc(snapshot, row.ref.id);
|
|
2353
|
+
return doc === void 0 ? {
|
|
2354
|
+
stage: null,
|
|
2355
|
+
status: "active"
|
|
2356
|
+
} : {
|
|
2357
|
+
stage: doc.currentStage ?? null,
|
|
2358
|
+
status: invariants.resolvedChildStatus(doc) ?? "active"
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
function activityGateParams(activities) {
|
|
2363
|
+
return {
|
|
2364
|
+
allActivitiesDone: activities.every(activity => activity.status === "done" || activity.status === "skipped"),
|
|
2365
|
+
anyActivityFailed: activities.some(activity => activity.status === "failed")
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
function renderedFields(entries, snapshot) {
|
|
2370
|
+
const out = {};
|
|
2371
|
+
for (const entry of entries) out[entry.name] = renderedValue(entry, snapshot);
|
|
2372
|
+
return out;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
function renderedValue(entry, snapshot) {
|
|
2376
|
+
return resolveFieldRead({
|
|
2377
|
+
kind: entry._type,
|
|
2378
|
+
value: entry.value,
|
|
2379
|
+
path: void 0,
|
|
2380
|
+
snapshot: snapshot
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
function scopedFieldOverlay({instance: instance, snapshot: snapshot, activityName: activityName}) {
|
|
2385
|
+
const stageEntry = invariants.findOpenStageEntry(instance);
|
|
2386
|
+
if (stageEntry === void 0) return {};
|
|
2387
|
+
const stageFields = renderedFields(stageEntry.fields ?? [], snapshot), activity = activityName ? stageEntry.activities.find(t => t.name === activityName) : void 0;
|
|
2388
|
+
return {
|
|
2389
|
+
...stageFields,
|
|
2390
|
+
...renderedFields(activity?.fields ?? [], snapshot)
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
function assignedFor({instance: instance, activityName: activityName, actor: actor, roleAliases: roleAliases}) {
|
|
2395
|
+
if (actor === void 0) return !1;
|
|
2396
|
+
const activity = invariants.findCurrentActivityEntry(instance, activityName);
|
|
2397
|
+
return invariants.actorMatchesAssignment({
|
|
2398
|
+
actor: actor,
|
|
2399
|
+
members: invariants.assignmentMembers(activity?.fields ?? []),
|
|
2400
|
+
roleAliases: roleAliases
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
function effectStatusMap(instance) {
|
|
2405
|
+
const entry = invariants.findOpenStageEntry(instance);
|
|
2406
|
+
if (entry === void 0) return {};
|
|
2407
|
+
const out = {};
|
|
2408
|
+
for (const run of instance.effectHistory) run.stageEntryKey === entry._key && (out[run.name] = run.status);
|
|
2409
|
+
return out;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
function contextMap(instance) {
|
|
2413
|
+
const out = {};
|
|
2414
|
+
for (const entry of instance.context) out[entry.name] = entry._type === "context.json" ? parseJsonContextEntry(entry) : entry.value;
|
|
2415
|
+
return out;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
function effectOutputsMap(instance) {
|
|
2419
|
+
const out = {};
|
|
2420
|
+
for (const run of instance.effectHistory) run.outputs !== void 0 && (out[run.name] = run.outputs);
|
|
2421
|
+
return out;
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
function parseJsonContextEntry(entry) {
|
|
2425
|
+
try {
|
|
2426
|
+
return JSON.parse(entry.value);
|
|
2427
|
+
} catch (err) {
|
|
2428
|
+
invariants.rethrowWithContext(err, `context entry "${entry.name}" holds unparseable JSON`);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
function paramsForLake(params) {
|
|
2433
|
+
return {
|
|
2434
|
+
...params,
|
|
2435
|
+
self: typeof params.self == "string" ? invariants.toBareId(params.self) : params.self,
|
|
2436
|
+
parent: typeof params.parent == "string" ? invariants.toBareId(params.parent) : params.parent,
|
|
2437
|
+
ancestors: Array.isArray(params.ancestors) ? params.ancestors.map(a => typeof a == "string" ? invariants.toBareId(a) : a) : params.ancestors,
|
|
2438
|
+
fields: stripFieldsForLake(params.fields)
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
function stripFieldsForLake(value) {
|
|
2443
|
+
return mapJsonStrings(value, s => invariants.toBareId(s));
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
function resolveStaticValueExpr(src, ctx) {
|
|
2447
|
+
switch (src.type) {
|
|
2448
|
+
case "literal":
|
|
2449
|
+
return src.value;
|
|
2450
|
+
|
|
2451
|
+
case "param":
|
|
2452
|
+
return ctx.params?.[src.param];
|
|
2453
|
+
|
|
2454
|
+
case "actor":
|
|
2455
|
+
return ctx.actor;
|
|
2456
|
+
|
|
2457
|
+
case "now":
|
|
2458
|
+
return ctx.now;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
function randomKey(length = 12) {
|
|
2463
|
+
const bytes = new Uint8Array(length);
|
|
2464
|
+
return globalThis.crypto.getRandomValues(bytes), [ ...bytes ].map(b => b.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
function instanceDocId(tag) {
|
|
2468
|
+
return `${tag}.wf-instance.${randomKey()}`;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
function mapFieldRefValues(args) {
|
|
2472
|
+
const {entryType: entryType, value: value, fields: fields, of: of, mapRef: mapRef} = args;
|
|
2473
|
+
return value == null ? value : invariants.isSingleDocRefKind(entryType) || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
|
|
2474
|
+
row: value,
|
|
2475
|
+
shapes: fields ?? [],
|
|
2476
|
+
mapRef: mapRef
|
|
2477
|
+
}) : entryType === "array" ? mapItems(value, row => mapRowRefValues({
|
|
2478
|
+
row: row,
|
|
2479
|
+
shapes: of ?? [],
|
|
2480
|
+
mapRef: mapRef
|
|
2481
|
+
})) : value;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
function mapItems(value, mapItem) {
|
|
2485
|
+
return Array.isArray(value) ? value.map(mapItem) : value;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
function mapRowRefValues(args) {
|
|
2489
|
+
const {row: row, shapes: shapes, mapRef: mapRef} = args;
|
|
2490
|
+
if (typeof row != "object" || row === null || Array.isArray(row)) return row;
|
|
2491
|
+
const record = row, out = {
|
|
2492
|
+
...record
|
|
2493
|
+
};
|
|
2494
|
+
for (const shape of shapes) shape.name in record && (out[shape.name] = mapFieldRefValues({
|
|
2051
2495
|
entryType: shape.type,
|
|
2052
2496
|
value: record[shape.name],
|
|
2053
2497
|
fields: shape.fields,
|
|
@@ -2269,10 +2713,12 @@ class WorkflowStateDivergedError extends invariants.WorkflowError {
|
|
|
2269
2713
|
class PartialGuardDeployError extends invariants.WorkflowError {
|
|
2270
2714
|
stageName;
|
|
2271
2715
|
deployed;
|
|
2716
|
+
rollbackError;
|
|
2272
2717
|
constructor(args) {
|
|
2273
2718
|
super("partial-guard-deploy", `Partial guard deploy on stage "${args.stageName}": ${args.deployed} guard(s) deployed before a later one failed.`, {
|
|
2274
2719
|
cause: args.cause
|
|
2275
|
-
}), this.name = "PartialGuardDeployError", this.stageName = args.stageName, this.deployed = args.deployed
|
|
2720
|
+
}), this.name = "PartialGuardDeployError", this.stageName = args.stageName, this.deployed = args.deployed,
|
|
2721
|
+
args.rollbackError !== void 0 && (this.rollbackError = args.rollbackError);
|
|
2276
2722
|
}
|
|
2277
2723
|
}
|
|
2278
2724
|
|
|
@@ -2313,7 +2759,23 @@ function staleClaimDetail(reason) {
|
|
|
2313
2759
|
const CONCURRENT_COMMIT_MAX_ATTEMPTS = 3;
|
|
2314
2760
|
|
|
2315
2761
|
function lostRaceMessage(args) {
|
|
2316
|
-
return `${args.what} (instance ${args.instanceId}) lost the optimistic-locking race ${args.attempts} attempts running — a concurrent writer kept committing first. Re-read and retry, or investigate a write storm on this instance
|
|
2762
|
+
return `${args.what} (instance ${args.instanceId}) lost the optimistic-locking race ${args.attempts} attempts running — a concurrent writer kept committing first. ${args.recovery ?? "Re-read and retry, or investigate a write storm on this instance."}`;
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
function isRetryableInstanceCommitConflict(error) {
|
|
2766
|
+
return !isCreateIdCollision(error) && isRevisionConflict(error);
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
class InstanceCommitRevisionConflict extends Error {
|
|
2770
|
+
constructor(cause) {
|
|
2771
|
+
super("Instance commit lost its revision fence", {
|
|
2772
|
+
cause: cause
|
|
2773
|
+
}), this.name = "InstanceCommitRevisionConflict";
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
function isInstanceCommitRevisionConflict(error) {
|
|
2778
|
+
return error instanceof InstanceCommitRevisionConflict;
|
|
2317
2779
|
}
|
|
2318
2780
|
|
|
2319
2781
|
class ConcurrentFireActionError extends invariants.WorkflowError {
|
|
@@ -2331,6 +2793,19 @@ class ConcurrentFireActionError extends invariants.WorkflowError {
|
|
|
2331
2793
|
}
|
|
2332
2794
|
}
|
|
2333
2795
|
|
|
2796
|
+
class ConcurrentCascadeError extends invariants.WorkflowError {
|
|
2797
|
+
instanceId;
|
|
2798
|
+
attempts;
|
|
2799
|
+
constructor(args) {
|
|
2800
|
+
super("concurrent-cascade", lostRaceMessage({
|
|
2801
|
+
what: "Automatic cascade",
|
|
2802
|
+
instanceId: args.instanceId,
|
|
2803
|
+
attempts: args.attempts,
|
|
2804
|
+
recovery: "An earlier verb commit may already have landed. Re-read the instance and invoke tick after contention subsides."
|
|
2805
|
+
})), this.name = "ConcurrentCascadeError", this.instanceId = args.instanceId, this.attempts = args.attempts;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2334
2809
|
function isRevisionConflict(error) {
|
|
2335
2810
|
if (typeof error != "object" || error === null) return !1;
|
|
2336
2811
|
const {statusCode: statusCode, message: message} = error;
|
|
@@ -2613,11 +3088,15 @@ function applyFieldSet(op, ctx) {
|
|
|
2613
3088
|
...entryShape(entry),
|
|
2614
3089
|
memberRoles: ctx.memberRoles,
|
|
2615
3090
|
roleAliases: ctx.roleAliases,
|
|
2616
|
-
...entry._type === "assignees" || entry._type === "object" || entry._type === "array" ? {
|
|
3091
|
+
...entry._type === "assignee" || entry._type === "assignees" || entry._type === "object" || entry._type === "array" ? {
|
|
2617
3092
|
previousValue: entry.value
|
|
2618
3093
|
} : {}
|
|
2619
3094
|
});
|
|
2620
|
-
return
|
|
3095
|
+
return assertLegacySingularValue({
|
|
3096
|
+
entry: entry,
|
|
3097
|
+
value: validated,
|
|
3098
|
+
ctx: ctx
|
|
3099
|
+
}), assertRuntimeRefsWithinSurface({
|
|
2621
3100
|
entryType: entry._type,
|
|
2622
3101
|
entryName: entry.name,
|
|
2623
3102
|
value: validated,
|
|
@@ -2634,12 +3113,12 @@ function applyFieldSet(op, ctx) {
|
|
|
2634
3113
|
}
|
|
2635
3114
|
|
|
2636
3115
|
function applyFieldSetIfMissing(op, ctx) {
|
|
2637
|
-
const entry = locateEntry(ctx, op.target);
|
|
2638
|
-
return invariants.isAlwaysArrayFieldKind(entry._type) && rejectFieldOpTarget({
|
|
3116
|
+
const entry = locateEntry(ctx, op.target), legacySingular = isLegacySingularAssignment(entry, ctx);
|
|
3117
|
+
return invariants.isAlwaysArrayFieldKind(entry._type) && !legacySingular && rejectFieldOpTarget({
|
|
2639
3118
|
entry: entry,
|
|
2640
3119
|
op: op,
|
|
2641
3120
|
issue: "is always array-valued — setIfMissing applies to nullable entries only; an empty array entry already holds []"
|
|
2642
|
-
}), entry.value !== null && entry.value !== void 0 ? {
|
|
3121
|
+
}), entry.value !== null && entry.value !== void 0 && !(legacySingular && Array.isArray(entry.value) && entry.value.length === 0) ? {
|
|
2643
3122
|
opType: op.type,
|
|
2644
3123
|
target: op.target
|
|
2645
3124
|
} : {
|
|
@@ -2760,7 +3239,14 @@ function applyFieldUnset(op, ctx) {
|
|
|
2760
3239
|
}
|
|
2761
3240
|
|
|
2762
3241
|
function applyFieldAppend(op, ctx) {
|
|
2763
|
-
const entry = locateEntry(ctx, op.target)
|
|
3242
|
+
const entry = locateEntry(ctx, op.target);
|
|
3243
|
+
if (isLegacySingularAssignment(entry, ctx)) throw new invariants.FieldValueShapeError({
|
|
3244
|
+
entryType: entry._type,
|
|
3245
|
+
entryName: entry.name,
|
|
3246
|
+
mode: "item",
|
|
3247
|
+
issues: [ "legacy singular assignee entries do not support append; redeploy at model 9" ]
|
|
3248
|
+
});
|
|
3249
|
+
const slot = appendItemSlot(entry), item = resolveOpValue({
|
|
2764
3250
|
src: op.value,
|
|
2765
3251
|
ctx: ctx,
|
|
2766
3252
|
...slot !== void 0 ? {
|
|
@@ -2772,7 +3258,7 @@ function applyFieldAppend(op, ctx) {
|
|
|
2772
3258
|
item: item,
|
|
2773
3259
|
types: entry._type === "doc.refs" ? entry.types : void 0,
|
|
2774
3260
|
of: entry._type === "array" ? entry.of : void 0,
|
|
2775
|
-
roles: entry
|
|
3261
|
+
roles: invariants.isAssignmentFieldEntry(entry) ? entry.roles : void 0,
|
|
2776
3262
|
memberRoles: ctx.memberRoles,
|
|
2777
3263
|
roleAliases: ctx.roleAliases
|
|
2778
3264
|
});
|
|
@@ -2784,8 +3270,16 @@ function applyFieldAppend(op, ctx) {
|
|
|
2784
3270
|
ctx: ctx,
|
|
2785
3271
|
src: op.value
|
|
2786
3272
|
});
|
|
2787
|
-
const
|
|
2788
|
-
|
|
3273
|
+
const next = [ ...Array.isArray(entry.value) ? entry.value : [], withRowKey(validated) ], value = invariants.isAssignmentFieldEntry(entry) ? invariants.validateFieldValue({
|
|
3274
|
+
entryType: entry._type,
|
|
3275
|
+
entryName: entry.name,
|
|
3276
|
+
value: next,
|
|
3277
|
+
...assignmentEntryShape(entry),
|
|
3278
|
+
previousValue: entry.value,
|
|
3279
|
+
memberRoles: ctx.memberRoles,
|
|
3280
|
+
roleAliases: ctx.roleAliases
|
|
3281
|
+
}) : next;
|
|
3282
|
+
return setEntryValue(entry, value), {
|
|
2789
3283
|
opType: op.type,
|
|
2790
3284
|
target: op.target,
|
|
2791
3285
|
resolved: {
|
|
@@ -2862,7 +3356,14 @@ async function applyFieldUpdateWhere(op, ctx) {
|
|
|
2862
3356
|
}
|
|
2863
3357
|
|
|
2864
3358
|
async function applyFieldRemoveWhere(op, ctx) {
|
|
2865
|
-
const entry = locateEntry(ctx, op.target)
|
|
3359
|
+
const entry = locateEntry(ctx, op.target);
|
|
3360
|
+
if (isLegacySingularAssignment(entry, ctx)) throw new invariants.FieldValueShapeError({
|
|
3361
|
+
entryType: entry._type,
|
|
3362
|
+
entryName: entry.name,
|
|
3363
|
+
mode: "value",
|
|
3364
|
+
issues: [ "legacy singular assignee entries do not support removeWhere; redeploy at model 9" ]
|
|
3365
|
+
});
|
|
3366
|
+
const rows = requireArrayValue(entry, op), matches = await rowMatches({
|
|
2866
3367
|
where: op.where,
|
|
2867
3368
|
rows: rows,
|
|
2868
3369
|
ctx: ctx
|
|
@@ -2873,6 +3374,20 @@ async function applyFieldRemoveWhere(op, ctx) {
|
|
|
2873
3374
|
};
|
|
2874
3375
|
}
|
|
2875
3376
|
|
|
3377
|
+
function assertLegacySingularValue(args) {
|
|
3378
|
+
const {entry: entry, value: value, ctx: ctx} = args;
|
|
3379
|
+
if (!(!isLegacySingularAssignment(entry, ctx) || !Array.isArray(value) || value.length <= 1)) throw new invariants.FieldValueShapeError({
|
|
3380
|
+
entryType: entry._type,
|
|
3381
|
+
entryName: entry.name,
|
|
3382
|
+
mode: "value",
|
|
3383
|
+
issues: [ "legacy singular assignee entries accept at most one total member; redeploy at model 9" ]
|
|
3384
|
+
});
|
|
3385
|
+
}
|
|
3386
|
+
|
|
3387
|
+
function isLegacySingularAssignment(entry, ctx) {
|
|
3388
|
+
return entry._type === "assignee" && !isAssignmentListModel(ctx.mutation.definitionModelVersion);
|
|
3389
|
+
}
|
|
3390
|
+
|
|
2876
3391
|
function requireMergeableRows(entry, op) {
|
|
2877
3392
|
if (entry._type !== "array") throw new Error(`${op.type} target ${op.target.scope}:"${op.target.field}" is a ${entry._type} entry — updateWhere merges declared row sub-fields, so it targets \`array\` entries only`);
|
|
2878
3393
|
}
|
|
@@ -2893,7 +3408,7 @@ function requireArrayValue(entry, op) {
|
|
|
2893
3408
|
}
|
|
2894
3409
|
|
|
2895
3410
|
function applyStatusSet(op, ctx) {
|
|
2896
|
-
const entry = findCurrentActivityEntry(ctx.mutation, op.activity);
|
|
3411
|
+
const entry = invariants.findCurrentActivityEntry(ctx.mutation, op.activity);
|
|
2897
3412
|
if (entry === void 0) throw new Error(`status.set targets activity "${op.activity}" which has no entry in the open stage`);
|
|
2898
3413
|
return applyActivityStatusChange({
|
|
2899
3414
|
entry: entry,
|
|
@@ -2925,7 +3440,7 @@ function locateEntry(ctx, target) {
|
|
|
2925
3440
|
|
|
2926
3441
|
function fieldHost(ctx, scope) {
|
|
2927
3442
|
if (scope === "workflow") return ctx.mutation.fields;
|
|
2928
|
-
const stageEntry = findOpenStageEntry(ctx.mutation);
|
|
3443
|
+
const stageEntry = invariants.findOpenStageEntry(ctx.mutation);
|
|
2929
3444
|
if (scope === "stage") return stageEntry?.fields;
|
|
2930
3445
|
const activity = stageEntry?.activities.find(t => t.name === ctx.activityName);
|
|
2931
3446
|
return activity !== void 0 && activity.fields === void 0 && (activity.fields = []),
|
|
@@ -2997,10 +3512,10 @@ function resolveAtomicOpValue(src, ctx) {
|
|
|
2997
3512
|
}
|
|
2998
3513
|
|
|
2999
3514
|
function readEntryFromMutation(ctx, src) {
|
|
3000
|
-
const scopes = src.scope !== void 0 ? [ src.scope ] : [ "activity", "stage", "workflow" ], stageEntry = findOpenStageEntry(ctx.mutation);
|
|
3515
|
+
const scopes = src.scope !== void 0 ? [ src.scope ] : [ "activity", "stage", "workflow" ], stageEntry = invariants.findOpenStageEntry(ctx.mutation);
|
|
3001
3516
|
for (const scope of scopes) {
|
|
3002
3517
|
let host;
|
|
3003
|
-
scope === "workflow" ? host = ctx.mutation.fields : scope === "stage" ? host = stageEntry?.fields : host = findCurrentActivityEntry(ctx.mutation, ctx.activityName)?.fields;
|
|
3518
|
+
scope === "workflow" ? host = ctx.mutation.fields : scope === "stage" ? host = stageEntry?.fields : host = invariants.findCurrentActivityEntry(ctx.mutation, ctx.activityName)?.fields;
|
|
3004
3519
|
const entry = host?.find(s => s.name === src.field);
|
|
3005
3520
|
if (entry !== void 0) return entry;
|
|
3006
3521
|
}
|
|
@@ -3023,7 +3538,7 @@ async function rowMatches({where: where, rows: rows, ctx: ctx}) {
|
|
|
3023
3538
|
const WHERE_SCOPE_PARAM_NAMES = [ "row", "params", "actor", "now", "self", "stage", "fields", "context", "effects", "effectStatus", "activities", "allActivitiesDone", "anyActivityFailed" ];
|
|
3024
3539
|
|
|
3025
3540
|
function whereParams(ctx) {
|
|
3026
|
-
const activities = findOpenStageEntry(ctx.mutation)?.activities ?? [];
|
|
3541
|
+
const activities = invariants.findOpenStageEntry(ctx.mutation)?.activities ?? [];
|
|
3027
3542
|
return {
|
|
3028
3543
|
params: ctx.params,
|
|
3029
3544
|
actor: ctx.actor ?? null,
|
|
@@ -3048,6 +3563,14 @@ function whereParams(ctx) {
|
|
|
3048
3563
|
|
|
3049
3564
|
function validateDefinition(definition) {
|
|
3050
3565
|
const v2 = createDefinitionValidator();
|
|
3566
|
+
validateConditionSites(v2, definition), validateStart(v2, definition);
|
|
3567
|
+
for (const entry of definition.fields ?? []) v2.checkEntry(entry, `workflow.fields "${entry.name}"`);
|
|
3568
|
+
for (const stage of definition.stages) validateStage(v2, stage);
|
|
3569
|
+
for (const issue of invariants.checkWorkflowInvariants(definition)) v2.errors.push(` · ${invariants.formatIssuePath(issue.path)}: ${issue.message}`);
|
|
3570
|
+
if (v2.errors.length > 0) throw new Error(`validateDefinition("${definition.name}"): ${v2.errors.length} deploy-time validation error${v2.errors.length === 1 ? "" : "s"}:\n` + v2.errors.join(`\n`));
|
|
3571
|
+
}
|
|
3572
|
+
|
|
3573
|
+
function validateConditionSites(v2, definition) {
|
|
3051
3574
|
for (const site of conditionSitesOf(definition)) {
|
|
3052
3575
|
const {address: address} = site;
|
|
3053
3576
|
address.kind !== "editable-field" && v2.checkCondition(site.condition, conditionSiteLabel({
|
|
@@ -3055,12 +3578,11 @@ function validateDefinition(definition) {
|
|
|
3055
3578
|
address: address
|
|
3056
3579
|
}));
|
|
3057
3580
|
}
|
|
3581
|
+
}
|
|
3582
|
+
|
|
3583
|
+
function validateStart(v2, definition) {
|
|
3058
3584
|
definition.start?.filter !== void 0 && v2.report("start.filter", startFilterSyntaxIssues(definition.start.filter));
|
|
3059
3585
|
for (const [index, requirement] of (definition.start?.requirements ?? []).entries()) requirement.type === "groq" && v2.report(`start.requirements[${index}].query`, startRequirementSyntaxIssues(requirement.query));
|
|
3060
|
-
for (const entry of definition.fields ?? []) v2.checkEntry(entry, `workflow.fields "${entry.name}"`);
|
|
3061
|
-
for (const stage of definition.stages) validateStage(v2, stage);
|
|
3062
|
-
for (const issue of invariants.checkWorkflowInvariants(definition)) v2.errors.push(` · ${invariants.formatIssuePath(issue.path)}: ${issue.message}`);
|
|
3063
|
-
if (v2.errors.length > 0) throw new Error(`validateDefinition("${definition.name}"): ${v2.errors.length} deploy-time validation error${v2.errors.length === 1 ? "" : "s"}:\n` + v2.errors.join(`\n`));
|
|
3064
3586
|
}
|
|
3065
3587
|
|
|
3066
3588
|
function createDefinitionValidator() {
|
|
@@ -3091,33 +3613,12 @@ function createDefinitionValidator() {
|
|
|
3091
3613
|
|
|
3092
3614
|
function conditionSiteLabel({stage: stage, address: address}) {
|
|
3093
3615
|
const at = `stage "${stage}"`;
|
|
3094
|
-
|
|
3095
|
-
case "predicate":
|
|
3096
|
-
return `predicate "${address.predicate}"`;
|
|
3097
|
-
|
|
3098
|
-
case "transition":
|
|
3099
|
-
return `${at} transition "${address.transition}" when`;
|
|
3100
|
-
|
|
3101
|
-
case "activity-filter":
|
|
3102
|
-
return `${at} activity "${address.activity}".filter`;
|
|
3103
|
-
|
|
3104
|
-
case "requirement":
|
|
3105
|
-
return `${at} activity "${address.activity}".requirements "${address.requirement}"`;
|
|
3106
|
-
|
|
3107
|
-
case "action":
|
|
3108
|
-
return `${at} activity "${address.activity}" action "${address.action}".filter`;
|
|
3109
|
-
|
|
3110
|
-
case "action-when":
|
|
3111
|
-
return `${at} activity "${address.activity}" action "${address.action}".when`;
|
|
3112
|
-
|
|
3113
|
-
case "editable-override":
|
|
3114
|
-
return `${at}.editable "${address.name}"`;
|
|
3115
|
-
}
|
|
3616
|
+
return address.kind === "predicate" ? `predicate "${address.predicate}"` : address.kind === "transition" ? `${at} transition "${address.transition}" when` : address.kind === "activity-filter" ? `${at} activity "${address.activity}".filter` : address.kind === "requirement" ? `${at} activity "${address.activity}".requirements "${address.requirement}"` : address.kind === "action" ? `${at} activity "${address.activity}" action "${address.action}".filter` : address.kind === "action-when" ? `${at} activity "${address.activity}" action "${address.action}".when` : `${at}.editable "${address.name}"`;
|
|
3116
3617
|
}
|
|
3117
3618
|
|
|
3118
3619
|
function validateStage(v2, stage) {
|
|
3119
3620
|
for (const entry of stage.fields ?? []) v2.checkEntry(entry, `stage "${stage.name}".fields "${entry.name}"`);
|
|
3120
|
-
for (const guard of stage.guards ?? [])
|
|
3621
|
+
for (const guard of stage.guards ?? []) validateGuard({
|
|
3121
3622
|
v: v2,
|
|
3122
3623
|
stageName: stage.name,
|
|
3123
3624
|
guard: guard
|
|
@@ -3129,12 +3630,28 @@ function validateStage(v2, stage) {
|
|
|
3129
3630
|
});
|
|
3130
3631
|
}
|
|
3131
3632
|
|
|
3132
|
-
function
|
|
3633
|
+
function validateGuard({v: v2, stageName: stageName, guard: guard}) {
|
|
3133
3634
|
const where = `stage "${stageName}" guard "${guard.name}"`;
|
|
3134
|
-
|
|
3635
|
+
if (validateGuardMatch({
|
|
3636
|
+
v: v2,
|
|
3637
|
+
where: where,
|
|
3638
|
+
guard: guard
|
|
3639
|
+
}), guard.predicate !== void 0 && guard.predicate !== "") {
|
|
3640
|
+
const issue = guardPredicateSyntaxIssue(guard.predicate);
|
|
3641
|
+
issue !== void 0 && v2.report(`${where} predicate`, [ issue ]);
|
|
3642
|
+
}
|
|
3135
3643
|
for (const [key, expr] of Object.entries(guard.metadata ?? {})) v2.checkGuardRead(expr, `${where} metadata "${key}"`);
|
|
3136
3644
|
}
|
|
3137
3645
|
|
|
3646
|
+
function validateGuardMatch({v: v2, where: where, guard: guard}) {
|
|
3647
|
+
guard.match.actions.length === 0 && v2.report(`${where} match.actions`, [ invariants.GUARD_ACTIONS_REQUIRED_MESSAGE ]);
|
|
3648
|
+
for (const pattern of guard.match.idPatterns ?? []) {
|
|
3649
|
+
const issue = guardIdPatternIssue(pattern, guard.match.actions);
|
|
3650
|
+
issue !== void 0 && v2.report(`${where} match.idPatterns`, [ issue ]);
|
|
3651
|
+
}
|
|
3652
|
+
for (const expr of guard.match.idRefs ?? []) v2.checkGuardRead(expr, `${where} match.idRefs`);
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3138
3655
|
function validateActivity({v: v2, stageName: stageName, activity: activity}) {
|
|
3139
3656
|
const where = `stage "${stageName}" activity "${activity.name}"`;
|
|
3140
3657
|
for (const entry of activity.fields ?? []) v2.checkEntry(entry, `${where}.fields "${entry.name}"`);
|
|
@@ -3239,211 +3756,43 @@ function buildClientForGdr(args) {
|
|
|
3239
3756
|
target: target,
|
|
3240
3757
|
parsed: parsed,
|
|
3241
3758
|
siblings: siblings
|
|
3242
|
-
});
|
|
3243
|
-
};
|
|
3244
|
-
}
|
|
3245
|
-
|
|
3246
|
-
function siblingFor(args) {
|
|
3247
|
-
const {client: client, workflowResource: workflowResource, target: target, parsed: parsed, siblings: siblings} = args, key = `${target.type}:${target.id}`, cached = siblings.get(key);
|
|
3248
|
-
if (cached !== void 0) return cached;
|
|
3249
|
-
if (client.withConfig === void 0) throw new invariants.ContractViolationError(`Cannot route "${invariants.gdrFromResource(target, parsed.documentId)}": the GDR targets ${target.type} "${target.id}", not the workflow resource (${workflowResource.type} "${workflowResource.id}"), and the workflow client cannot derive a sibling client for it (no withConfig). Pass resourceClients to route foreign resources, or use a client with withConfig (e.g. @sanity/client).`);
|
|
3250
|
-
const sibling = client.withConfig(siblingConfig(target));
|
|
3251
|
-
return siblings.set(key, sibling), sibling;
|
|
3252
|
-
}
|
|
3253
|
-
|
|
3254
|
-
function siblingConfig(target) {
|
|
3255
|
-
if (target.type === "dataset") {
|
|
3256
|
-
const {projectId: projectId, dataset: dataset} = invariants.datasetResourceParts(target.id);
|
|
3257
|
-
return {
|
|
3258
|
-
resource: target,
|
|
3259
|
-
projectId: projectId,
|
|
3260
|
-
dataset: dataset
|
|
3261
|
-
};
|
|
3262
|
-
}
|
|
3263
|
-
return {
|
|
3264
|
-
resource: target
|
|
3265
|
-
};
|
|
3266
|
-
}
|
|
3267
|
-
|
|
3268
|
-
const wallClock = () => /* @__PURE__ */ (new Date).toISOString();
|
|
3269
|
-
|
|
3270
|
-
function addMs(instant, ms) {
|
|
3271
|
-
return new Date(Date.parse(instant) + ms).toISOString();
|
|
3272
|
-
}
|
|
3273
|
-
|
|
3274
|
-
function hasPassed(instant, now) {
|
|
3275
|
-
return Date.parse(instant) <= Date.parse(now);
|
|
3276
|
-
}
|
|
3277
|
-
|
|
3278
|
-
const GUARD_DOC_TYPE = "temp.system.guard";
|
|
3279
|
-
|
|
3280
|
-
class MutationGuardDeniedError extends invariants.WorkflowError {
|
|
3281
|
-
denied;
|
|
3282
|
-
documentId;
|
|
3283
|
-
action;
|
|
3284
|
-
constructor(args) {
|
|
3285
|
-
const ids = args.denied.map(d => d.guardId).join(", ");
|
|
3286
|
-
super("mutation-guard-denied", `Mutation on "${args.documentId}" (${args.action}) denied by guard(s) [${ids}]`),
|
|
3287
|
-
this.name = "MutationGuardDeniedError", this.denied = args.denied, this.documentId = args.documentId,
|
|
3288
|
-
this.action = args.action;
|
|
3289
|
-
}
|
|
3290
|
-
static fromGuards(args) {
|
|
3291
|
-
return new MutationGuardDeniedError({
|
|
3292
|
-
documentId: args.documentId,
|
|
3293
|
-
action: args.action,
|
|
3294
|
-
denied: deniedGuardRefs(args.guards)
|
|
3295
|
-
});
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
|
|
3299
|
-
function deniedGuardRefs(guards) {
|
|
3300
|
-
return guards.map(g => ({
|
|
3301
|
-
guardId: g._id,
|
|
3302
|
-
...g.name !== void 0 ? {
|
|
3303
|
-
name: g.name
|
|
3304
|
-
} : {}
|
|
3305
|
-
}));
|
|
3306
|
-
}
|
|
3307
|
-
|
|
3308
|
-
function deniedGuardLabels(denied) {
|
|
3309
|
-
return denied.map(d => d.name ?? d.guardId);
|
|
3310
|
-
}
|
|
3311
|
-
|
|
3312
|
-
function lakeGuardId(args) {
|
|
3313
|
-
return `${GUARD_DOC_TYPE}.${args.instanceDocId}.${args.guardName}`;
|
|
3314
|
-
}
|
|
3315
|
-
|
|
3316
|
-
function compileGuard(args) {
|
|
3317
|
-
return {
|
|
3318
|
-
_id: args.id,
|
|
3319
|
-
_type: GUARD_DOC_TYPE,
|
|
3320
|
-
resourceType: args.resourceType,
|
|
3321
|
-
resourceId: args.resourceId,
|
|
3322
|
-
owner: args.owner,
|
|
3323
|
-
sourceInstanceId: args.sourceInstanceId,
|
|
3324
|
-
sourceDefinition: args.sourceDefinition,
|
|
3325
|
-
sourceStage: args.sourceStage,
|
|
3326
|
-
...args.name !== void 0 ? {
|
|
3327
|
-
name: args.name
|
|
3328
|
-
} : {},
|
|
3329
|
-
...args.description !== void 0 ? {
|
|
3330
|
-
description: args.description
|
|
3331
|
-
} : {},
|
|
3332
|
-
match: args.match,
|
|
3333
|
-
predicate: args.predicate,
|
|
3334
|
-
metadata: args.metadata
|
|
3759
|
+
});
|
|
3335
3760
|
};
|
|
3336
3761
|
}
|
|
3337
3762
|
|
|
3338
|
-
function
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
3345
|
-
return new RegExp(`^${escaped}$`).test(value);
|
|
3763
|
+
function siblingFor(args) {
|
|
3764
|
+
const {client: client, workflowResource: workflowResource, target: target, parsed: parsed, siblings: siblings} = args, key = `${target.type}:${target.id}`, cached = siblings.get(key);
|
|
3765
|
+
if (cached !== void 0) return cached;
|
|
3766
|
+
if (client.withConfig === void 0) throw new invariants.ContractViolationError(`Cannot route "${invariants.gdrFromResource(target, parsed.documentId)}": the GDR targets ${target.type} "${target.id}", not the workflow resource (${workflowResource.type} "${workflowResource.id}"), and the workflow client cannot derive a sibling client for it (no withConfig). Pass resourceClients to route foreign resources, or use a client with withConfig (e.g. @sanity/client).`);
|
|
3767
|
+
const sibling = client.withConfig(siblingConfig(target));
|
|
3768
|
+
return siblings.set(key, sibling), sibling;
|
|
3346
3769
|
}
|
|
3347
3770
|
|
|
3348
|
-
function
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3771
|
+
function siblingConfig(target) {
|
|
3772
|
+
if (target.type === "dataset") {
|
|
3773
|
+
const {projectId: projectId, dataset: dataset} = invariants.datasetResourceParts(target.id);
|
|
3774
|
+
return {
|
|
3775
|
+
resource: target,
|
|
3776
|
+
projectId: projectId,
|
|
3777
|
+
dataset: dataset
|
|
3778
|
+
};
|
|
3354
3779
|
}
|
|
3355
|
-
return !0;
|
|
3356
|
-
}
|
|
3357
|
-
|
|
3358
|
-
function guardPredicateParams(args) {
|
|
3359
3780
|
return {
|
|
3360
|
-
|
|
3361
|
-
mutation: {
|
|
3362
|
-
action: args.action
|
|
3363
|
-
}
|
|
3781
|
+
resource: target
|
|
3364
3782
|
};
|
|
3365
3783
|
}
|
|
3366
3784
|
|
|
3367
|
-
|
|
3368
|
-
const {guard: guard, context: context} = args;
|
|
3369
|
-
if (guard.predicate === "") return !1;
|
|
3370
|
-
const params = guardPredicateParams({
|
|
3371
|
-
guard: guard,
|
|
3372
|
-
action: context.action
|
|
3373
|
-
});
|
|
3374
|
-
try {
|
|
3375
|
-
const tree = groqJs.parse(toGroqJsPredicate(guard.predicate), {
|
|
3376
|
-
mode: "delta",
|
|
3377
|
-
params: params
|
|
3378
|
-
});
|
|
3379
|
-
return await (await groqJs.evaluate(tree, {
|
|
3380
|
-
before: context.before,
|
|
3381
|
-
after: context.after,
|
|
3382
|
-
params: params,
|
|
3383
|
-
...context.identity !== void 0 ? {
|
|
3384
|
-
identity: context.identity
|
|
3385
|
-
} : {}
|
|
3386
|
-
})).get() === !0;
|
|
3387
|
-
} catch {
|
|
3388
|
-
return !1;
|
|
3389
|
-
}
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
async function denyingGuards(args) {
|
|
3393
|
-
const {guards: guards, doc: doc, context: context} = args, denied = [];
|
|
3394
|
-
for (const guard of guards) guardMatches({
|
|
3395
|
-
guard: guard,
|
|
3396
|
-
doc: doc,
|
|
3397
|
-
action: context.action
|
|
3398
|
-
}) && (await evaluateMutationGuard({
|
|
3399
|
-
guard: guard,
|
|
3400
|
-
context: context
|
|
3401
|
-
}) || denied.push(guard));
|
|
3402
|
-
return denied;
|
|
3403
|
-
}
|
|
3404
|
-
|
|
3405
|
-
async function documentActionDenials(args) {
|
|
3406
|
-
const {doc: doc, resource: resource, action: action, guards: guards, identity: identity} = args, enforceable = guards.filter(g => g.resourceType === resource.type && g.resourceId === resource.id);
|
|
3407
|
-
return enforceable.length === 0 ? [] : denyingGuards({
|
|
3408
|
-
guards: enforceable,
|
|
3409
|
-
doc: {
|
|
3410
|
-
id: doc._id,
|
|
3411
|
-
type: doc._type
|
|
3412
|
-
},
|
|
3413
|
-
context: {
|
|
3414
|
-
action: action,
|
|
3415
|
-
before: doc,
|
|
3416
|
-
after: doc,
|
|
3417
|
-
...identity !== void 0 ? {
|
|
3418
|
-
identity: identity
|
|
3419
|
-
} : {}
|
|
3420
|
-
}
|
|
3421
|
-
});
|
|
3422
|
-
}
|
|
3785
|
+
const wallClock = () => /* @__PURE__ */ (new Date).toISOString();
|
|
3423
3786
|
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
return documentActionDenials({
|
|
3427
|
-
doc: instance,
|
|
3428
|
-
resource: instance.workflowResource,
|
|
3429
|
-
action: "update",
|
|
3430
|
-
guards: guards,
|
|
3431
|
-
...identity !== void 0 ? {
|
|
3432
|
-
identity: identity
|
|
3433
|
-
} : {}
|
|
3434
|
-
});
|
|
3787
|
+
function addMs(instant, ms) {
|
|
3788
|
+
return new Date(Date.parse(instant) + ms).toISOString();
|
|
3435
3789
|
}
|
|
3436
3790
|
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
if (denied.length !== 0) throw MutationGuardDeniedError.fromGuards({
|
|
3440
|
-
documentId: args.instance._id,
|
|
3441
|
-
action: "update",
|
|
3442
|
-
guards: denied
|
|
3443
|
-
});
|
|
3791
|
+
function hasPassed(instant, now) {
|
|
3792
|
+
return Date.parse(instant) <= Date.parse(now);
|
|
3444
3793
|
}
|
|
3445
3794
|
|
|
3446
|
-
const DATA_MODEL_VERSION =
|
|
3795
|
+
const DATA_MODEL_VERSION = 9, DATA_MODEL_MIN_READER = 4, DATA_MODEL_MAX_READER = 9, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/workflows/prerelease";
|
|
3447
3796
|
|
|
3448
3797
|
class ReaderModelAcknowledgementError extends invariants.WorkflowError {
|
|
3449
3798
|
code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
|
|
@@ -3583,6 +3932,22 @@ const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
|
|
|
3583
3932
|
compatibility: "reader-floor",
|
|
3584
3933
|
applicability: "detectable",
|
|
3585
3934
|
summary: "Assignee fields may restrict newly assigned users and collective roles by role."
|
|
3935
|
+
}), Object.freeze({
|
|
3936
|
+
id: "split-guard-id-spaces",
|
|
3937
|
+
introducedInModel: 9,
|
|
3938
|
+
minReaderModel: 9,
|
|
3939
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
3940
|
+
compatibility: "reader-floor",
|
|
3941
|
+
applicability: "detectable",
|
|
3942
|
+
summary: "Guards spanning edit and lifecycle id spaces emit independently retractable documents."
|
|
3943
|
+
}), Object.freeze({
|
|
3944
|
+
id: "singular-assignee-lists",
|
|
3945
|
+
introducedInModel: 9,
|
|
3946
|
+
minReaderModel: 9,
|
|
3947
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
3948
|
+
compatibility: "reader-floor",
|
|
3949
|
+
applicability: "detectable",
|
|
3950
|
+
summary: "Singular assignee fields use member lists with at most one user and any number of roles."
|
|
3586
3951
|
}) ]);
|
|
3587
3952
|
|
|
3588
3953
|
function recordOf(value) {
|
|
@@ -3706,6 +4071,25 @@ function hasRoleConstrainedAssignments(document) {
|
|
|
3706
4071
|
return persistedFieldEntries(document).some(entry => entryKindMatches(entry, invariants.assignmentKindAcceptsRoles) && Array.isArray(entry.roles) && entry.roles.length > 0);
|
|
3707
4072
|
}
|
|
3708
4073
|
|
|
4074
|
+
function hasSingularAssigneeLists(document) {
|
|
4075
|
+
const root = recordOf(document);
|
|
4076
|
+
if (root === void 0) return !1;
|
|
4077
|
+
if (typeof root.definitionSnapshot != "string") return persistedFieldEntries(document).some(entry => entryHasKind(entry, "assignee"));
|
|
4078
|
+
const snapshot = parsedDefinitionSnapshot(root);
|
|
4079
|
+
return typeof snapshot?.modelVersion == "number" && isAssignmentListModel(snapshot.modelVersion) && persistedFieldEntries(document).some(entry => entryHasKind(entry, "assignee"));
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
function isMutationGuardAction(action) {
|
|
4083
|
+
return typeof action == "string" && invariants.MUTATION_GUARD_ACTIONS.some(candidate => candidate === action);
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
function hasSplitGuardIdSpaces(document) {
|
|
4087
|
+
return persistedDefinitionTree(document)?.stages.some(stage => recordsAt(stage, "guards").some(guard => {
|
|
4088
|
+
const actions = recordOf(guard.match)?.actions;
|
|
4089
|
+
return Array.isArray(actions) && invariants.mutationGuardRequiresSplitEmission(actions.filter(isMutationGuardAction));
|
|
4090
|
+
})) ?? !1;
|
|
4091
|
+
}
|
|
4092
|
+
|
|
3709
4093
|
const featureDetectors = {
|
|
3710
4094
|
"governed-model-stamps": () => !0,
|
|
3711
4095
|
"subject-field-kind": document => hasFieldKind(document, "subject"),
|
|
@@ -3718,6 +4102,8 @@ const featureDetectors = {
|
|
|
3718
4102
|
"readiness-requirements": hasReadinessRequirements,
|
|
3719
4103
|
"due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime"),
|
|
3720
4104
|
"role-constrained-assignment-fields": hasRoleConstrainedAssignments,
|
|
4105
|
+
"singular-assignee-lists": hasSingularAssigneeLists,
|
|
4106
|
+
"split-guard-id-spaces": hasSplitGuardIdSpaces,
|
|
3721
4107
|
"node-semantics": hasNodeSemantics,
|
|
3722
4108
|
"field-patch-ops": document => hasPersistedOpType(document, [ "field.inc", "field.dec", "field.setIfMissing" ]),
|
|
3723
4109
|
"attributes-condition-var": () => !0
|
|
@@ -3857,8 +4243,93 @@ function findActivityNode(args) {
|
|
|
3857
4243
|
return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
|
|
3858
4244
|
}
|
|
3859
4245
|
|
|
4246
|
+
function requirementDescriptor(requirement) {
|
|
4247
|
+
return {
|
|
4248
|
+
name: requirement.name,
|
|
4249
|
+
...requirement.title !== void 0 ? {
|
|
4250
|
+
title: requirement.title
|
|
4251
|
+
} : {},
|
|
4252
|
+
...requirement.description !== void 0 ? {
|
|
4253
|
+
description: requirement.description
|
|
4254
|
+
} : {}
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4257
|
+
|
|
4258
|
+
function subjectDenialLabels(denied) {
|
|
4259
|
+
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
4260
|
+
}
|
|
4261
|
+
|
|
4262
|
+
class ActionDisabledError extends invariants.WorkflowError {
|
|
4263
|
+
reason;
|
|
4264
|
+
activity;
|
|
4265
|
+
action;
|
|
4266
|
+
constructor(args) {
|
|
4267
|
+
super("action-disabled", formatDisabledReason({
|
|
4268
|
+
activity: args.activity,
|
|
4269
|
+
action: args.action,
|
|
4270
|
+
reason: args.reason
|
|
4271
|
+
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
4272
|
+
this.action = args.action;
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
class StartNotAllowedError extends invariants.WorkflowError {
|
|
4277
|
+
definition;
|
|
4278
|
+
unmetRequirements;
|
|
4279
|
+
constructor(args) {
|
|
4280
|
+
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
4281
|
+
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
function actionRendering(action) {
|
|
4286
|
+
const kind = action.disabledReason?.kind;
|
|
4287
|
+
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
4288
|
+
}
|
|
4289
|
+
|
|
4290
|
+
const disabledReasonDetail = {
|
|
4291
|
+
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
4292
|
+
"cascade-fired": r => `the action is cascade-fired (when: ${JSON.stringify(r.when)}) — the engine fires it on truth; it cannot be invoked via fireAction`,
|
|
4293
|
+
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
4294
|
+
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
4295
|
+
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
4296
|
+
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
4297
|
+
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.map(requirement => requirement.name).join(", ")}`,
|
|
4298
|
+
"subject-permission-denied": r => `missing subject permission(s): ${subjectDenialLabels(r.denied).join(", ")}`
|
|
4299
|
+
};
|
|
4300
|
+
|
|
4301
|
+
function actionDisabledDetail(reason) {
|
|
4302
|
+
return disabledReasonDetail[reason.kind](reason);
|
|
4303
|
+
}
|
|
4304
|
+
|
|
4305
|
+
function formatDisabledReason({activity: activity, action: action, reason: reason}) {
|
|
4306
|
+
return `Action "${activity}:${action}" is not allowed: ${actionDisabledDetail(reason)}`;
|
|
4307
|
+
}
|
|
4308
|
+
|
|
4309
|
+
class EditFieldDeniedError extends invariants.WorkflowError {
|
|
4310
|
+
reason;
|
|
4311
|
+
target;
|
|
4312
|
+
constructor(args) {
|
|
4313
|
+
super("edit-field-denied", formatEditDisabledReason(args.target, args.reason)),
|
|
4314
|
+
this.name = "EditFieldDeniedError", this.reason = args.reason, this.target = args.target;
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
const editDisabledReasonDetail = {
|
|
4319
|
+
"not-editable": () => "field is not declared editable",
|
|
4320
|
+
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
4321
|
+
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
4322
|
+
"edit-window-closed": r => `edit window closed (${r.detail})`,
|
|
4323
|
+
"editor-not-permitted": r => `editor not permitted (${r.predicate})`
|
|
4324
|
+
};
|
|
4325
|
+
|
|
4326
|
+
function formatEditDisabledReason(target, reason) {
|
|
4327
|
+
const detail = editDisabledReasonDetail[reason.kind](reason), where = target.activity !== void 0 ? `${target.activity}.${target.field}` : target.field;
|
|
4328
|
+
return `Field "${target.scope}:${where}" is not editable: ${detail}`;
|
|
4329
|
+
}
|
|
4330
|
+
|
|
3860
4331
|
function liveChildrenField(instance) {
|
|
3861
|
-
const live = liveSubworkflows(instance).length;
|
|
4332
|
+
const live = invariants.liveSubworkflows(instance).length;
|
|
3862
4333
|
return live > 0 ? {
|
|
3863
4334
|
liveChildren: live
|
|
3864
4335
|
} : {};
|
|
@@ -3879,11 +4350,12 @@ function diagnoseInputFromEvaluation(evaluation) {
|
|
|
3879
4350
|
}
|
|
3880
4351
|
|
|
3881
4352
|
function openStage(instance) {
|
|
3882
|
-
return findOpenStageEntry(instance);
|
|
4353
|
+
return invariants.findOpenStageEntry(instance);
|
|
3883
4354
|
}
|
|
3884
4355
|
|
|
3885
4356
|
function assigneesOf(stage, activityName) {
|
|
3886
|
-
|
|
4357
|
+
const entry = stage?.activities.find(t => t.name === activityName);
|
|
4358
|
+
return [ ...invariants.assignmentMembers(entry?.fields ?? []) ];
|
|
3887
4359
|
}
|
|
3888
4360
|
|
|
3889
4361
|
function isResolved(status) {
|
|
@@ -3916,11 +4388,16 @@ function failedActivityCause(input) {
|
|
|
3916
4388
|
|
|
3917
4389
|
function waitingState(input) {
|
|
3918
4390
|
const active = input.activities.find(t => t.status === "active" && (t.activity.actions ?? []).length > 0 && (t.unmetRequirements ?? []).length === 0);
|
|
3919
|
-
if (active
|
|
4391
|
+
if (active === void 0) return;
|
|
4392
|
+
const actions = active.actions.filter(action => actionRendering(action) === "button" && action.allowed).map(action => action.action.name), hasManualAction = active.actions.some(action => !invariants.isCascadeFired(action.action));
|
|
4393
|
+
let waitingFor = "automation";
|
|
4394
|
+
return actions.length > 0 ? waitingFor = "caller" : hasManualAction && (waitingFor = "manual-action"),
|
|
4395
|
+
{
|
|
3920
4396
|
state: "waiting",
|
|
3921
4397
|
activity: active.activity.name,
|
|
3922
4398
|
assignees: input.assignees[active.activity.name] ?? [],
|
|
3923
|
-
actions:
|
|
4399
|
+
actions: actions,
|
|
4400
|
+
waitingFor: waitingFor
|
|
3924
4401
|
};
|
|
3925
4402
|
}
|
|
3926
4403
|
|
|
@@ -3950,7 +4427,7 @@ function stuckFromDocumentState(input) {
|
|
|
3950
4427
|
}
|
|
3951
4428
|
|
|
3952
4429
|
function documentStuckCause(args) {
|
|
3953
|
-
const stage = findOpenStageEntry(args.instance);
|
|
4430
|
+
const stage = invariants.findOpenStageEntry(args.instance);
|
|
3954
4431
|
if (stage !== void 0) return stuckFromDocumentState({
|
|
3955
4432
|
instance: args.instance,
|
|
3956
4433
|
activities: stage.activities.map(entry => ({
|
|
@@ -4046,7 +4523,7 @@ function isClaimExpired(claim, now) {
|
|
|
4046
4523
|
return claim.leaseExpiresAt === void 0 || hasPassed(claim.leaseExpiresAt, now);
|
|
4047
4524
|
}
|
|
4048
4525
|
|
|
4049
|
-
const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ];
|
|
4526
|
+
const EFFECT_RUN_STATUSES = groqConditionDescribe._exhaustiveOptions()([ "done", "failed", "cancelled" ]);
|
|
4050
4527
|
|
|
4051
4528
|
function userLoginProvider(user) {
|
|
4052
4529
|
return user?.provider ?? user?.loginProvider;
|
|
@@ -4299,7 +4776,7 @@ function collectWatchRefs(instance) {
|
|
|
4299
4776
|
}
|
|
4300
4777
|
|
|
4301
4778
|
function collectSubjectRefs(instance) {
|
|
4302
|
-
const stage = findOpenStageEntry(instance), activityFields = stage?.activities.map(activity => activity.fields) ?? [];
|
|
4779
|
+
const stage = invariants.findOpenStageEntry(instance), activityFields = stage?.activities.map(activity => activity.fields) ?? [];
|
|
4303
4780
|
return [ ...entryDocRefs(instance.fields), ...entryDocRefs(stage?.fields), ...activityFields.flatMap(entryDocRefs), ...entryReleaseRefs(instance.fields), ...entryReleaseRefs(stage?.fields), ...activityFields.flatMap(entryReleaseRefs) ];
|
|
4304
4781
|
}
|
|
4305
4782
|
|
|
@@ -4317,7 +4794,7 @@ function foreignSubjectRefs(instance) {
|
|
|
4317
4794
|
}
|
|
4318
4795
|
|
|
4319
4796
|
function liveSubworkflowRefs(instance) {
|
|
4320
|
-
return liveSubworkflows(instance).map(row => row.ref);
|
|
4797
|
+
return invariants.liveSubworkflows(instance).map(row => row.ref);
|
|
4321
4798
|
}
|
|
4322
4799
|
|
|
4323
4800
|
function readsRaw(ref) {
|
|
@@ -4800,32 +5277,122 @@ function normalizeQueryResult({entryType: entryType, raw: raw, workflowResource:
|
|
|
4800
5277
|
}
|
|
4801
5278
|
}
|
|
4802
5279
|
|
|
4803
|
-
function coerceGdrShape(raw, workflowResource) {
|
|
4804
|
-
if (!("id" in raw) || !("type" in raw)) return null;
|
|
4805
|
-
const r = raw;
|
|
4806
|
-
return typeof r.id != "string" || typeof r.type != "string" ? null : invariants.isGdrUri(r.id) ? {
|
|
4807
|
-
id: r.id,
|
|
4808
|
-
type: r.type
|
|
4809
|
-
} : workflowResource ? {
|
|
4810
|
-
id: invariants.toPhysicalGdr(r.id, workflowResource),
|
|
4811
|
-
type: r.type
|
|
4812
|
-
} : null;
|
|
5280
|
+
function coerceGdrShape(raw, workflowResource) {
|
|
5281
|
+
if (!("id" in raw) || !("type" in raw)) return null;
|
|
5282
|
+
const r = raw;
|
|
5283
|
+
return typeof r.id != "string" || typeof r.type != "string" ? null : invariants.isGdrUri(r.id) ? {
|
|
5284
|
+
id: r.id,
|
|
5285
|
+
type: r.type
|
|
5286
|
+
} : workflowResource ? {
|
|
5287
|
+
id: invariants.toPhysicalGdr(r.id, workflowResource),
|
|
5288
|
+
type: r.type
|
|
5289
|
+
} : null;
|
|
5290
|
+
}
|
|
5291
|
+
|
|
5292
|
+
function coerceRefEnvelope(raw, workflowResource) {
|
|
5293
|
+
if (!("_ref" in raw)) return null;
|
|
5294
|
+
const r = raw;
|
|
5295
|
+
return typeof r._ref != "string" || !workflowResource ? null : {
|
|
5296
|
+
id: invariants.toPhysicalGdr(r._ref, workflowResource),
|
|
5297
|
+
type: "document"
|
|
5298
|
+
};
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
function coerceToGdr(raw, workflowResource) {
|
|
5302
|
+
return raw == null ? null : typeof raw == "object" ? coerceGdrShape(raw, workflowResource) ?? coerceRefEnvelope(raw, workflowResource) : typeof raw == "string" && workflowResource ? {
|
|
5303
|
+
id: invariants.toPhysicalGdr(raw, workflowResource),
|
|
5304
|
+
type: "document"
|
|
5305
|
+
} : null;
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
const NOW = {
|
|
5309
|
+
variable: "now",
|
|
5310
|
+
path: []
|
|
5311
|
+
}, LAST_REPRESENTABLE_MS = 864e13;
|
|
5312
|
+
|
|
5313
|
+
function readsNowIn(reads) {
|
|
5314
|
+
return reads.some(read => read.variable === "now");
|
|
5315
|
+
}
|
|
5316
|
+
|
|
5317
|
+
function readsNow(condition) {
|
|
5318
|
+
return readsNowIn(groqConditionDescribe.analyzeCondition(condition).reads);
|
|
5319
|
+
}
|
|
5320
|
+
|
|
5321
|
+
async function stageTimeSites(args) {
|
|
5322
|
+
const {definition: definition, stage: stage, scopeFor: scopeFor} = args, sites = [];
|
|
5323
|
+
for (const site of conditionSitesOf(definition)) {
|
|
5324
|
+
if (site.stage !== stage || site.address.kind === "editable-override" || !readsNow(site.condition)) continue;
|
|
5325
|
+
const activity = "activity" in site.address ? site.address.activity : void 0;
|
|
5326
|
+
sites.push({
|
|
5327
|
+
condition: site.condition,
|
|
5328
|
+
params: await scopeFor(activity)
|
|
5329
|
+
});
|
|
5330
|
+
}
|
|
5331
|
+
return sites;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
async function nextEvaluationInstant(args) {
|
|
5335
|
+
const {sites: sites, dataset: dataset, now: now} = args, boundaries = [];
|
|
5336
|
+
for (const site of sites) {
|
|
5337
|
+
const boundary = await siteBoundary({
|
|
5338
|
+
...site,
|
|
5339
|
+
dataset: dataset,
|
|
5340
|
+
now: now
|
|
5341
|
+
});
|
|
5342
|
+
boundary !== void 0 && boundaries.push(boundary);
|
|
5343
|
+
}
|
|
5344
|
+
return [ ...boundaries ].sort(byInstant)[0];
|
|
5345
|
+
}
|
|
5346
|
+
|
|
5347
|
+
function byInstant(a, b) {
|
|
5348
|
+
return Date.parse(a) - Date.parse(b);
|
|
5349
|
+
}
|
|
5350
|
+
|
|
5351
|
+
async function siteBoundary(args) {
|
|
5352
|
+
const {condition: condition, params: params, dataset: dataset, now: now} = args, insight = await groqConditionDescribe.explainCondition({
|
|
5353
|
+
condition: condition,
|
|
5354
|
+
dataset: dataset,
|
|
5355
|
+
params: params
|
|
5356
|
+
});
|
|
5357
|
+
for (const candidate of await candidateInstants({
|
|
5358
|
+
insight: insight,
|
|
5359
|
+
params: params,
|
|
5360
|
+
dataset: dataset,
|
|
5361
|
+
now: now
|
|
5362
|
+
})) if ((await groqConditionDescribe.whatIfCondition({
|
|
5363
|
+
condition: condition,
|
|
5364
|
+
dataset: dataset,
|
|
5365
|
+
params: params,
|
|
5366
|
+
assign: {
|
|
5367
|
+
target: NOW,
|
|
5368
|
+
value: candidate
|
|
5369
|
+
}
|
|
5370
|
+
})).changed) return candidate;
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
async function candidateInstants(args) {
|
|
5374
|
+
const {insight: insight, params: params, dataset: dataset, now: now} = args, comparands = [];
|
|
5375
|
+
for (const atom of insight.atoms) readsNowIn(atom.atom.reads) && comparands.push(...await comparandsOf({
|
|
5376
|
+
atom: atom,
|
|
5377
|
+
params: params,
|
|
5378
|
+
dataset: dataset
|
|
5379
|
+
}));
|
|
5380
|
+
const instants = comparands.filter(invariants.isParseableInstant).map(normalizeInstant).filter(instant => Date.parse(instant) < LAST_REPRESENTABLE_MS).flatMap(instant => [ instant, addMs(instant, 1) ]).filter(instant => !hasPassed(instant, now));
|
|
5381
|
+
return [ ...new Set(instants) ].sort(byInstant);
|
|
4813
5382
|
}
|
|
4814
5383
|
|
|
4815
|
-
function
|
|
4816
|
-
|
|
4817
|
-
const r = raw;
|
|
4818
|
-
return typeof r._ref != "string" || !workflowResource ? null : {
|
|
4819
|
-
id: invariants.toPhysicalGdr(r._ref, workflowResource),
|
|
4820
|
-
type: "document"
|
|
4821
|
-
};
|
|
5384
|
+
function normalizeInstant(value) {
|
|
5385
|
+
return new Date(Date.parse(value)).toISOString();
|
|
4822
5386
|
}
|
|
4823
5387
|
|
|
4824
|
-
function
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
5388
|
+
async function comparandsOf(args) {
|
|
5389
|
+
const {atom: atom, params: params, dataset: dataset} = args, requirement = atom.requirement, values = requirement !== void 0 && requirement.target.variable === "now" && "value" in requirement ? [ requirement.value ] : [];
|
|
5390
|
+
for (const read of atom.atom.reads) read.variable !== "now" && values.push(await groqConditionDescribe.runGroq({
|
|
5391
|
+
groq: groqConditionDescribe.formatRead(read),
|
|
5392
|
+
params: params,
|
|
5393
|
+
dataset: dataset
|
|
5394
|
+
}));
|
|
5395
|
+
return values;
|
|
4829
5396
|
}
|
|
4830
5397
|
|
|
4831
5398
|
const NonEmpty = invariants.NonEmptyString, PersistedAssignmentRolesSchema = v__namespace.pipe(v__namespace.array(invariants.NonEmptyString), v__namespace.minLength(1, "assignment roles must not be empty")), UnknownRecord = v__namespace.record(v__namespace.string(), v__namespace.unknown()), PersistedChoiceOptionsSchema = v__namespace.looseObject({
|
|
@@ -4880,7 +5447,7 @@ function fieldArm(kind, value) {
|
|
|
4880
5447
|
};
|
|
4881
5448
|
}
|
|
4882
5449
|
|
|
4883
|
-
const OptionalRefTypes = v__namespace.exactOptional(v__namespace.array(v__namespace.string())),
|
|
5450
|
+
const OptionalRefTypes = v__namespace.exactOptional(v__namespace.array(v__namespace.string())), RawResolvedFieldEntrySchema = v__namespace.variant("_type", [ v__namespace.looseObject(invariants.tolerantEntries()({
|
|
4884
5451
|
...fieldArm("doc.ref", invariants.fieldValueSchemas["doc.ref"]),
|
|
4885
5452
|
types: OptionalRefTypes
|
|
4886
5453
|
})), v__namespace.looseObject(invariants.tolerantEntries()({
|
|
@@ -4901,7 +5468,7 @@ const OptionalRefTypes = v__namespace.exactOptional(v__namespace.array(v__namesp
|
|
|
4901
5468
|
})), v__namespace.looseObject(invariants.tolerantEntries()({
|
|
4902
5469
|
...fieldArm("array", v__namespace.array(UnknownRecord)),
|
|
4903
5470
|
of: v__namespace.array(PersistedFieldShapeSchema)
|
|
4904
|
-
})) ]), EffectOriginSchema = invariants.tolerantObject()({
|
|
5471
|
+
})) ]), ResolvedFieldEntrySchema = v__namespace.pipe(RawResolvedFieldEntrySchema, v__namespace.transform(normalizeNestedAssignmentValues)), EffectOriginSchema = invariants.tolerantObject()({
|
|
4905
5472
|
kind: v__namespace.literal("action"),
|
|
4906
5473
|
name: NonEmpty
|
|
4907
5474
|
}), PendingEffectClaimSchema = invariants.tolerantObject()({
|
|
@@ -5762,6 +6329,25 @@ function buildInstanceBase(args) {
|
|
|
5762
6329
|
};
|
|
5763
6330
|
}
|
|
5764
6331
|
|
|
6332
|
+
function instanceDocumentForWrite(instance) {
|
|
6333
|
+
const listModel = writesSingularAssignmentLists(instance);
|
|
6334
|
+
return {
|
|
6335
|
+
...instance,
|
|
6336
|
+
fields: assignmentFieldsForWrite(instance.fields, listModel),
|
|
6337
|
+
stages: assignmentStagesForWrite(instance.stages, listModel)
|
|
6338
|
+
};
|
|
6339
|
+
}
|
|
6340
|
+
|
|
6341
|
+
function memoizedBy(compute) {
|
|
6342
|
+
const cache = /* @__PURE__ */ new Map;
|
|
6343
|
+
return key => {
|
|
6344
|
+
const hit = cache.get(key);
|
|
6345
|
+
if (hit !== void 0) return hit;
|
|
6346
|
+
const value = (async () => compute(key))();
|
|
6347
|
+
return cache.set(key, value), value;
|
|
6348
|
+
};
|
|
6349
|
+
}
|
|
6350
|
+
|
|
5765
6351
|
async function hydrateSnapshot(args) {
|
|
5766
6352
|
const {client: client, clientForGdr: clientForGdr, instance: instance, overlay: overlay} = args, loaded = [], visited = /* @__PURE__ */ new Set;
|
|
5767
6353
|
loaded.push({
|
|
@@ -5912,16 +6498,26 @@ function loadCallContext({client: client, instanceId: instanceId, options: optio
|
|
|
5912
6498
|
|
|
5913
6499
|
async function retryOnRevisionConflict(args) {
|
|
5914
6500
|
const {client: client, instanceId: instanceId, options: options, commit: commit, onExhausted: onExhausted} = args;
|
|
5915
|
-
|
|
5916
|
-
|
|
6501
|
+
return retryCommit({
|
|
6502
|
+
load: () => loadCallContext({
|
|
5917
6503
|
client: client,
|
|
5918
6504
|
instanceId: instanceId,
|
|
5919
6505
|
options: options
|
|
5920
|
-
})
|
|
6506
|
+
}),
|
|
6507
|
+
commit: commit,
|
|
6508
|
+
shouldRetry: isInstanceCommitRevisionConflict,
|
|
6509
|
+
onExhausted: onExhausted
|
|
6510
|
+
});
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6513
|
+
async function retryCommit(args) {
|
|
6514
|
+
const {load: load, commit: commit, shouldRetry: shouldRetry, onExhausted: onExhausted} = args;
|
|
6515
|
+
for (let attempt = 1; attempt <= CONCURRENT_COMMIT_MAX_ATTEMPTS; attempt++) {
|
|
6516
|
+
const ctx = await load();
|
|
5921
6517
|
try {
|
|
5922
6518
|
return await commit(ctx);
|
|
5923
6519
|
} catch (error) {
|
|
5924
|
-
if (!
|
|
6520
|
+
if (!shouldRetry(error)) throw error;
|
|
5925
6521
|
}
|
|
5926
6522
|
}
|
|
5927
6523
|
throw onExhausted();
|
|
@@ -5969,6 +6565,22 @@ async function ctxConditionParams(ctx, opts) {
|
|
|
5969
6565
|
}, opts);
|
|
5970
6566
|
}
|
|
5971
6567
|
|
|
6568
|
+
async function ctxNextEvaluationAt(ctx) {
|
|
6569
|
+
if (ctx.instance.completedAt !== void 0) return;
|
|
6570
|
+
const scopeFor = memoizedBy(activityName => ctxConditionParams(ctx, activityName === void 0 ? void 0 : {
|
|
6571
|
+
activityName: activityName
|
|
6572
|
+
})), sites = await stageTimeSites({
|
|
6573
|
+
definition: ctx.definition,
|
|
6574
|
+
stage: ctx.instance.currentStage,
|
|
6575
|
+
scopeFor: scopeFor
|
|
6576
|
+
});
|
|
6577
|
+
if (sites.length !== 0) return nextEvaluationInstant({
|
|
6578
|
+
sites: sites,
|
|
6579
|
+
dataset: ctx.snapshot.docs,
|
|
6580
|
+
now: ctx.now
|
|
6581
|
+
});
|
|
6582
|
+
}
|
|
6583
|
+
|
|
5972
6584
|
async function ctxEvaluateConditionOutcome({ctx: ctx, condition: condition, opts: opts}) {
|
|
5973
6585
|
return condition === void 0 ? "satisfied" : invariants.evaluateConditionOutcome({
|
|
5974
6586
|
condition: condition,
|
|
@@ -6597,7 +7209,7 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
6597
7209
|
if (route === null) return null;
|
|
6598
7210
|
const resource = assertSingleResource(route.targets), types = resolveMatchTypes(route.targets, guard.match.types);
|
|
6599
7211
|
return {
|
|
6600
|
-
|
|
7212
|
+
docs: compileGuards({
|
|
6601
7213
|
id: route.guardId,
|
|
6602
7214
|
resourceType: resource.type,
|
|
6603
7215
|
resourceId: resource.id,
|
|
@@ -6629,19 +7241,63 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
6629
7241
|
async function upsertGuard(args) {
|
|
6630
7242
|
const {client: client, doc: doc, exists: exists} = args;
|
|
6631
7243
|
if (!exists) try {
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
7244
|
+
return {
|
|
7245
|
+
created: await client.create(doc, {
|
|
7246
|
+
...SYNC_COMMIT,
|
|
7247
|
+
tag: REQUEST_TAG.guardDeploy
|
|
7248
|
+
})
|
|
7249
|
+
};
|
|
6637
7250
|
} catch (error) {
|
|
6638
7251
|
if (!isCreateIdCollision(error)) throw error;
|
|
6639
7252
|
}
|
|
6640
7253
|
const {_id: _id, _type: _type, _rev: _rev, _createdAt: _createdAt, _updatedAt: _updatedAt, ...body} = doc;
|
|
6641
|
-
await client.patch(doc._id).set(body).commit({
|
|
7254
|
+
return await client.patch(doc._id).set(body).commit({
|
|
6642
7255
|
...SYNC_COMMIT,
|
|
6643
7256
|
tag: REQUEST_TAG.guardRefresh
|
|
7257
|
+
}), {
|
|
7258
|
+
created: void 0
|
|
7259
|
+
};
|
|
7260
|
+
}
|
|
7261
|
+
|
|
7262
|
+
async function retractCreatedGuards(guards) {
|
|
7263
|
+
for (const {client: client, doc: doc} of guards.toReversed()) {
|
|
7264
|
+
if (doc._rev === void 0) return new Error(`Cannot roll back guard ${doc._id}: created document has no revision`);
|
|
7265
|
+
try {
|
|
7266
|
+
const revisionCheck = client.patch(doc._id).set({
|
|
7267
|
+
predicate: doc.predicate
|
|
7268
|
+
}).ifRevisionId(doc._rev);
|
|
7269
|
+
await client.transaction().patch(revisionCheck).delete(doc._id).commit({
|
|
7270
|
+
tag: REQUEST_TAG.guardDeploy
|
|
7271
|
+
});
|
|
7272
|
+
} catch (error) {
|
|
7273
|
+
return error;
|
|
7274
|
+
}
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
|
|
7278
|
+
async function deployResolvedGuard(args) {
|
|
7279
|
+
const {client: client, resourceKey: resourceKey, doc: doc, guard: guard, stageArgs: stageArgs, existingByResource: existingByResource} = args, localized = await localizeGuardMetadata({
|
|
7280
|
+
doc: doc,
|
|
7281
|
+
guard: guard,
|
|
7282
|
+
client: client,
|
|
7283
|
+
instance: stageArgs.instance,
|
|
7284
|
+
definition: stageArgs.definition
|
|
6644
7285
|
});
|
|
7286
|
+
return (await upsertGuard({
|
|
7287
|
+
client: client,
|
|
7288
|
+
doc: localized,
|
|
7289
|
+
exists: existingByResource.get(resourceKey)?.has(doc._id) ?? !1
|
|
7290
|
+
})).created;
|
|
7291
|
+
}
|
|
7292
|
+
|
|
7293
|
+
async function failGuardDeploy(args) {
|
|
7294
|
+
const {cause: cause, stageName: stageName, deployed: deployed, createdGuards: createdGuards, updatedExistingGuard: updatedExistingGuard} = args, rollbackError = updatedExistingGuard ? void 0 : await retractCreatedGuards(createdGuards);
|
|
7295
|
+
throw deployed > 0 && (updatedExistingGuard || rollbackError !== void 0) ? new PartialGuardDeployError({
|
|
7296
|
+
stageName: stageName,
|
|
7297
|
+
deployed: deployed,
|
|
7298
|
+
cause: cause,
|
|
7299
|
+
rollbackError: rollbackError
|
|
7300
|
+
}) : cause;
|
|
6645
7301
|
}
|
|
6646
7302
|
|
|
6647
7303
|
function resolvedStageGuards(args) {
|
|
@@ -6654,10 +7310,12 @@ function resolvedStageGuards(args) {
|
|
|
6654
7310
|
now: args.now,
|
|
6655
7311
|
snapshot: args.snapshot
|
|
6656
7312
|
});
|
|
6657
|
-
resolved
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
7313
|
+
if (resolved === null) continue;
|
|
7314
|
+
const client = args.clientForGdr(resolved.routeGdr), resourceKey = invariants.resourceGdr(invariants.resourceFromParsed(resolved.routeGdr));
|
|
7315
|
+
for (const doc of resolved.docs) out.push({
|
|
7316
|
+
client: client,
|
|
7317
|
+
resourceKey: resourceKey,
|
|
7318
|
+
value: doc,
|
|
6661
7319
|
guard: guard
|
|
6662
7320
|
});
|
|
6663
7321
|
}
|
|
@@ -6673,10 +7331,15 @@ function resolvedStageGuardRoutes(args) {
|
|
|
6673
7331
|
}, out = [];
|
|
6674
7332
|
for (const guard of stage?.guards ?? []) {
|
|
6675
7333
|
const route = resolveGuardRoute(guard, ctx);
|
|
6676
|
-
route
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
7334
|
+
if (route === null) continue;
|
|
7335
|
+
const client = args.clientForGdr(route.routeGdr), resourceKey = invariants.resourceGdr(invariants.resourceFromParsed(route.routeGdr));
|
|
7336
|
+
for (const guardId of compiledGuardIds({
|
|
7337
|
+
id: route.guardId,
|
|
7338
|
+
actions: guard.match.actions
|
|
7339
|
+
})) out.push({
|
|
7340
|
+
client: client,
|
|
7341
|
+
resourceKey: resourceKey,
|
|
7342
|
+
value: guardId
|
|
6680
7343
|
});
|
|
6681
7344
|
}
|
|
6682
7345
|
return out;
|
|
@@ -6732,26 +7395,30 @@ async function deployStageGuards(args) {
|
|
|
6732
7395
|
if (live === void 0 || live.currentStage !== args.stageName || live.abortedAt !== void 0) return;
|
|
6733
7396
|
const routed = resolvedStageGuards(args), existingByResource = await existingGuardIds(groupByResource(routed));
|
|
6734
7397
|
let deployed = 0;
|
|
7398
|
+
const createdGuards = [];
|
|
7399
|
+
let updatedExistingGuard = !1;
|
|
6735
7400
|
for (const {client: client, resourceKey: resourceKey, value: doc, guard: guard} of routed) {
|
|
6736
7401
|
try {
|
|
6737
|
-
const
|
|
7402
|
+
const created = await deployResolvedGuard({
|
|
7403
|
+
client: client,
|
|
7404
|
+
resourceKey: resourceKey,
|
|
6738
7405
|
doc: doc,
|
|
6739
7406
|
guard: guard,
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
definition: args.definition
|
|
7407
|
+
stageArgs: args,
|
|
7408
|
+
existingByResource: existingByResource
|
|
6743
7409
|
});
|
|
6744
|
-
|
|
7410
|
+
created === void 0 ? updatedExistingGuard = !0 : createdGuards.push({
|
|
6745
7411
|
client: client,
|
|
6746
|
-
doc:
|
|
6747
|
-
exists: existingByResource.get(resourceKey)?.has(doc._id) ?? !1
|
|
7412
|
+
doc: created
|
|
6748
7413
|
});
|
|
6749
7414
|
} catch (cause) {
|
|
6750
|
-
|
|
7415
|
+
await failGuardDeploy({
|
|
7416
|
+
cause: cause,
|
|
6751
7417
|
stageName: args.stageName,
|
|
6752
7418
|
deployed: deployed,
|
|
6753
|
-
|
|
6754
|
-
|
|
7419
|
+
createdGuards: createdGuards,
|
|
7420
|
+
updatedExistingGuard: updatedExistingGuard
|
|
7421
|
+
});
|
|
6755
7422
|
}
|
|
6756
7423
|
deployed += 1;
|
|
6757
7424
|
}
|
|
@@ -6830,9 +7497,9 @@ async function commitAbort({ctx: ctx, reason: reason, requestRecord: requestReco
|
|
|
6830
7497
|
record: requestRecord,
|
|
6831
7498
|
now: ctx.now
|
|
6832
7499
|
});
|
|
6833
|
-
const at = ctx.now, openEntry = findOpenStageEntry(mutation);
|
|
7500
|
+
const at = ctx.now, openEntry = invariants.findOpenStageEntry(mutation);
|
|
6834
7501
|
openEntry !== void 0 && (openEntry.exitedAt = at);
|
|
6835
|
-
for (const row of liveSubworkflows(mutation)) condemnSubworkflow(row, {
|
|
7502
|
+
for (const row of invariants.liveSubworkflows(mutation)) invariants.condemnSubworkflow(row, {
|
|
6836
7503
|
at: at,
|
|
6837
7504
|
reason: "parent instance aborted"
|
|
6838
7505
|
});
|
|
@@ -6983,7 +7650,8 @@ async function persistThenDeploy({ctx: ctx, mutation: mutation, deploy: deploy})
|
|
|
6983
7650
|
committedRev: committed._rev,
|
|
6984
7651
|
restore: instanceStateFields({
|
|
6985
7652
|
...ctx.instance,
|
|
6986
|
-
minReaderModel: minReaderModelOf(ctx.instance)
|
|
7653
|
+
minReaderModel: minReaderModelOf(ctx.instance),
|
|
7654
|
+
definitionModelVersion: definitionAssignmentModel(ctx.instance)
|
|
6987
7655
|
}),
|
|
6988
7656
|
unset: ctx.instance.completedAt === void 0 ? [ "completedAt" ] : [],
|
|
6989
7657
|
reversible: !spawned,
|
|
@@ -7039,7 +7707,7 @@ function subworkflowsOnExit(sub) {
|
|
|
7039
7707
|
|
|
7040
7708
|
async function spawnSubworkflows({ctx: ctx, mutation: mutation, activity: activity, action: action, sub: sub, actor: actor}) {
|
|
7041
7709
|
assertSpawnDepth(ctx, activity);
|
|
7042
|
-
const openEntry = findOpenStageEntry(mutation);
|
|
7710
|
+
const openEntry = invariants.findOpenStageEntry(mutation);
|
|
7043
7711
|
if (openEntry === void 0) throw new Error(`Mutation invariant broken: no open StageEntry while spawning on activity "${activity.name}" of ${ctx.instance._id}`);
|
|
7044
7712
|
const definition = await requireChildDefinition({
|
|
7045
7713
|
ctx: ctx,
|
|
@@ -7054,7 +7722,7 @@ async function spawnSubworkflows({ctx: ctx, mutation: mutation, activity: activi
|
|
|
7054
7722
|
activity: activity.name,
|
|
7055
7723
|
action: action.name,
|
|
7056
7724
|
instanceId: ctx.instance._id
|
|
7057
|
-
}), live = liveSubworkflows(mutation).filter(r => r.activity === activity.name && r.action === action.name && r.definition === sub.definition.name && r.abortPending === void 0);
|
|
7725
|
+
}), live = invariants.liveSubworkflows(mutation).filter(r => r.activity === activity.name && r.action === action.name && r.definition === sub.definition.name && r.abortPending === void 0);
|
|
7058
7726
|
adoptRediscoveredRows({
|
|
7059
7727
|
mutation: mutation,
|
|
7060
7728
|
live: live,
|
|
@@ -7193,8 +7861,8 @@ function condemnOnExitCohorts({mutation: mutation, stage: stage, exitedEntry: ex
|
|
|
7193
7861
|
action: action.name
|
|
7194
7862
|
})));
|
|
7195
7863
|
for (const cohort of abortCohorts) {
|
|
7196
|
-
const owed = liveSubworkflows(mutation).filter(row => row.activity === cohort.activity && row.action === cohort.action && row.stageEntry === exitedEntry._key);
|
|
7197
|
-
for (const row of owed) condemnSubworkflow(row, {
|
|
7864
|
+
const owed = invariants.liveSubworkflows(mutation).filter(row => row.activity === cohort.activity && row.action === cohort.action && row.stageEntry === exitedEntry._key);
|
|
7865
|
+
for (const row of owed) invariants.condemnSubworkflow(row, {
|
|
7198
7866
|
at: at,
|
|
7199
7867
|
reason: `stage "${stage.name}" exited with the child still live (onExit: "abort" on action "${cohort.action}" of activity "${cohort.activity}")`
|
|
7200
7868
|
});
|
|
@@ -7557,7 +8225,7 @@ function emitStageTransitioned({ctx: ctx, nextStage: nextStage, at: at, via: via
|
|
|
7557
8225
|
}
|
|
7558
8226
|
|
|
7559
8227
|
function exitOpenStage({mutation: mutation, stage: stage, at: at}) {
|
|
7560
|
-
const priorEntry = findOpenStageEntry(mutation);
|
|
8228
|
+
const priorEntry = invariants.findOpenStageEntry(mutation);
|
|
7561
8229
|
priorEntry !== void 0 && (priorEntry.exitedAt = at, condemnOnExitCohorts({
|
|
7562
8230
|
mutation: mutation,
|
|
7563
8231
|
stage: stage,
|
|
@@ -8078,91 +8746,6 @@ async function callerBoundVarsForCall(args) {
|
|
|
8078
8746
|
});
|
|
8079
8747
|
}
|
|
8080
8748
|
|
|
8081
|
-
function requirementDescriptor(requirement) {
|
|
8082
|
-
return {
|
|
8083
|
-
name: requirement.name,
|
|
8084
|
-
...requirement.title !== void 0 ? {
|
|
8085
|
-
title: requirement.title
|
|
8086
|
-
} : {},
|
|
8087
|
-
...requirement.description !== void 0 ? {
|
|
8088
|
-
description: requirement.description
|
|
8089
|
-
} : {}
|
|
8090
|
-
};
|
|
8091
|
-
}
|
|
8092
|
-
|
|
8093
|
-
function subjectDenialLabels(denied) {
|
|
8094
|
-
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
8095
|
-
}
|
|
8096
|
-
|
|
8097
|
-
class ActionDisabledError extends invariants.WorkflowError {
|
|
8098
|
-
reason;
|
|
8099
|
-
activity;
|
|
8100
|
-
action;
|
|
8101
|
-
constructor(args) {
|
|
8102
|
-
super("action-disabled", formatDisabledReason({
|
|
8103
|
-
activity: args.activity,
|
|
8104
|
-
action: args.action,
|
|
8105
|
-
reason: args.reason
|
|
8106
|
-
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
8107
|
-
this.action = args.action;
|
|
8108
|
-
}
|
|
8109
|
-
}
|
|
8110
|
-
|
|
8111
|
-
class StartNotAllowedError extends invariants.WorkflowError {
|
|
8112
|
-
definition;
|
|
8113
|
-
unmetRequirements;
|
|
8114
|
-
constructor(args) {
|
|
8115
|
-
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
8116
|
-
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
8117
|
-
}
|
|
8118
|
-
}
|
|
8119
|
-
|
|
8120
|
-
function actionRendering(action) {
|
|
8121
|
-
const kind = action.disabledReason?.kind;
|
|
8122
|
-
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
8123
|
-
}
|
|
8124
|
-
|
|
8125
|
-
const disabledReasonDetail = {
|
|
8126
|
-
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
8127
|
-
"cascade-fired": r => `the action is cascade-fired (when: ${JSON.stringify(r.when)}) — the engine fires it on truth; it cannot be invoked via fireAction`,
|
|
8128
|
-
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
8129
|
-
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
8130
|
-
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
8131
|
-
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
8132
|
-
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.map(requirement => requirement.name).join(", ")}`,
|
|
8133
|
-
"subject-permission-denied": r => `missing subject permission(s): ${subjectDenialLabels(r.denied).join(", ")}`
|
|
8134
|
-
};
|
|
8135
|
-
|
|
8136
|
-
function actionDisabledDetail(reason) {
|
|
8137
|
-
return disabledReasonDetail[reason.kind](reason);
|
|
8138
|
-
}
|
|
8139
|
-
|
|
8140
|
-
function formatDisabledReason({activity: activity, action: action, reason: reason}) {
|
|
8141
|
-
return `Action "${activity}:${action}" is not allowed: ${actionDisabledDetail(reason)}`;
|
|
8142
|
-
}
|
|
8143
|
-
|
|
8144
|
-
class EditFieldDeniedError extends invariants.WorkflowError {
|
|
8145
|
-
reason;
|
|
8146
|
-
target;
|
|
8147
|
-
constructor(args) {
|
|
8148
|
-
super("edit-field-denied", formatEditDisabledReason(args.target, args.reason)),
|
|
8149
|
-
this.name = "EditFieldDeniedError", this.reason = args.reason, this.target = args.target;
|
|
8150
|
-
}
|
|
8151
|
-
}
|
|
8152
|
-
|
|
8153
|
-
const editDisabledReasonDetail = {
|
|
8154
|
-
"not-editable": () => "field is not declared editable",
|
|
8155
|
-
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
8156
|
-
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
8157
|
-
"edit-window-closed": r => `edit window closed (${r.detail})`,
|
|
8158
|
-
"editor-not-permitted": r => `editor not permitted (${r.predicate})`
|
|
8159
|
-
};
|
|
8160
|
-
|
|
8161
|
-
function formatEditDisabledReason(target, reason) {
|
|
8162
|
-
const detail = editDisabledReasonDetail[reason.kind](reason), where = target.activity !== void 0 ? `${target.activity}.${target.field}` : target.field;
|
|
8163
|
-
return `Field "${target.scope}:${where}" is not editable: ${detail}`;
|
|
8164
|
-
}
|
|
8165
|
-
|
|
8166
8749
|
async function fireAction(args) {
|
|
8167
8750
|
const {client: client, instanceId: instanceId, activity: activity, action: action, params: params, requestRecord: requestRecord, options: options} = args;
|
|
8168
8751
|
return retryOnRevisionConflict({
|
|
@@ -8330,7 +8913,7 @@ async function commitAction({ctx: ctx, activityName: activityName, actionName: a
|
|
|
8330
8913
|
actionName: actionName,
|
|
8331
8914
|
callerParams: callerParams,
|
|
8332
8915
|
options: options
|
|
8333
|
-
}), mutation =
|
|
8916
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
8334
8917
|
recordProcessedRequest({
|
|
8335
8918
|
mutation: mutation,
|
|
8336
8919
|
record: requestRecord,
|
|
@@ -8496,7 +9079,7 @@ async function primeInitialStage(args) {
|
|
|
8496
9079
|
})
|
|
8497
9080
|
});
|
|
8498
9081
|
const terminal = isTerminalStage(stage), committed = await client.patch(instance._id).set({
|
|
8499
|
-
stages: [ initialStageEntry ],
|
|
9082
|
+
stages: assignmentStagesForWrite([ initialStageEntry ], writesSingularAssignmentLists(instance)),
|
|
8500
9083
|
lastChangedAt: now,
|
|
8501
9084
|
...terminal ? {
|
|
8502
9085
|
completedAt: now
|
|
@@ -8554,32 +9137,59 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
8554
9137
|
settlingCohorts: settlingCohorts
|
|
8555
9138
|
} : {},
|
|
8556
9139
|
memberRolesLoader: memberRolesLoader
|
|
8557
|
-
}
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
9140
|
+
};
|
|
9141
|
+
let preloadedInstance = instance;
|
|
9142
|
+
return retryCommit({
|
|
9143
|
+
load: async () => {
|
|
9144
|
+
if (preloadedInstance === void 0) return loadContext({
|
|
9145
|
+
client: client,
|
|
9146
|
+
instanceId: instanceId,
|
|
9147
|
+
options: contextOptions
|
|
9148
|
+
});
|
|
9149
|
+
const loaded = preloadedInstance;
|
|
9150
|
+
return preloadedInstance = void 0, buildEngineContext({
|
|
9151
|
+
client: client,
|
|
9152
|
+
instance: loaded,
|
|
9153
|
+
definition: parseDefinitionSnapshot(loaded),
|
|
9154
|
+
...contextOptions
|
|
9155
|
+
});
|
|
9156
|
+
},
|
|
9157
|
+
commit: ctx => commitCascadeHop({
|
|
9158
|
+
ctx: ctx,
|
|
9159
|
+
actor: actor
|
|
9160
|
+
}),
|
|
9161
|
+
shouldRetry: isInstanceCommitRevisionConflict,
|
|
9162
|
+
onExhausted: () => new ConcurrentCascadeError({
|
|
9163
|
+
instanceId: instanceId,
|
|
9164
|
+
attempts: CONCURRENT_COMMIT_MAX_ATTEMPTS
|
|
9165
|
+
})
|
|
8566
9166
|
});
|
|
9167
|
+
}
|
|
9168
|
+
|
|
9169
|
+
async function commitCascadeHop({ctx: ctx, actor: actor}) {
|
|
8567
9170
|
if (isTerminal(ctx)) return {
|
|
8568
9171
|
moved: !1
|
|
8569
9172
|
};
|
|
8570
|
-
const stage = findStage(ctx.definition, ctx.instance.currentStage), mutation =
|
|
9173
|
+
const stage = findStage(ctx.definition, ctx.instance.currentStage), mutation = startRevisionRetryMutation(ctx.instance), fired = await runTriggeredActions({
|
|
8571
9174
|
ctx: ctx,
|
|
8572
9175
|
mutation: mutation,
|
|
8573
9176
|
stage: stage
|
|
8574
9177
|
}), hopCtx = liveViewContext(ctx, mutation), transition = await pickTransition(hopCtx, stage);
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
9178
|
+
if (transition === void 0) {
|
|
9179
|
+
const nextEvaluationAt = await ctxNextEvaluationAt(hopCtx);
|
|
9180
|
+
return fired.fires > 0 && await persistThenMaybeRefresh({
|
|
9181
|
+
ctx: ctx,
|
|
9182
|
+
mutation: mutation,
|
|
9183
|
+
stageName: stage.name,
|
|
9184
|
+
didChangeState: fired.ranFieldOps
|
|
9185
|
+
}), {
|
|
9186
|
+
moved: !1,
|
|
9187
|
+
...nextEvaluationAt !== void 0 ? {
|
|
9188
|
+
nextEvaluationAt: nextEvaluationAt
|
|
9189
|
+
} : {}
|
|
9190
|
+
};
|
|
9191
|
+
}
|
|
9192
|
+
return await commitStageMove({
|
|
8583
9193
|
ctx: ctx,
|
|
8584
9194
|
mutation: mutation,
|
|
8585
9195
|
fromStage: stage,
|
|
@@ -8589,7 +9199,7 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
8589
9199
|
actor: actor
|
|
8590
9200
|
}), {
|
|
8591
9201
|
moved: !0
|
|
8592
|
-
}
|
|
9202
|
+
};
|
|
8593
9203
|
}
|
|
8594
9204
|
|
|
8595
9205
|
async function cascadeAutoTransitions({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts}) {
|
|
@@ -8605,8 +9215,7 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
8605
9215
|
clock: clock,
|
|
8606
9216
|
executionContext: executionContext,
|
|
8607
9217
|
telemetry: telemetry
|
|
8608
|
-
})
|
|
8609
|
-
if (!(await runCascadeHop({
|
|
9218
|
+
}), hop = await runCascadeHop({
|
|
8610
9219
|
client: client,
|
|
8611
9220
|
instanceId: instanceId,
|
|
8612
9221
|
actor: actor,
|
|
@@ -8621,7 +9230,13 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
8621
9230
|
...drained.drained ? {} : {
|
|
8622
9231
|
instance: drained.instance
|
|
8623
9232
|
}
|
|
8624
|
-
})
|
|
9233
|
+
});
|
|
9234
|
+
if (!hop.moved) return {
|
|
9235
|
+
cascaded: count,
|
|
9236
|
+
...hop.nextEvaluationAt !== void 0 ? {
|
|
9237
|
+
nextEvaluationAt: hop.nextEvaluationAt
|
|
9238
|
+
} : {}
|
|
9239
|
+
};
|
|
8625
9240
|
if (count++, count >= CASCADE_LIMIT) throw new CascadeLimitError({
|
|
8626
9241
|
instanceId: instanceId,
|
|
8627
9242
|
limit: CASCADE_LIMIT
|
|
@@ -8640,7 +9255,7 @@ async function drainCondemnedChildren({client: client, instanceId: instanceId, a
|
|
|
8640
9255
|
instance: void 0,
|
|
8641
9256
|
drained: !1
|
|
8642
9257
|
};
|
|
8643
|
-
const condemned = condemnedSubworkflows(instance);
|
|
9258
|
+
const condemned = invariants.condemnedSubworkflows(instance);
|
|
8644
9259
|
if (condemned.length === 0) return {
|
|
8645
9260
|
instance: instance,
|
|
8646
9261
|
drained: !1
|
|
@@ -8754,7 +9369,7 @@ async function loadInstancesById(client, ids) {
|
|
|
8754
9369
|
}
|
|
8755
9370
|
|
|
8756
9371
|
function terminalResolution(child) {
|
|
8757
|
-
const status = resolvedChildStatus(child);
|
|
9372
|
+
const status = invariants.resolvedChildStatus(child);
|
|
8758
9373
|
if (!(status === void 0 || child.completedAt === void 0 || child.completedAt === null)) return {
|
|
8759
9374
|
at: child.completedAt,
|
|
8760
9375
|
stage: child.currentStage,
|
|
@@ -8921,6 +9536,8 @@ async function recordOrphanedPropagation({ctx: ctx, mutation: mutation, child: c
|
|
|
8921
9536
|
function startMutation(instance) {
|
|
8922
9537
|
return {
|
|
8923
9538
|
minReaderModel: minReaderModelOf(instance),
|
|
9539
|
+
definitionSnapshot: instance.definitionSnapshot,
|
|
9540
|
+
definitionModelVersion: definitionAssignmentModel(instance),
|
|
8924
9541
|
currentStage: instance.currentStage,
|
|
8925
9542
|
fields: (instance.fields ?? []).map(s => ({
|
|
8926
9543
|
...s
|
|
@@ -8968,11 +9585,17 @@ function startMutation(instance) {
|
|
|
8968
9585
|
};
|
|
8969
9586
|
}
|
|
8970
9587
|
|
|
9588
|
+
function startRevisionRetryMutation(instance) {
|
|
9589
|
+
const mutation = startMutation(instance);
|
|
9590
|
+
return mutation.commitErrorMapper = error => isRetryableInstanceCommitConflict(error) ? new InstanceCommitRevisionConflict(error) : error,
|
|
9591
|
+
mutation;
|
|
9592
|
+
}
|
|
9593
|
+
|
|
8971
9594
|
function instanceStateFields(src) {
|
|
8972
|
-
const state = {
|
|
9595
|
+
const listModel = isAssignmentListModel(src.definitionModelVersion), state = {
|
|
8973
9596
|
currentStage: src.currentStage,
|
|
8974
|
-
fields: src.fields,
|
|
8975
|
-
stages: src.stages,
|
|
9597
|
+
fields: assignmentFieldsForWrite(src.fields, listModel),
|
|
9598
|
+
stages: assignmentStagesForWrite(src.stages, listModel),
|
|
8976
9599
|
subworkflows: src.subworkflows ?? [],
|
|
8977
9600
|
pendingEffects: src.pendingEffects,
|
|
8978
9601
|
effectHistory: src.effectHistory,
|
|
@@ -8989,7 +9612,10 @@ function instanceStateFields(src) {
|
|
|
8989
9612
|
return {
|
|
8990
9613
|
...modelStampFor({
|
|
8991
9614
|
documentType: "instance",
|
|
8992
|
-
document:
|
|
9615
|
+
document: {
|
|
9616
|
+
...state,
|
|
9617
|
+
definitionSnapshot: src.definitionSnapshot
|
|
9618
|
+
},
|
|
8993
9619
|
storedMinReaderModel: src.minReaderModel
|
|
8994
9620
|
}),
|
|
8995
9621
|
...state
|
|
@@ -9024,11 +9650,11 @@ async function persist(ctx, mutation) {
|
|
|
9024
9650
|
...instanceStateFields(mutation),
|
|
9025
9651
|
lastChangedAt: ctx.now
|
|
9026
9652
|
}, pendingCreates = mutation.pendingCreates;
|
|
9027
|
-
if (pendingCreates.length === 0) return ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit(SYNC_COMMIT);
|
|
9653
|
+
if (pendingCreates.length === 0) return commitInstanceWrite(() => ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit(SYNC_COMMIT), mutation.commitErrorMapper);
|
|
9028
9654
|
const tx = ctx.client.transaction();
|
|
9029
|
-
for (const {body: body} of pendingCreates) tx.create(body);
|
|
9655
|
+
for (const {body: body} of pendingCreates) tx.create(instanceDocumentForWrite(body));
|
|
9030
9656
|
tx.patch(ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev)),
|
|
9031
|
-
await tx.commit(), mutation.pendingCreates = [];
|
|
9657
|
+
await commitInstanceWrite(() => tx.commit(), mutation.commitErrorMapper), mutation.pendingCreates = [];
|
|
9032
9658
|
const actorForPriming = ctx.actor, settlingCohorts = new Set(ctx.settlingCohorts).add(ctx.instance._id);
|
|
9033
9659
|
for (const {body: body} of pendingCreates) try {
|
|
9034
9660
|
const stepArgs = spawnStepArgs(ctx, {
|
|
@@ -9055,6 +9681,14 @@ async function persist(ctx, mutation) {
|
|
|
9055
9681
|
return reloaded;
|
|
9056
9682
|
}
|
|
9057
9683
|
|
|
9684
|
+
async function commitInstanceWrite(write, mapError) {
|
|
9685
|
+
try {
|
|
9686
|
+
return await write();
|
|
9687
|
+
} catch (error) {
|
|
9688
|
+
throw mapError?.(error) ?? error;
|
|
9689
|
+
}
|
|
9690
|
+
}
|
|
9691
|
+
|
|
9058
9692
|
async function settleSpawnBatch(ctx, args) {
|
|
9059
9693
|
try {
|
|
9060
9694
|
await propagateSpawnBatch({
|
|
@@ -9096,7 +9730,7 @@ function stampExecutionContext(ctx, mutation) {
|
|
|
9096
9730
|
}
|
|
9097
9731
|
|
|
9098
9732
|
function currentStageEntry(mutation) {
|
|
9099
|
-
const entry = findOpenStageEntry(mutation);
|
|
9733
|
+
const entry = invariants.findOpenStageEntry(mutation);
|
|
9100
9734
|
if (entry === void 0) throw new Error(`Mutation invariant broken: no current (un-exited) StageEntry for currentStage "${mutation.currentStage}"`);
|
|
9101
9735
|
return entry;
|
|
9102
9736
|
}
|
|
@@ -9121,7 +9755,7 @@ function requireMutationActivityEntry(mutation, activity) {
|
|
|
9121
9755
|
}
|
|
9122
9756
|
|
|
9123
9757
|
function findCurrentStageEntry(instance) {
|
|
9124
|
-
return findOpenStageEntry(instance);
|
|
9758
|
+
return invariants.findOpenStageEntry(instance);
|
|
9125
9759
|
}
|
|
9126
9760
|
|
|
9127
9761
|
function findCurrentActivities(instance) {
|
|
@@ -9317,7 +9951,7 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
|
|
|
9317
9951
|
outputs: outputs,
|
|
9318
9952
|
memberRoles: ctx.memberRoles,
|
|
9319
9953
|
roleAliases: ctx.definition.roleAliases
|
|
9320
|
-
}), mutation =
|
|
9954
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
9321
9955
|
recordProcessedRequest({
|
|
9322
9956
|
mutation: mutation,
|
|
9323
9957
|
record: requestRecord,
|
|
@@ -9406,7 +10040,7 @@ async function queueEffects({ctx: ctx, mutation: mutation, effects: effects, ori
|
|
|
9406
10040
|
const now = ctx.now, liveCtx = {
|
|
9407
10041
|
...ctx,
|
|
9408
10042
|
instance: materializeInstance(ctx.instance, mutation)
|
|
9409
|
-
}, stageEntryKey = opts?.stageEntryKey ?? findOpenStageEntry(liveCtx.instance)?._key, params = await ctxConditionParams(liveCtx, {
|
|
10043
|
+
}, stageEntryKey = opts?.stageEntryKey ?? invariants.findOpenStageEntry(liveCtx.instance)?._key, params = await ctxConditionParams(liveCtx, {
|
|
9410
10044
|
...opts?.activityName !== void 0 ? {
|
|
9411
10045
|
activityName: opts.activityName
|
|
9412
10046
|
} : {},
|
|
@@ -9496,7 +10130,7 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
9496
10130
|
effect: pending.name,
|
|
9497
10131
|
issues: [ "a mid-dispatch report must carry at least one field op — there is nothing to commit" ]
|
|
9498
10132
|
});
|
|
9499
|
-
const mutation =
|
|
10133
|
+
const mutation = startRevisionRetryMutation(ctx.instance);
|
|
9500
10134
|
return recordProcessedRequest({
|
|
9501
10135
|
mutation: mutation,
|
|
9502
10136
|
record: requestRecord,
|
|
@@ -9532,7 +10166,7 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
9532
10166
|
};
|
|
9533
10167
|
}
|
|
9534
10168
|
|
|
9535
|
-
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
10169
|
+
const RESET_ACTIVITY_TARGETS = groqConditionDescribe._exhaustiveOptions()([ "active", "skipped" ]);
|
|
9536
10170
|
|
|
9537
10171
|
function isResetActivityTarget(value) {
|
|
9538
10172
|
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
@@ -9561,7 +10195,7 @@ async function commitResetActivity({ctx: ctx, activity: activity, to: to, reques
|
|
|
9561
10195
|
}), isTerminal(ctx)) return {
|
|
9562
10196
|
fired: !1
|
|
9563
10197
|
};
|
|
9564
|
-
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
10198
|
+
const mutation = startMutation(ctx.instance), openStage2 = invariants.findOpenStageEntry(mutation), entry = invariants.findCurrentActivityEntry(mutation, activity);
|
|
9565
10199
|
if (openStage2 === void 0 || entry === void 0) throw new invariants.ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
9566
10200
|
const from = entry.status;
|
|
9567
10201
|
if (from === to) return {
|
|
@@ -9640,10 +10274,14 @@ async function whatIfFireAction(args) {
|
|
|
9640
10274
|
function replayable(args) {
|
|
9641
10275
|
const {instance: instance, stage: stage, action: action} = args;
|
|
9642
10276
|
if (terminalState(instance) !== "in-flight" || (action.params ?? []).length > 0 || action.spawn !== void 0) return !1;
|
|
9643
|
-
const primed = new Set((findOpenStageEntry(instance)?.activities ?? []).map(e => e.name));
|
|
10277
|
+
const primed = new Set((invariants.findOpenStageEntry(instance)?.activities ?? []).map(e => e.name));
|
|
9644
10278
|
return (stage.activities ?? []).every(declared => primed.has(declared.name)) ? !(stage.activities ?? []).flatMap(declared => declared.actions ?? []).some(sibling => invariants.isCascadeFired(sibling) && sibling.spawn !== void 0) : !1;
|
|
9645
10279
|
}
|
|
9646
10280
|
|
|
10281
|
+
function clientGuardDereference(client) {
|
|
10282
|
+
return async ({_ref: _ref}) => await client.getDocument(invariants.toBareId(_ref)) ?? null;
|
|
10283
|
+
}
|
|
10284
|
+
|
|
9647
10285
|
async function buildFieldInsights({sites: sites, snapshot: snapshot}) {
|
|
9648
10286
|
const insights = [];
|
|
9649
10287
|
for (const field of fieldsReadAcross(sites)) {
|
|
@@ -9799,6 +10437,7 @@ async function evaluateInstance(args) {
|
|
|
9799
10437
|
guards: guards,
|
|
9800
10438
|
now: now,
|
|
9801
10439
|
resourceGrants: resourceGrants,
|
|
10440
|
+
guardDereference: clientGuardDereference(client),
|
|
9802
10441
|
...localPrincipalId !== void 0 ? {
|
|
9803
10442
|
localPrincipalId: localPrincipalId
|
|
9804
10443
|
} : {},
|
|
@@ -9811,16 +10450,6 @@ async function evaluateInstance(args) {
|
|
|
9811
10450
|
});
|
|
9812
10451
|
}
|
|
9813
10452
|
|
|
9814
|
-
function memoizedByName(render) {
|
|
9815
|
-
const rendered = /* @__PURE__ */ new Map;
|
|
9816
|
-
return activityName => {
|
|
9817
|
-
const hit = rendered.get(activityName);
|
|
9818
|
-
if (hit !== void 0) return hit;
|
|
9819
|
-
const scope = render(activityName);
|
|
9820
|
-
return rendered.set(activityName, scope), scope;
|
|
9821
|
-
};
|
|
9822
|
-
}
|
|
9823
|
-
|
|
9824
10453
|
async function callerBoundProjectionScopes(args) {
|
|
9825
10454
|
const can = await advisoryCan({
|
|
9826
10455
|
instance: args.instance,
|
|
@@ -9841,13 +10470,17 @@ async function callerBoundProjectionScopes(args) {
|
|
|
9841
10470
|
};
|
|
9842
10471
|
return {
|
|
9843
10472
|
scope: await renderConditionScope(args.scopeSource, opts),
|
|
9844
|
-
scopeForActivity:
|
|
10473
|
+
scopeForActivity: memoizedBy(activityName => renderConditionScope(args.scopeSource, {
|
|
9845
10474
|
activityName: activityName,
|
|
9846
10475
|
...opts
|
|
9847
10476
|
}))
|
|
9848
10477
|
};
|
|
9849
10478
|
}
|
|
9850
10479
|
|
|
10480
|
+
function clockSitesOf(instance, sites) {
|
|
10481
|
+
return terminalState(instance) !== "in-flight" ? [] : sites.filter(entry => readsNowIn(entry.insight.analysis.reads));
|
|
10482
|
+
}
|
|
10483
|
+
|
|
9851
10484
|
function currentStageOf(instance, definition) {
|
|
9852
10485
|
try {
|
|
9853
10486
|
return findStage(definition, instance.currentStage);
|
|
@@ -9897,12 +10530,13 @@ async function evaluateFromSnapshot(args) {
|
|
|
9897
10530
|
grants: grants,
|
|
9898
10531
|
attributes: attributes,
|
|
9899
10532
|
identity: anchorIdentity
|
|
9900
|
-
}), cascadeScopeForActivity =
|
|
10533
|
+
}), cascadeScopeForActivity = memoizedBy(activityName => renderConditionScope(scopeSource, {
|
|
9901
10534
|
activityName: activityName
|
|
9902
|
-
})), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
10535
|
+
})), currentActivityEntries = invariants.findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
9903
10536
|
instance: instance,
|
|
9904
10537
|
identity: anchorIdentity,
|
|
9905
|
-
guards: args.guards
|
|
10538
|
+
guards: args.guards,
|
|
10539
|
+
dereference: args.guardDereference
|
|
9906
10540
|
}), subjectDenials = await forecastSubjectDenials({
|
|
9907
10541
|
instance: instance,
|
|
9908
10542
|
snapshot: snapshot,
|
|
@@ -9959,6 +10593,10 @@ async function evaluateFromSnapshot(args) {
|
|
|
9959
10593
|
scopeForActivity: scopeForActivity,
|
|
9960
10594
|
guardDenial: editGuardDenial,
|
|
9961
10595
|
sites: sites
|
|
10596
|
+
}), nextEvaluationAt = await nextEvaluationInstant({
|
|
10597
|
+
sites: clockSitesOf(instance, sites),
|
|
10598
|
+
dataset: snapshot.docs,
|
|
10599
|
+
now: now
|
|
9962
10600
|
});
|
|
9963
10601
|
return {
|
|
9964
10602
|
instance: instance,
|
|
@@ -9973,7 +10611,10 @@ async function evaluateFromSnapshot(args) {
|
|
|
9973
10611
|
sites: sites,
|
|
9974
10612
|
snapshot: snapshot
|
|
9975
10613
|
}),
|
|
9976
|
-
autonomy: autonomy
|
|
10614
|
+
autonomy: autonomy,
|
|
10615
|
+
...nextEvaluationAt !== void 0 ? {
|
|
10616
|
+
nextEvaluationAt: nextEvaluationAt
|
|
10617
|
+
} : {}
|
|
9977
10618
|
};
|
|
9978
10619
|
}
|
|
9979
10620
|
|
|
@@ -10121,7 +10762,8 @@ async function evaluateActivity(args) {
|
|
|
10121
10762
|
subjectPermissionReason: subjectPermissionReason,
|
|
10122
10763
|
requirementsReason: requirementsReason,
|
|
10123
10764
|
sites: sites,
|
|
10124
|
-
fireConsequence: a => fireConsequence(activity, a)
|
|
10765
|
+
fireConsequence: a => fireConsequence(activity, a),
|
|
10766
|
+
assignment: invariants.assignmentMembers(statusEntry?.fields ?? [])
|
|
10125
10767
|
}));
|
|
10126
10768
|
return {
|
|
10127
10769
|
activity: activity,
|
|
@@ -10131,7 +10773,7 @@ async function evaluateActivity(args) {
|
|
|
10131
10773
|
classification: invariants.deriveExecutorClassification(activity),
|
|
10132
10774
|
autonomy: autonomy,
|
|
10133
10775
|
pendingOnActor: status === "active" && assigned,
|
|
10134
|
-
scopedOut: isFilterScopedOut({
|
|
10776
|
+
scopedOut: invariants.isFilterScopedOut({
|
|
10135
10777
|
status: status,
|
|
10136
10778
|
startedAt: statusEntry?.startedAt
|
|
10137
10779
|
}),
|
|
@@ -10278,19 +10920,31 @@ function fireableActionVerdict({args: args, insights: insights}) {
|
|
|
10278
10920
|
reason: args.requirementsReason,
|
|
10279
10921
|
...insights
|
|
10280
10922
|
});
|
|
10281
|
-
const
|
|
10282
|
-
return
|
|
10923
|
+
const filterFailure = filterFailureVerdict(args, insights);
|
|
10924
|
+
return filterFailure !== void 0 ? filterFailure : {
|
|
10925
|
+
...actionEvaluationIdentity(action),
|
|
10926
|
+
allowed: !0,
|
|
10927
|
+
...insights
|
|
10928
|
+
};
|
|
10929
|
+
}
|
|
10930
|
+
|
|
10931
|
+
function filterFailureVerdict(args, insights) {
|
|
10932
|
+
const {action: action} = args, {insight: insight} = insights;
|
|
10933
|
+
if (action.filter === void 0 || insight === void 0 || insight.outcome === "satisfied") return;
|
|
10934
|
+
const holderGate = insight.blockedBy.some(entry => isAssignedGate(entry.atom)) ? {
|
|
10935
|
+
holders: [ ...invariants.activeAssignmentMembers(args.assignment) ]
|
|
10936
|
+
} : void 0;
|
|
10937
|
+
return disabled({
|
|
10283
10938
|
action: action,
|
|
10284
10939
|
reason: {
|
|
10285
10940
|
kind: "filter-failed",
|
|
10286
10941
|
filter: action.filter
|
|
10287
10942
|
},
|
|
10288
|
-
...insights
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
};
|
|
10943
|
+
...insights,
|
|
10944
|
+
...holderGate === void 0 ? {} : {
|
|
10945
|
+
holderGate: holderGate
|
|
10946
|
+
}
|
|
10947
|
+
});
|
|
10294
10948
|
}
|
|
10295
10949
|
|
|
10296
10950
|
function actionEvaluationIdentity(action) {
|
|
@@ -10306,12 +10960,13 @@ function semanticsOf(node) {
|
|
|
10306
10960
|
};
|
|
10307
10961
|
}
|
|
10308
10962
|
|
|
10309
|
-
async function instanceGuardReason({instance: instance, identity: identity, guards: guards}) {
|
|
10963
|
+
async function instanceGuardReason({instance: instance, identity: identity, guards: guards, dereference: dereference}) {
|
|
10310
10964
|
if (guards === void 0 || guards.length === 0) return;
|
|
10311
10965
|
const denied = await instanceWriteDenials({
|
|
10312
10966
|
instance: instance,
|
|
10313
10967
|
guards: guards,
|
|
10314
|
-
identity: identity
|
|
10968
|
+
identity: identity,
|
|
10969
|
+
dereference: dereference ?? (() => Promise.resolve(null))
|
|
10315
10970
|
});
|
|
10316
10971
|
if (denied.length !== 0) return {
|
|
10317
10972
|
kind: "mutation-guard-denied",
|
|
@@ -10342,10 +10997,29 @@ function disabled(args) {
|
|
|
10342
10997
|
} : {},
|
|
10343
10998
|
...args.whenInsight !== void 0 ? {
|
|
10344
10999
|
whenInsight: args.whenInsight
|
|
11000
|
+
} : {},
|
|
11001
|
+
...args.holderGate !== void 0 ? {
|
|
11002
|
+
holderGate: args.holderGate
|
|
10345
11003
|
} : {}
|
|
10346
11004
|
};
|
|
10347
11005
|
}
|
|
10348
11006
|
|
|
11007
|
+
const ASSIGNMENT_KINDS = '["assignee", "assignees"]', HAS_USER = '(count(value[@.type == "user"]) > 0 || value.type == "user")', HAS_MEMBER = "(count(value) > 0 || defined(value.type))";
|
|
11008
|
+
|
|
11009
|
+
function assignmentActivityArm(state) {
|
|
11010
|
+
const assignmentFields = `fields[_type in ${ASSIGNMENT_KINDS}]`;
|
|
11011
|
+
return state === "unrouted" ? `count(${assignmentFields}[${HAS_MEMBER}]) == 0` : state === "held" ? `count(${assignmentFields}[${HAS_USER} && (count(value[@.type == "user" && id == $assignmentUserId]) > 0 || (value.type == "user" && value.id == $assignmentUserId))]) > 0` : `count(${assignmentFields}[${HAS_USER}]) == 0 && count(${assignmentFields}[count(value[@.type == "role" && role in $assignmentRoles]) > 0 || (value.type == "role" && value.role in $assignmentRoles)]) > 0`;
|
|
11012
|
+
}
|
|
11013
|
+
|
|
11014
|
+
function assignmentPrefilter(assignment, params) {
|
|
11015
|
+
if (assignment.userId.length === 0) throw new invariants.ContractViolationError("instancesQuery: assignment.userId must be non-empty");
|
|
11016
|
+
const states = [ ...new Set(assignment.states ?? [ "unrouted", "routed", "held" ]) ];
|
|
11017
|
+
if (states.length === 0) throw new invariants.ContractViolationError("instancesQuery: assignment.states must not be empty");
|
|
11018
|
+
if (states.some(state => state !== "unrouted" && state !== "routed" && state !== "held")) throw new invariants.ContractViolationError("instancesQuery: assignment.states contains an unknown state");
|
|
11019
|
+
return params.assignmentUserId = assignment.userId, params.assignmentRoles = [ ...new Set(assignment.roles ?? []) ].sort(),
|
|
11020
|
+
`count(stages[!defined(exitedAt)].activities[status == "active" && (${states.map(assignmentActivityArm).join(" || ")})]) > 0`;
|
|
11021
|
+
}
|
|
11022
|
+
|
|
10349
11023
|
function inFlightFilter() {
|
|
10350
11024
|
return "!defined(completedAt)";
|
|
10351
11025
|
}
|
|
@@ -10385,7 +11059,7 @@ function compiledConditions(filter, params) {
|
|
|
10385
11059
|
const conditions = [ `_type == "${WORKFLOW_INSTANCE_TYPE}"`, invariants.tagScopeFilter() ];
|
|
10386
11060
|
filter.includeCompleted !== !0 && conditions.push(inFlightFilter()), filter.definition !== void 0 && (conditions.push("definition == $definition"),
|
|
10387
11061
|
params.definition = filter.definition), filter.stage !== void 0 && (conditions.push("currentStage == $stage"),
|
|
10388
|
-
params.stage = filter.stage);
|
|
11062
|
+
params.stage = filter.stage), filter.assignment !== void 0 && conditions.push(assignmentPrefilter(filter.assignment, params));
|
|
10389
11063
|
const cursor = beforeArm(filter, params);
|
|
10390
11064
|
cursor !== void 0 && conditions.push(cursor);
|
|
10391
11065
|
const arms = [ documentArm(filter, params), idsArm(filter, params) ].filter(arm => arm !== void 0);
|
|
@@ -10488,6 +11162,222 @@ function stripClaim(entry) {
|
|
|
10488
11162
|
return rest;
|
|
10489
11163
|
}
|
|
10490
11164
|
|
|
11165
|
+
function isProjectRole(value) {
|
|
11166
|
+
return invariants.isRecord(value) && typeof value.name == "string";
|
|
11167
|
+
}
|
|
11168
|
+
|
|
11169
|
+
async function projectRoleNames(request, projectId) {
|
|
11170
|
+
const result = await request({
|
|
11171
|
+
uri: `/projects/${encodeURIComponent(projectId)}/roles`
|
|
11172
|
+
});
|
|
11173
|
+
if (!Array.isArray(result) || !result.every(isProjectRole)) throw new Error(`Project role catalog response is invalid for project "${projectId}"`);
|
|
11174
|
+
return new Set(result.map(role => role.name));
|
|
11175
|
+
}
|
|
11176
|
+
|
|
11177
|
+
function memberRoleNames(member, projectId) {
|
|
11178
|
+
if (!Array.isArray(member.roles) || !member.roles.every(isProjectRole)) throw new Error(`Project member role directory response is invalid for project "${projectId}" and member "${member.id}"`);
|
|
11179
|
+
return member.roles.map(role => role.name);
|
|
11180
|
+
}
|
|
11181
|
+
|
|
11182
|
+
function heldRoleNames(members, projectId) {
|
|
11183
|
+
return new Set(members.flatMap(member => member.isRobot === !0 ? [] : memberRoleNames(member, projectId)));
|
|
11184
|
+
}
|
|
11185
|
+
|
|
11186
|
+
function addRoles(collector, args) {
|
|
11187
|
+
for (const role of args.roles ?? []) collector.references.push({
|
|
11188
|
+
definition: collector.definition,
|
|
11189
|
+
path: args.path,
|
|
11190
|
+
role: role
|
|
11191
|
+
});
|
|
11192
|
+
}
|
|
11193
|
+
|
|
11194
|
+
function visitAssigneeValue(collector, args) {
|
|
11195
|
+
const members = Array.isArray(args.value) ? args.value : [ args.value ];
|
|
11196
|
+
for (const [index, member] of members.entries()) !invariants.isRecord(member) || member.type !== "role" || typeof member.role != "string" || collector.references.push({
|
|
11197
|
+
definition: collector.definition,
|
|
11198
|
+
path: `${args.path}[${index}].role`,
|
|
11199
|
+
role: member.role
|
|
11200
|
+
});
|
|
11201
|
+
}
|
|
11202
|
+
|
|
11203
|
+
function visitObjectValue(collector, args) {
|
|
11204
|
+
for (const shape of args.fields ?? []) visitShapeValue(collector, {
|
|
11205
|
+
path: `${args.path}.${shape.name}`,
|
|
11206
|
+
shape: shape,
|
|
11207
|
+
value: args.value[shape.name]
|
|
11208
|
+
});
|
|
11209
|
+
}
|
|
11210
|
+
|
|
11211
|
+
function visitArrayValue(collector, args) {
|
|
11212
|
+
for (const [index, row] of args.rows.entries()) if (invariants.isRecord(row)) for (const shape of args.shapes ?? []) visitShapeValue(collector, {
|
|
11213
|
+
path: `${args.path}[${index}].${shape.name}`,
|
|
11214
|
+
shape: shape,
|
|
11215
|
+
value: row[shape.name]
|
|
11216
|
+
});
|
|
11217
|
+
}
|
|
11218
|
+
|
|
11219
|
+
function visitAssignmentValue(collector, args) {
|
|
11220
|
+
args.kind === "assignee" || args.kind === "assignees" ? visitAssigneeValue(collector, args) : args.kind === "object" && invariants.isRecord(args.value) ? visitObjectValue(collector, {
|
|
11221
|
+
...args,
|
|
11222
|
+
value: args.value
|
|
11223
|
+
}) : args.kind === "array" && Array.isArray(args.value) && visitArrayValue(collector, {
|
|
11224
|
+
path: args.path,
|
|
11225
|
+
rows: args.value,
|
|
11226
|
+
shapes: args.of
|
|
11227
|
+
});
|
|
11228
|
+
}
|
|
11229
|
+
|
|
11230
|
+
function visitShapeValue(collector, args) {
|
|
11231
|
+
visitAssignmentValue(collector, {
|
|
11232
|
+
path: args.path,
|
|
11233
|
+
kind: args.shape.type,
|
|
11234
|
+
value: args.value,
|
|
11235
|
+
fields: args.shape.fields,
|
|
11236
|
+
of: args.shape.of
|
|
11237
|
+
});
|
|
11238
|
+
}
|
|
11239
|
+
|
|
11240
|
+
function visitField(collector, args) {
|
|
11241
|
+
addRoles(collector, {
|
|
11242
|
+
path: `${args.path}.roles`,
|
|
11243
|
+
roles: args.field.roles
|
|
11244
|
+
});
|
|
11245
|
+
for (const shape of args.field.fields ?? args.field.of ?? []) visitFieldShape(collector, {
|
|
11246
|
+
parentPath: args.path,
|
|
11247
|
+
shape: shape
|
|
11248
|
+
});
|
|
11249
|
+
args.field.initialValue?.type === "literal" && visitAssignmentValue(collector, {
|
|
11250
|
+
path: `${args.path}.initialValue.value`,
|
|
11251
|
+
kind: args.field.type,
|
|
11252
|
+
value: args.field.initialValue.value,
|
|
11253
|
+
fields: args.field.fields,
|
|
11254
|
+
of: args.field.of
|
|
11255
|
+
});
|
|
11256
|
+
}
|
|
11257
|
+
|
|
11258
|
+
function visitFieldShape(collector, args) {
|
|
11259
|
+
const path = `${args.parentPath}.${args.shape.name}`;
|
|
11260
|
+
addRoles(collector, {
|
|
11261
|
+
path: `${path}.roles`,
|
|
11262
|
+
roles: args.shape.roles
|
|
11263
|
+
});
|
|
11264
|
+
for (const child of args.shape.fields ?? args.shape.of ?? []) visitFieldShape(collector, {
|
|
11265
|
+
parentPath: path,
|
|
11266
|
+
shape: child
|
|
11267
|
+
});
|
|
11268
|
+
}
|
|
11269
|
+
|
|
11270
|
+
function rolesFromConditions(definition) {
|
|
11271
|
+
return conditionSitesOf(definition).flatMap(site => {
|
|
11272
|
+
try {
|
|
11273
|
+
return groqConditionDescribe.analyzeCondition(site.condition).atoms.flatMap(atom => rolesGateOf(atom) ?? []);
|
|
11274
|
+
} catch {
|
|
11275
|
+
return [];
|
|
11276
|
+
}
|
|
11277
|
+
});
|
|
11278
|
+
}
|
|
11279
|
+
|
|
11280
|
+
function visitRoleAliases(collector, aliases) {
|
|
11281
|
+
for (const [role, fulfillers] of Object.entries(aliases ?? {})) role !== invariants.UNIVERSAL_ROLE_ALIAS_KEY && collector.references.push({
|
|
11282
|
+
definition: collector.definition,
|
|
11283
|
+
path: `roleAliases.${role}`,
|
|
11284
|
+
role: role
|
|
11285
|
+
}), addRoles(collector, {
|
|
11286
|
+
path: `roleAliases.${role}`,
|
|
11287
|
+
roles: fulfillers
|
|
11288
|
+
});
|
|
11289
|
+
}
|
|
11290
|
+
|
|
11291
|
+
function visitFields(collector, args) {
|
|
11292
|
+
for (const [index, field] of (args.fields ?? []).entries()) visitField(collector, {
|
|
11293
|
+
path: `${args.parentPath}[${index}]`,
|
|
11294
|
+
field: field
|
|
11295
|
+
});
|
|
11296
|
+
}
|
|
11297
|
+
|
|
11298
|
+
function visitAction(collector, args) {
|
|
11299
|
+
addRoles(collector, {
|
|
11300
|
+
path: `${args.path}.roles`,
|
|
11301
|
+
roles: args.action.roles
|
|
11302
|
+
});
|
|
11303
|
+
for (const [effectIndex, effect] of (args.action.effects ?? []).entries()) for (const shape of effect.outputs ?? []) visitFieldShape(collector, {
|
|
11304
|
+
parentPath: `${args.path}.effects[${effectIndex}].outputs`,
|
|
11305
|
+
shape: shape
|
|
11306
|
+
});
|
|
11307
|
+
}
|
|
11308
|
+
|
|
11309
|
+
function visitStage(collector, args) {
|
|
11310
|
+
const stagePath = `stages[${args.stageIndex}]`;
|
|
11311
|
+
visitFields(collector, {
|
|
11312
|
+
fields: args.stage.fields,
|
|
11313
|
+
parentPath: `${stagePath}.fields`
|
|
11314
|
+
});
|
|
11315
|
+
for (const [activityIndex, activity] of (args.stage.activities ?? []).entries()) {
|
|
11316
|
+
const activityPath = `${stagePath}.activities[${activityIndex}]`;
|
|
11317
|
+
visitFields(collector, {
|
|
11318
|
+
fields: activity.fields,
|
|
11319
|
+
parentPath: `${activityPath}.fields`
|
|
11320
|
+
});
|
|
11321
|
+
for (const [actionIndex, action] of (activity.actions ?? []).entries()) visitAction(collector, {
|
|
11322
|
+
action: action,
|
|
11323
|
+
path: `${activityPath}.actions[${actionIndex}]`
|
|
11324
|
+
});
|
|
11325
|
+
}
|
|
11326
|
+
}
|
|
11327
|
+
|
|
11328
|
+
function addConditionReferences(collector, definition) {
|
|
11329
|
+
for (const role of rolesFromConditions(definition)) collector.references.push({
|
|
11330
|
+
definition: collector.definition,
|
|
11331
|
+
path: "generated role condition",
|
|
11332
|
+
role: role
|
|
11333
|
+
});
|
|
11334
|
+
}
|
|
11335
|
+
|
|
11336
|
+
function definitionRoleReferences(definition) {
|
|
11337
|
+
const collector = {
|
|
11338
|
+
references: [],
|
|
11339
|
+
definition: definition.name
|
|
11340
|
+
};
|
|
11341
|
+
visitRoleAliases(collector, definition.roleAliases), visitFields(collector, {
|
|
11342
|
+
fields: definition.fields,
|
|
11343
|
+
parentPath: "fields"
|
|
11344
|
+
});
|
|
11345
|
+
for (const [stageIndex, stage] of definition.stages.entries()) visitStage(collector, {
|
|
11346
|
+
stage: stage,
|
|
11347
|
+
stageIndex: stageIndex
|
|
11348
|
+
});
|
|
11349
|
+
return addConditionReferences(collector, definition), collector.references;
|
|
11350
|
+
}
|
|
11351
|
+
|
|
11352
|
+
function definitionRoleNames(definition) {
|
|
11353
|
+
return [ ...new Set(definitionRoleReferences(definition).map(reference => reference.role)) ];
|
|
11354
|
+
}
|
|
11355
|
+
|
|
11356
|
+
function roleCatalogProjectId(client, resource) {
|
|
11357
|
+
if (resource.type === "dataset") return invariants.datasetResourceParts(resource.id).projectId;
|
|
11358
|
+
const projectId = client.config?.().projectId;
|
|
11359
|
+
if (typeof projectId == "string" && projectId.length > 0) return projectId;
|
|
11360
|
+
throw new Error(`workflow.deployDefinitions: definitions reference project roles on ${resource.type} workflow resources, but the client does not expose a projectId for the project role catalog`);
|
|
11361
|
+
}
|
|
11362
|
+
|
|
11363
|
+
async function validateDefinitionRoles(args) {
|
|
11364
|
+
const references = args.definitions.flatMap(definitionRoleReferences);
|
|
11365
|
+
if (references.length === 0) /* @__PURE__ */ return new Map;
|
|
11366
|
+
if (args.client.request === void 0) throw new Error("workflow.deployDefinitions: definitions reference project roles, but the client cannot read the project role catalog");
|
|
11367
|
+
const projectId = roleCatalogProjectId(args.client, args.workflowResource), [known, members] = await Promise.all([ projectRoleNames(args.client.request, projectId), requestProjectMembers(args.client.request, projectId) ]), unknown = references.filter(reference => !known.has(reference.role));
|
|
11368
|
+
if (unknown.length > 0) {
|
|
11369
|
+
const lines = unknown.map(({definition: definition, path: path, role: role}) => ` - ${definition}: ${path} references unknown role "${role}"`);
|
|
11370
|
+
throw new Error(`workflow.deployDefinitions: unknown project roles for project "${projectId}":\n${lines.join(`\n`)}`);
|
|
11371
|
+
}
|
|
11372
|
+
const held = heldRoleNames(members, projectId), warnings = /* @__PURE__ */ new Map;
|
|
11373
|
+
for (const {definition: definition, role: role} of references) {
|
|
11374
|
+
if (held.has(role)) continue;
|
|
11375
|
+
const message = `Project role "${role}" has no current user holder; work routed to it has no recipient.`, definitionWarnings = warnings.get(definition) ?? [];
|
|
11376
|
+
definitionWarnings.includes(message) || definitionWarnings.push(message), warnings.set(definition, definitionWarnings);
|
|
11377
|
+
}
|
|
11378
|
+
return warnings;
|
|
11379
|
+
}
|
|
11380
|
+
|
|
10491
11381
|
async function sortByDependencies({client: client, definitions: definitions, tag: tag}) {
|
|
10492
11382
|
const byName = /* @__PURE__ */ new Map;
|
|
10493
11383
|
for (const def of definitions) {
|
|
@@ -10788,7 +11678,7 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
|
|
|
10788
11678
|
site: site,
|
|
10789
11679
|
mode: mode,
|
|
10790
11680
|
value: value
|
|
10791
|
-
}), mutation =
|
|
11681
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
10792
11682
|
recordProcessedRequest({
|
|
10793
11683
|
mutation: mutation,
|
|
10794
11684
|
record: requestRecord,
|
|
@@ -10932,14 +11822,14 @@ async function runCommitVerb(params) {
|
|
|
10932
11822
|
client: client,
|
|
10933
11823
|
instanceId: instanceId,
|
|
10934
11824
|
tag: tag
|
|
10935
|
-
});
|
|
11825
|
+
}), now = clock();
|
|
10936
11826
|
return runDeduped({
|
|
10937
11827
|
client: client,
|
|
10938
11828
|
tag: tag,
|
|
10939
11829
|
instanceId: instanceId,
|
|
10940
11830
|
record: record,
|
|
10941
11831
|
before: before,
|
|
10942
|
-
now:
|
|
11832
|
+
now: now,
|
|
10943
11833
|
actor: context.actor,
|
|
10944
11834
|
clientForGdr: context.clientForGdr,
|
|
10945
11835
|
refSurface: context.refSurface,
|
|
@@ -10950,6 +11840,7 @@ async function runCommitVerb(params) {
|
|
|
10950
11840
|
run: () => run({
|
|
10951
11841
|
...context,
|
|
10952
11842
|
clock: clock,
|
|
11843
|
+
now: now,
|
|
10953
11844
|
record: record,
|
|
10954
11845
|
before: before
|
|
10955
11846
|
})
|
|
@@ -10973,7 +11864,7 @@ async function runDeduped(args) {
|
|
|
10973
11864
|
client: client,
|
|
10974
11865
|
instanceId: instanceId,
|
|
10975
11866
|
tag: tag
|
|
10976
|
-
}),
|
|
11867
|
+
}), settled = await cascadeAndReload({
|
|
10977
11868
|
client: client,
|
|
10978
11869
|
tag: tag,
|
|
10979
11870
|
instanceId: instanceId,
|
|
@@ -10985,11 +11876,10 @@ async function runDeduped(args) {
|
|
|
10985
11876
|
executionContext: executionContext,
|
|
10986
11877
|
telemetry: telemetry
|
|
10987
11878
|
});
|
|
10988
|
-
return {
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
};
|
|
11879
|
+
return settledResult({
|
|
11880
|
+
...settled,
|
|
11881
|
+
changed: settled.instance._rev !== pre._rev
|
|
11882
|
+
});
|
|
10993
11883
|
};
|
|
10994
11884
|
if (record !== void 0 && before !== void 0 && findProcessedRequest({
|
|
10995
11885
|
instance: before,
|
|
@@ -11005,7 +11895,7 @@ async function runDeduped(args) {
|
|
|
11005
11895
|
}
|
|
11006
11896
|
|
|
11007
11897
|
async function cascade({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
|
|
11008
|
-
const
|
|
11898
|
+
const settled = await cascadeAutoTransitions({
|
|
11009
11899
|
client: client,
|
|
11010
11900
|
instanceId: instanceId,
|
|
11011
11901
|
actor: actor,
|
|
@@ -11041,13 +11931,13 @@ async function cascade({client: client, instanceId: instanceId, actor: actor, cl
|
|
|
11041
11931
|
...telemetry !== void 0 ? {
|
|
11042
11932
|
telemetry: telemetry
|
|
11043
11933
|
} : {}
|
|
11044
|
-
}),
|
|
11934
|
+
}), settled;
|
|
11045
11935
|
}
|
|
11046
11936
|
|
|
11047
11937
|
async function cascadeAndReload(args) {
|
|
11048
11938
|
const {client: client, tag: tag, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock} = args;
|
|
11049
11939
|
return {
|
|
11050
|
-
|
|
11940
|
+
...await cascade({
|
|
11051
11941
|
client: client,
|
|
11052
11942
|
instanceId: instanceId,
|
|
11053
11943
|
actor: actor,
|
|
@@ -11070,6 +11960,84 @@ async function cascadeAndReload(args) {
|
|
|
11070
11960
|
};
|
|
11071
11961
|
}
|
|
11072
11962
|
|
|
11963
|
+
async function unchangedNextEvaluationAt(args) {
|
|
11964
|
+
const {client: client, instance: instance, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, now: now} = args;
|
|
11965
|
+
if (terminalState(instance) !== "in-flight") return;
|
|
11966
|
+
const ctx = await buildEngineContext({
|
|
11967
|
+
client: client,
|
|
11968
|
+
instance: instance,
|
|
11969
|
+
definition: parseDefinitionSnapshot(instance),
|
|
11970
|
+
clientForGdr: clientForGdr,
|
|
11971
|
+
refSurface: refSurface,
|
|
11972
|
+
memberRolesLoader: memberRolesLoader,
|
|
11973
|
+
clock: () => now,
|
|
11974
|
+
...actor !== void 0 ? {
|
|
11975
|
+
actor: actor
|
|
11976
|
+
} : {},
|
|
11977
|
+
...args.executionContext !== void 0 ? {
|
|
11978
|
+
executionContext: args.executionContext
|
|
11979
|
+
} : {},
|
|
11980
|
+
...args.telemetry !== void 0 ? {
|
|
11981
|
+
telemetry: args.telemetry
|
|
11982
|
+
} : {}
|
|
11983
|
+
});
|
|
11984
|
+
return ctxNextEvaluationAt(ctx);
|
|
11985
|
+
}
|
|
11986
|
+
|
|
11987
|
+
async function adminOverrideResult(args) {
|
|
11988
|
+
const {client: client, tag: tag, instanceId: instanceId, fired: fired, now: now, executionContext: executionContext, telemetry: telemetry, ...scope} = args, optional = {
|
|
11989
|
+
...executionContext !== void 0 ? {
|
|
11990
|
+
executionContext: executionContext
|
|
11991
|
+
} : {},
|
|
11992
|
+
...telemetry !== void 0 ? {
|
|
11993
|
+
telemetry: telemetry
|
|
11994
|
+
} : {}
|
|
11995
|
+
}, settled = fired ? await cascade({
|
|
11996
|
+
client: client,
|
|
11997
|
+
instanceId: instanceId,
|
|
11998
|
+
...scope,
|
|
11999
|
+
...optional
|
|
12000
|
+
}) : {
|
|
12001
|
+
cascaded: 0
|
|
12002
|
+
}, instance = await reload({
|
|
12003
|
+
client: client,
|
|
12004
|
+
instanceId: instanceId,
|
|
12005
|
+
tag: tag
|
|
12006
|
+
});
|
|
12007
|
+
return settledResult({
|
|
12008
|
+
...settled,
|
|
12009
|
+
instance: instance,
|
|
12010
|
+
changed: fired,
|
|
12011
|
+
...fired ? {} : {
|
|
12012
|
+
nextEvaluationAt: await unchangedNextEvaluationAt({
|
|
12013
|
+
client: client,
|
|
12014
|
+
instance: instance,
|
|
12015
|
+
now: now,
|
|
12016
|
+
actor: scope.actor,
|
|
12017
|
+
clientForGdr: scope.clientForGdr,
|
|
12018
|
+
refSurface: scope.refSurface,
|
|
12019
|
+
memberRolesLoader: scope.memberRolesLoader,
|
|
12020
|
+
...optional
|
|
12021
|
+
})
|
|
12022
|
+
}
|
|
12023
|
+
});
|
|
12024
|
+
}
|
|
12025
|
+
|
|
12026
|
+
function settledResult(args) {
|
|
12027
|
+
const {instance: instance, cascaded: cascaded, changed: changed, ranOps: ranOps, nextEvaluationAt: nextEvaluationAt} = args;
|
|
12028
|
+
return {
|
|
12029
|
+
instance: instance,
|
|
12030
|
+
cascaded: cascaded,
|
|
12031
|
+
changed: changed,
|
|
12032
|
+
...ranOps !== void 0 ? {
|
|
12033
|
+
ranOps: ranOps
|
|
12034
|
+
} : {},
|
|
12035
|
+
...nextEvaluationAt !== void 0 ? {
|
|
12036
|
+
nextEvaluationAt: nextEvaluationAt
|
|
12037
|
+
} : {}
|
|
12038
|
+
};
|
|
12039
|
+
}
|
|
12040
|
+
|
|
11073
12041
|
async function settleStart(args) {
|
|
11074
12042
|
const runArgs = {
|
|
11075
12043
|
client: args.client,
|
|
@@ -11131,7 +12099,7 @@ async function resumeStart(args) {
|
|
|
11131
12099
|
instance: existing,
|
|
11132
12100
|
initialFieldCount: initialFieldCount,
|
|
11133
12101
|
viaSpawn: !1
|
|
11134
|
-
})),
|
|
12102
|
+
})), settled = await settleStart({
|
|
11135
12103
|
...settlementArgs,
|
|
11136
12104
|
instanceId: existing._id,
|
|
11137
12105
|
...completesStart ? {
|
|
@@ -11142,11 +12110,11 @@ async function resumeStart(args) {
|
|
|
11142
12110
|
instanceId: existing._id,
|
|
11143
12111
|
tag: args.tag
|
|
11144
12112
|
});
|
|
11145
|
-
return {
|
|
12113
|
+
return settledResult({
|
|
12114
|
+
...settled,
|
|
11146
12115
|
instance: instance,
|
|
11147
|
-
cascaded: cascaded,
|
|
11148
12116
|
changed: instance._rev !== existing._rev
|
|
11149
|
-
};
|
|
12117
|
+
});
|
|
11150
12118
|
}
|
|
11151
12119
|
|
|
11152
12120
|
function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, executionContext: executionContext, telemetry: telemetry}) {
|
|
@@ -11245,7 +12213,7 @@ async function dispatchGatedWrite(args) {
|
|
|
11245
12213
|
...resourceClients !== void 0 ? {
|
|
11246
12214
|
resourceClients: resourceClients
|
|
11247
12215
|
} : {}
|
|
11248
|
-
}), ranOps = await apply(args.before, evaluation),
|
|
12216
|
+
}), ranOps = await apply(args.before, evaluation), settled = await cascadeAndReload({
|
|
11249
12217
|
client: client,
|
|
11250
12218
|
tag: tag,
|
|
11251
12219
|
instanceId: instanceId,
|
|
@@ -11257,14 +12225,13 @@ async function dispatchGatedWrite(args) {
|
|
|
11257
12225
|
executionContext: args.executionContext,
|
|
11258
12226
|
telemetry: args.telemetry
|
|
11259
12227
|
});
|
|
11260
|
-
return {
|
|
11261
|
-
|
|
11262
|
-
cascaded: cascaded,
|
|
12228
|
+
return settledResult({
|
|
12229
|
+
...settled,
|
|
11263
12230
|
changed: !0,
|
|
11264
12231
|
...ranOps !== void 0 ? {
|
|
11265
12232
|
ranOps: ranOps
|
|
11266
12233
|
} : {}
|
|
11267
|
-
};
|
|
12234
|
+
});
|
|
11268
12235
|
}
|
|
11269
12236
|
|
|
11270
12237
|
function guardDeniedError(instanceId, reason) {
|
|
@@ -11478,6 +12445,10 @@ async function abortInstances(args) {
|
|
|
11478
12445
|
return aborted;
|
|
11479
12446
|
}
|
|
11480
12447
|
|
|
12448
|
+
function lintDeadActivityInputSeeds(definition) {
|
|
12449
|
+
return definition.stages.flatMap(stage => (stage.activities ?? []).flatMap(activity => (activity.fields ?? []).filter(field => field.initialValue?.type === "input").map(field => `Activity field "${stage.name}.${activity.name}.${field.name}" uses an input seed, but start/spawn inputs address workflow-scope fields only; this field will always materialize empty. Use a literal, query, field read, or working-memory field instead.`)));
|
|
12450
|
+
}
|
|
12451
|
+
|
|
11481
12452
|
function projectStartSliceRow(instance) {
|
|
11482
12453
|
const subject = (instance.fields ?? []).find(field => field._type === "subject")?.value;
|
|
11483
12454
|
return {
|
|
@@ -11505,14 +12476,18 @@ const workflow = {
|
|
|
11505
12476
|
definitions.forEach(validateDefinition), assertReaderModelAcknowledgement(args.expectedMinReaderModel, {
|
|
11506
12477
|
requiredMinReaderModel: requiredDefinitionReaderModel(definitions)
|
|
11507
12478
|
});
|
|
11508
|
-
const
|
|
12479
|
+
const roleWarnings = await validateDefinitionRoles({
|
|
12480
|
+
client: client,
|
|
12481
|
+
definitions: definitions,
|
|
12482
|
+
workflowResource: workflowResource
|
|
12483
|
+
}), ordered = await sortByDependencies({
|
|
11509
12484
|
client: client,
|
|
11510
12485
|
definitions: definitions,
|
|
11511
12486
|
tag: tag
|
|
11512
12487
|
}), results = [], deployed = [], tx = client.transaction();
|
|
11513
12488
|
let hasWrites = !1;
|
|
11514
12489
|
for (const def of ordered) {
|
|
11515
|
-
const lint = lintEffectOutputs(def), warnings = lint.length > 0 ? {
|
|
12490
|
+
const lint = [ ...lintEffectOutputs(def), ...lintDeadActivityInputSeeds(def), ...roleWarnings.get(def.name) ?? [] ], warnings = lint.length > 0 ? {
|
|
11516
12491
|
warnings: lint
|
|
11517
12492
|
} : {}, latest = await loadLatestDeployed({
|
|
11518
12493
|
client: client,
|
|
@@ -11605,12 +12580,27 @@ const workflow = {
|
|
|
11605
12580
|
return runCommitVerb({
|
|
11606
12581
|
args: args,
|
|
11607
12582
|
op: "fireAction",
|
|
11608
|
-
run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
11609
|
-
if (findCurrentActivityEntry(before, activity) === void 0 && idempotent === !0) return {
|
|
12583
|
+
run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
12584
|
+
if (invariants.findCurrentActivityEntry(before, activity) === void 0 && idempotent === !0) return settledResult({
|
|
11610
12585
|
instance: before,
|
|
11611
12586
|
cascaded: 0,
|
|
11612
|
-
changed: !1
|
|
11613
|
-
|
|
12587
|
+
changed: !1,
|
|
12588
|
+
nextEvaluationAt: await unchangedNextEvaluationAt({
|
|
12589
|
+
client: client,
|
|
12590
|
+
instance: before,
|
|
12591
|
+
actor: actor,
|
|
12592
|
+
clientForGdr: clientForGdr,
|
|
12593
|
+
refSurface: refSurface,
|
|
12594
|
+
memberRolesLoader: memberRolesLoader,
|
|
12595
|
+
now: now,
|
|
12596
|
+
...executionContext !== void 0 ? {
|
|
12597
|
+
executionContext: executionContext
|
|
12598
|
+
} : {},
|
|
12599
|
+
...args.telemetry !== void 0 ? {
|
|
12600
|
+
telemetry: args.telemetry
|
|
12601
|
+
} : {}
|
|
12602
|
+
})
|
|
12603
|
+
});
|
|
11614
12604
|
const result = await dispatchGatedWrite({
|
|
11615
12605
|
client: client,
|
|
11616
12606
|
tag: tag,
|
|
@@ -11747,7 +12737,7 @@ const workflow = {
|
|
|
11747
12737
|
});
|
|
11748
12738
|
},
|
|
11749
12739
|
completeEffect: async rawArgs => {
|
|
11750
|
-
const args = taggedScope(rawArgs, REQUEST_TAG.completeEffect), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, status: status, outputs: outputs, ops: ops, detail: detail, error: error, durationMs: durationMs, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
|
|
12740
|
+
const args = taggedScope(rawArgs, REQUEST_TAG.completeEffect), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, status: status, outputs: outputs, ops: ops, detail: detail, error: error, durationMs: durationMs, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, now = clock(), record = requestRecordFor({
|
|
11751
12741
|
idempotencyKey: args.idempotencyKey,
|
|
11752
12742
|
op: "completeEffect",
|
|
11753
12743
|
idempotencyTtlMs: args.idempotencyTtlMs
|
|
@@ -11757,7 +12747,7 @@ const workflow = {
|
|
|
11757
12747
|
tag: tag,
|
|
11758
12748
|
instanceId: instanceId,
|
|
11759
12749
|
record: record,
|
|
11760
|
-
now:
|
|
12750
|
+
now: now,
|
|
11761
12751
|
...operationContext,
|
|
11762
12752
|
clock: clock,
|
|
11763
12753
|
executionContext: executionContext,
|
|
@@ -11792,7 +12782,7 @@ const workflow = {
|
|
|
11792
12782
|
executionContext: executionContext,
|
|
11793
12783
|
telemetry: args.telemetry
|
|
11794
12784
|
})
|
|
11795
|
-
}),
|
|
12785
|
+
}), settled = await cascadeAndReload({
|
|
11796
12786
|
client: client,
|
|
11797
12787
|
tag: tag,
|
|
11798
12788
|
instanceId: instanceId,
|
|
@@ -11802,22 +12792,21 @@ const workflow = {
|
|
|
11802
12792
|
telemetry: args.telemetry
|
|
11803
12793
|
});
|
|
11804
12794
|
return resolveTelemetry(args.telemetry).log(WorkflowEffectCompleted, {
|
|
11805
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12795
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11806
12796
|
instanceId: instanceId,
|
|
11807
12797
|
effect: completion.effect,
|
|
11808
12798
|
status: status,
|
|
11809
12799
|
origin: completion.origin,
|
|
11810
|
-
cascaded: cascaded
|
|
11811
|
-
}), {
|
|
11812
|
-
|
|
11813
|
-
cascaded: cascaded,
|
|
12800
|
+
cascaded: settled.cascaded
|
|
12801
|
+
}), settledResult({
|
|
12802
|
+
...settled,
|
|
11814
12803
|
changed: !0
|
|
11815
|
-
};
|
|
12804
|
+
});
|
|
11816
12805
|
}
|
|
11817
12806
|
});
|
|
11818
12807
|
},
|
|
11819
12808
|
commitEffectOps: async rawArgs => {
|
|
11820
|
-
const args = taggedScope(rawArgs, REQUEST_TAG.commitEffectOps), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, claimToken: claimToken, ops: ops, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
|
|
12809
|
+
const args = taggedScope(rawArgs, REQUEST_TAG.commitEffectOps), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, claimToken: claimToken, ops: ops, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, now = clock(), record = requestRecordFor({
|
|
11821
12810
|
idempotencyKey: args.idempotencyKey,
|
|
11822
12811
|
op: "commitEffectOps",
|
|
11823
12812
|
idempotencyTtlMs: args.idempotencyTtlMs
|
|
@@ -11828,7 +12817,7 @@ const workflow = {
|
|
|
11828
12817
|
tag: tag,
|
|
11829
12818
|
instanceId: instanceId,
|
|
11830
12819
|
record: record,
|
|
11831
|
-
now:
|
|
12820
|
+
now: now,
|
|
11832
12821
|
...operationContext,
|
|
11833
12822
|
clock: clock,
|
|
11834
12823
|
executionContext: executionContext,
|
|
@@ -11848,7 +12837,7 @@ const workflow = {
|
|
|
11848
12837
|
executionContext: executionContext,
|
|
11849
12838
|
telemetry: args.telemetry
|
|
11850
12839
|
})
|
|
11851
|
-
}),
|
|
12840
|
+
}), settled = await cascadeAndReload({
|
|
11852
12841
|
client: client,
|
|
11853
12842
|
tag: tag,
|
|
11854
12843
|
instanceId: instanceId,
|
|
@@ -11858,15 +12847,14 @@ const workflow = {
|
|
|
11858
12847
|
telemetry: args.telemetry
|
|
11859
12848
|
});
|
|
11860
12849
|
return resolveTelemetry(args.telemetry).log(WorkflowEffectStateReported, {
|
|
11861
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12850
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11862
12851
|
instanceId: instanceId,
|
|
11863
12852
|
effect: report.effect,
|
|
11864
|
-
cascaded: cascaded
|
|
11865
|
-
}), {
|
|
11866
|
-
|
|
11867
|
-
cascaded: cascaded,
|
|
12853
|
+
cascaded: settled.cascaded
|
|
12854
|
+
}), settledResult({
|
|
12855
|
+
...settled,
|
|
11868
12856
|
changed: !0
|
|
11869
|
-
};
|
|
12857
|
+
});
|
|
11870
12858
|
}
|
|
11871
12859
|
});
|
|
11872
12860
|
},
|
|
@@ -11879,9 +12867,10 @@ const workflow = {
|
|
|
11879
12867
|
await assertInstanceWriteAllowed({
|
|
11880
12868
|
instance: current,
|
|
11881
12869
|
guards: guards,
|
|
11882
|
-
identity: invariants.lakePrincipalId(access)
|
|
12870
|
+
identity: invariants.lakePrincipalId(access),
|
|
12871
|
+
dereference: clientGuardDereference(client)
|
|
11883
12872
|
});
|
|
11884
|
-
const
|
|
12873
|
+
const settled = await cascadeAndReload({
|
|
11885
12874
|
client: client,
|
|
11886
12875
|
tag: tag,
|
|
11887
12876
|
instanceId: instanceId,
|
|
@@ -11891,21 +12880,20 @@ const workflow = {
|
|
|
11891
12880
|
telemetry: args.telemetry
|
|
11892
12881
|
});
|
|
11893
12882
|
return resolveTelemetry(args.telemetry).log(WorkflowInstanceTicked, {
|
|
11894
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12883
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11895
12884
|
instanceId: instanceId,
|
|
11896
|
-
cascaded: cascaded
|
|
11897
|
-
}), {
|
|
11898
|
-
|
|
11899
|
-
|
|
11900
|
-
|
|
11901
|
-
};
|
|
12885
|
+
cascaded: settled.cascaded
|
|
12886
|
+
}), settledResult({
|
|
12887
|
+
...settled,
|
|
12888
|
+
changed: settled.instance._rev !== current._rev
|
|
12889
|
+
});
|
|
11902
12890
|
},
|
|
11903
12891
|
setStage: async rawArgs => {
|
|
11904
12892
|
const args = taggedScope(rawArgs, REQUEST_TAG.setStage), {client: client, tag: tag, instanceId: instanceId, targetStage: targetStage, reason: reason, executionContext: executionContext} = args;
|
|
11905
12893
|
return runCommitVerb({
|
|
11906
12894
|
args: args,
|
|
11907
12895
|
op: "setStage",
|
|
11908
|
-
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
12896
|
+
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
11909
12897
|
const result = await setStage({
|
|
11910
12898
|
client: client,
|
|
11911
12899
|
instanceId: instanceId,
|
|
@@ -11925,34 +12913,29 @@ const workflow = {
|
|
|
11925
12913
|
executionContext: executionContext,
|
|
11926
12914
|
telemetry: args.telemetry
|
|
11927
12915
|
})
|
|
11928
|
-
})
|
|
12916
|
+
});
|
|
12917
|
+
return resolveTelemetry(args.telemetry).log(WorkflowStageSet, {
|
|
12918
|
+
...definitionHashFragment(before.pinnedContentHash),
|
|
12919
|
+
instanceId: instanceId,
|
|
12920
|
+
changed: result.fired
|
|
12921
|
+
}), adminOverrideResult({
|
|
11929
12922
|
client: client,
|
|
12923
|
+
tag: tag,
|
|
11930
12924
|
instanceId: instanceId,
|
|
12925
|
+
fired: result.fired,
|
|
11931
12926
|
actor: actor,
|
|
11932
12927
|
clientForGdr: clientForGdr,
|
|
11933
12928
|
refSurface: refSurface,
|
|
11934
12929
|
memberRolesLoader: memberRolesLoader,
|
|
11935
12930
|
clock: clock,
|
|
12931
|
+
now: now,
|
|
11936
12932
|
...executionContext !== void 0 ? {
|
|
11937
12933
|
executionContext: executionContext
|
|
11938
12934
|
} : {},
|
|
11939
12935
|
...args.telemetry !== void 0 ? {
|
|
11940
12936
|
telemetry: args.telemetry
|
|
11941
12937
|
} : {}
|
|
11942
|
-
})
|
|
11943
|
-
return resolveTelemetry(args.telemetry).log(WorkflowStageSet, {
|
|
11944
|
-
...definitionHashFragment(before.pinnedContentHash),
|
|
11945
|
-
instanceId: instanceId,
|
|
11946
|
-
changed: result.fired
|
|
11947
|
-
}), {
|
|
11948
|
-
instance: await reload({
|
|
11949
|
-
client: client,
|
|
11950
|
-
instanceId: instanceId,
|
|
11951
|
-
tag: tag
|
|
11952
|
-
}),
|
|
11953
|
-
cascaded: cascaded,
|
|
11954
|
-
changed: result.fired
|
|
11955
|
-
};
|
|
12938
|
+
});
|
|
11956
12939
|
}
|
|
11957
12940
|
});
|
|
11958
12941
|
},
|
|
@@ -11985,7 +12968,7 @@ const workflow = {
|
|
|
11985
12968
|
...definitionHashFragment(before.pinnedContentHash),
|
|
11986
12969
|
instanceId: instanceId,
|
|
11987
12970
|
changed: changed
|
|
11988
|
-
}), {
|
|
12971
|
+
}), settledResult({
|
|
11989
12972
|
instance: await reload({
|
|
11990
12973
|
client: client,
|
|
11991
12974
|
instanceId: instanceId,
|
|
@@ -11993,7 +12976,7 @@ const workflow = {
|
|
|
11993
12976
|
}),
|
|
11994
12977
|
cascaded: 0,
|
|
11995
12978
|
changed: changed
|
|
11996
|
-
};
|
|
12979
|
+
});
|
|
11997
12980
|
}
|
|
11998
12981
|
});
|
|
11999
12982
|
},
|
|
@@ -12003,7 +12986,7 @@ const workflow = {
|
|
|
12003
12986
|
return runCommitVerb({
|
|
12004
12987
|
args: args,
|
|
12005
12988
|
op: "resetActivity",
|
|
12006
|
-
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
12989
|
+
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
12007
12990
|
const result = await resetActivity({
|
|
12008
12991
|
client: client,
|
|
12009
12992
|
instanceId: instanceId,
|
|
@@ -12021,34 +13004,29 @@ const workflow = {
|
|
|
12021
13004
|
executionContext: executionContext,
|
|
12022
13005
|
telemetry: args.telemetry
|
|
12023
13006
|
})
|
|
12024
|
-
})
|
|
13007
|
+
});
|
|
13008
|
+
return resolveTelemetry(args.telemetry).log(WorkflowActivityReset, {
|
|
13009
|
+
...definitionHashFragment(before.pinnedContentHash),
|
|
13010
|
+
instanceId: instanceId,
|
|
13011
|
+
changed: result.fired
|
|
13012
|
+
}), adminOverrideResult({
|
|
12025
13013
|
client: client,
|
|
13014
|
+
tag: tag,
|
|
12026
13015
|
instanceId: instanceId,
|
|
13016
|
+
fired: result.fired,
|
|
12027
13017
|
actor: actor,
|
|
12028
13018
|
clientForGdr: clientForGdr,
|
|
12029
13019
|
refSurface: refSurface,
|
|
12030
13020
|
memberRolesLoader: memberRolesLoader,
|
|
12031
13021
|
clock: clock,
|
|
13022
|
+
now: now,
|
|
12032
13023
|
...executionContext !== void 0 ? {
|
|
12033
13024
|
executionContext: executionContext
|
|
12034
13025
|
} : {},
|
|
12035
13026
|
...args.telemetry !== void 0 ? {
|
|
12036
13027
|
telemetry: args.telemetry
|
|
12037
13028
|
} : {}
|
|
12038
|
-
})
|
|
12039
|
-
return resolveTelemetry(args.telemetry).log(WorkflowActivityReset, {
|
|
12040
|
-
...definitionHashFragment(before.pinnedContentHash),
|
|
12041
|
-
instanceId: instanceId,
|
|
12042
|
-
changed: result.fired
|
|
12043
|
-
}), {
|
|
12044
|
-
instance: await reload({
|
|
12045
|
-
client: client,
|
|
12046
|
-
instanceId: instanceId,
|
|
12047
|
-
tag: tag
|
|
12048
|
-
}),
|
|
12049
|
-
cascaded: cascaded,
|
|
12050
|
-
changed: result.fired
|
|
12051
|
-
};
|
|
13029
|
+
});
|
|
12052
13030
|
}
|
|
12053
13031
|
});
|
|
12054
13032
|
},
|
|
@@ -12381,8 +13359,8 @@ async function startFreshInstance(args) {
|
|
|
12381
13359
|
extraHistory: fieldDiscards
|
|
12382
13360
|
} : {}
|
|
12383
13361
|
});
|
|
12384
|
-
await client.create(base, SYNC_COMMIT);
|
|
12385
|
-
const
|
|
13362
|
+
await client.create(instanceDocumentForWrite(base), SYNC_COMMIT);
|
|
13363
|
+
const settled = await settleStart({
|
|
12386
13364
|
client: client,
|
|
12387
13365
|
tag: tag,
|
|
12388
13366
|
instanceId: id,
|
|
@@ -12404,15 +13382,15 @@ async function startFreshInstance(args) {
|
|
|
12404
13382
|
viaSpawn: !1
|
|
12405
13383
|
}))
|
|
12406
13384
|
});
|
|
12407
|
-
return {
|
|
13385
|
+
return settledResult({
|
|
13386
|
+
...settled,
|
|
12408
13387
|
instance: await reload({
|
|
12409
13388
|
client: client,
|
|
12410
13389
|
instanceId: id,
|
|
12411
13390
|
tag: tag
|
|
12412
13391
|
}),
|
|
12413
|
-
cascaded: cascaded,
|
|
12414
13392
|
changed: !0
|
|
12415
|
-
};
|
|
13393
|
+
});
|
|
12416
13394
|
}
|
|
12417
13395
|
|
|
12418
13396
|
function assertInitialStageExists(definition) {
|
|
@@ -12587,7 +13565,7 @@ function missingHandlerMessage(info) {
|
|
|
12587
13565
|
}
|
|
12588
13566
|
|
|
12589
13567
|
async function verifyDeployedDefinitionsInternal(args) {
|
|
12590
|
-
const {tag: tag,
|
|
13568
|
+
const {tag: tag, handlers: handlers, missingHandler: missingHandler, logger: logger} = args, client = withRequestTag(args.client, REQUEST_TAG.verifyDefinitions);
|
|
12591
13569
|
invariants.validateTag(tag);
|
|
12592
13570
|
const log = logger("verifyDeployedDefinitions"), definitions = (await client.fetch(definitionsListGroq("asc"), {
|
|
12593
13571
|
tag: tag
|
|
@@ -12597,7 +13575,7 @@ async function verifyDeployedDefinitionsInternal(args) {
|
|
|
12597
13575
|
version: def.version,
|
|
12598
13576
|
_id: def._id
|
|
12599
13577
|
}), walkEffectNames(def, (name, location) => {
|
|
12600
|
-
if (
|
|
13578
|
+
if (handlers[name] !== void 0) return;
|
|
12601
13579
|
const key = `${name}@@${def._id}`;
|
|
12602
13580
|
let bucket = missingByName.get(key);
|
|
12603
13581
|
bucket === void 0 && (bucket = {
|
|
@@ -12656,7 +13634,7 @@ function isCancelledCompletion(data) {
|
|
|
12656
13634
|
}
|
|
12657
13635
|
|
|
12658
13636
|
async function drainEffectsInternal(args) {
|
|
12659
|
-
const {tag: tag, workflowResource: workflowResource, instanceId: instanceId,
|
|
13637
|
+
const {tag: tag, workflowResource: workflowResource, instanceId: instanceId, handlers: handlers, missingHandler: missingHandler, logger: logger, handlerClient: rawHandlerClient, handlerResourceClients: rawHandlerResourceClients} = args, cascadeTelemetry = drainCascadeTelemetry(args.telemetry), {client: client, resourceClients: resourceClients} = taggedScope(args, REQUEST_TAG.drain), leaseMs = args.leaseMs ?? DEFAULT_EFFECT_LEASE_MS, clock = args.clock ?? wallClock, handlerClient = effectHandlerClient(rawHandlerClient), handlerResourceClients = effectHandlerResolver(rawHandlerResourceClients), routeGdr = buildClientForGdr({
|
|
12660
13638
|
client: handlerClient,
|
|
12661
13639
|
workflowResource: workflowResource,
|
|
12662
13640
|
resourceClients: handlerResourceClients
|
|
@@ -12676,7 +13654,7 @@ async function drainEffectsInternal(args) {
|
|
|
12676
13654
|
resourceClients: resourceClients
|
|
12677
13655
|
} : {},
|
|
12678
13656
|
instanceId: instanceId,
|
|
12679
|
-
|
|
13657
|
+
handlers: handlers,
|
|
12680
13658
|
missingHandler: missingHandler,
|
|
12681
13659
|
logger: logger,
|
|
12682
13660
|
log: log,
|
|
@@ -12708,7 +13686,7 @@ async function drainOneCandidate(pass) {
|
|
|
12708
13686
|
skippedKeys: skippedKeys
|
|
12709
13687
|
});
|
|
12710
13688
|
if (candidate === void 0) return !1;
|
|
12711
|
-
const handler = pass.
|
|
13689
|
+
const handler = pass.handlers[candidate.name];
|
|
12712
13690
|
if (handler === void 0) return await assertSkippableOrThrow({
|
|
12713
13691
|
missingHandler: pass.missingHandler,
|
|
12714
13692
|
candidate: candidate,
|
|
@@ -13077,7 +14055,7 @@ function createInstanceSession(args) {
|
|
|
13077
14055
|
} : {}
|
|
13078
14056
|
};
|
|
13079
14057
|
previewOp(site, preview);
|
|
13080
|
-
const visit = site.scope === "workflow" ? void 0 : findOpenStageEntry(instance)?._key, row = {
|
|
14058
|
+
const visit = site.scope === "workflow" ? void 0 : invariants.findOpenStageEntry(instance)?._key, row = {
|
|
13081
14059
|
preview: preview,
|
|
13082
14060
|
...visit !== void 0 ? {
|
|
13083
14061
|
visit: visit
|
|
@@ -13086,7 +14064,7 @@ function createInstanceSession(args) {
|
|
|
13086
14064
|
return previews.set(key, preview.mode === "append" ? [ ...rows, row ] : [ row ]),
|
|
13087
14065
|
key;
|
|
13088
14066
|
}, optimisticSelf = () => {
|
|
13089
|
-
const visit = findOpenStageEntry(instance)?._key;
|
|
14067
|
+
const visit = invariants.findOpenStageEntry(instance)?._key;
|
|
13090
14068
|
for (const [key, rows] of previews) {
|
|
13091
14069
|
const live = rows.filter(row => row.visit === void 0 || row.visit === visit), target = live[0]?.preview.target;
|
|
13092
14070
|
target === void 0 || previewSiteOf({
|
|
@@ -13117,6 +14095,7 @@ function createInstanceSession(args) {
|
|
|
13117
14095
|
snapshot: snapshotFrom(held, normalizedSelf),
|
|
13118
14096
|
guards: guards,
|
|
13119
14097
|
resourceGrants: resourceGrants,
|
|
14098
|
+
guardDereference: clientGuardDereference(evalScope.client),
|
|
13120
14099
|
...localPrincipalId !== void 0 ? {
|
|
13121
14100
|
localPrincipalId: localPrincipalId
|
|
13122
14101
|
} : {},
|
|
@@ -13131,7 +14110,7 @@ function createInstanceSession(args) {
|
|
|
13131
14110
|
} : {}
|
|
13132
14111
|
});
|
|
13133
14112
|
}, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope, memberRolesLoader: memberRolesLoader}) => {
|
|
13134
|
-
const
|
|
14113
|
+
const settled = await cascadeHeld({
|
|
13135
14114
|
scope: scope,
|
|
13136
14115
|
actor: actor,
|
|
13137
14116
|
held: held,
|
|
@@ -13141,14 +14120,14 @@ function createInstanceSession(args) {
|
|
|
13141
14120
|
client: scope.client,
|
|
13142
14121
|
instanceId: instance._id,
|
|
13143
14122
|
tag: tag
|
|
13144
|
-
}), {
|
|
14123
|
+
}), settledResult({
|
|
14124
|
+
...settled,
|
|
13145
14125
|
instance: instance,
|
|
13146
|
-
cascaded: cascaded,
|
|
13147
14126
|
changed: !0,
|
|
13148
14127
|
...ranOps !== void 0 ? {
|
|
13149
14128
|
ranOps: ranOps
|
|
13150
14129
|
} : {}
|
|
13151
|
-
};
|
|
14130
|
+
});
|
|
13152
14131
|
}, cascadeHeld = ({scope: scope, actor: actor, held: held, memberRolesLoader: memberRolesLoader}) => cascade({
|
|
13153
14132
|
client: scope.client,
|
|
13154
14133
|
instanceId: instance._id,
|
|
@@ -13259,13 +14238,14 @@ function createInstanceSession(args) {
|
|
|
13259
14238
|
identity: invariants.lakePrincipalId({
|
|
13260
14239
|
actor: actor,
|
|
13261
14240
|
localPrincipalId: localPrincipalId
|
|
13262
|
-
})
|
|
14241
|
+
}),
|
|
14242
|
+
dereference: clientGuardDereference(tickScope.client)
|
|
13263
14243
|
});
|
|
13264
14244
|
const before = await reload({
|
|
13265
14245
|
client: tickScope.client,
|
|
13266
14246
|
instanceId: instance._id,
|
|
13267
14247
|
tag: tag
|
|
13268
|
-
}),
|
|
14248
|
+
}), settled = await cascadeHeld({
|
|
13269
14249
|
scope: tickScope,
|
|
13270
14250
|
actor: actor,
|
|
13271
14251
|
held: held,
|
|
@@ -13278,12 +14258,12 @@ function createInstanceSession(args) {
|
|
|
13278
14258
|
}), telemetry.log(WorkflowInstanceTicked, {
|
|
13279
14259
|
...definitionHashFragment(instance.pinnedContentHash),
|
|
13280
14260
|
instanceId: instance._id,
|
|
13281
|
-
cascaded: cascaded
|
|
13282
|
-
}), {
|
|
14261
|
+
cascaded: settled.cascaded
|
|
14262
|
+
}), settledResult({
|
|
14263
|
+
...settled,
|
|
13283
14264
|
instance: instance,
|
|
13284
|
-
cascaded: cascaded,
|
|
13285
14265
|
changed: instance._rev !== before._rev
|
|
13286
|
-
};
|
|
14266
|
+
});
|
|
13287
14267
|
});
|
|
13288
14268
|
},
|
|
13289
14269
|
fireAction({activity: activity, action: action, params: params}) {
|
|
@@ -13433,7 +14413,10 @@ const silentLogger = {
|
|
|
13433
14413
|
function createEngine(args) {
|
|
13434
14414
|
const {workflowResource: workflowResource, clock: clock, tag: tag, executionContext: executionContext} = args, {client: client, resourceClients: resourceClients} = taggedScope(args, REQUEST_TAG.engine);
|
|
13435
14415
|
invariants.validateTag(tag);
|
|
13436
|
-
const
|
|
14416
|
+
const effects = {
|
|
14417
|
+
handlers: args.effects?.handlers ?? {},
|
|
14418
|
+
missingHandler: args.effects?.missingHandler ?? "fail"
|
|
14419
|
+
}, logger = args.loggerFactory ?? defaultLoggerFactory, telemetry = resolveTelemetry(args.telemetry), EMPTY_DRAIN_LOG_INTERVAL_MS = 6e4;
|
|
13437
14420
|
let lastEmptyDrainLoggedAt;
|
|
13438
14421
|
const emptyDrainDue = () => {
|
|
13439
14422
|
const now = Date.parse((clock ?? wallClock)());
|
|
@@ -13464,8 +14447,7 @@ function createEngine(args) {
|
|
|
13464
14447
|
client: client,
|
|
13465
14448
|
tag: tag,
|
|
13466
14449
|
workflowResource: workflowResource,
|
|
13467
|
-
|
|
13468
|
-
missingHandler: missingHandler,
|
|
14450
|
+
effects: effects,
|
|
13469
14451
|
logger: logger,
|
|
13470
14452
|
telemetry: telemetry,
|
|
13471
14453
|
resolveActor: rest => resolveClientActor(client, rest),
|
|
@@ -13519,12 +14501,11 @@ function createEngine(args) {
|
|
|
13519
14501
|
workflowResource: workflowResource,
|
|
13520
14502
|
...optionalScope,
|
|
13521
14503
|
instanceId: instanceId,
|
|
13522
|
-
|
|
13523
|
-
missingHandler: missingHandler,
|
|
14504
|
+
...effects,
|
|
13524
14505
|
logger: logger,
|
|
13525
14506
|
telemetry: telemetry,
|
|
13526
|
-
...args.
|
|
13527
|
-
leaseMs: args.
|
|
14507
|
+
...args.effects?.leaseMs !== void 0 ? {
|
|
14508
|
+
leaseMs: args.effects.leaseMs
|
|
13528
14509
|
} : {}
|
|
13529
14510
|
}), drained = result.drained;
|
|
13530
14511
|
return (drained.length > 0 || emptyDrainDue()) && telemetry.log(WorkflowEffectsDrained, {
|
|
@@ -13537,8 +14518,7 @@ function createEngine(args) {
|
|
|
13537
14518
|
verifyDeployedDefinitions: () => verifyDeployedDefinitionsInternal({
|
|
13538
14519
|
client: client,
|
|
13539
14520
|
tag: tag,
|
|
13540
|
-
|
|
13541
|
-
missingHandler: missingHandler,
|
|
14521
|
+
...effects,
|
|
13542
14522
|
logger: logger
|
|
13543
14523
|
})
|
|
13544
14524
|
};
|
|
@@ -14093,6 +15073,8 @@ exports.DECISION_SEMANTICS = invariants.DECISION_SEMANTICS;
|
|
|
14093
15073
|
|
|
14094
15074
|
exports.DEFAULT_TRANSITION_WHEN = invariants.DEFAULT_TRANSITION_WHEN;
|
|
14095
15075
|
|
|
15076
|
+
exports.DOCUMENT_VALUE_PERMISSIONS = invariants.DOCUMENT_VALUE_PERMISSIONS;
|
|
15077
|
+
|
|
14096
15078
|
exports.DRIVER_KINDS = invariants.DRIVER_KINDS;
|
|
14097
15079
|
|
|
14098
15080
|
exports.DefinitionInUseError = invariants.DefinitionInUseError;
|
|
@@ -14131,8 +15113,20 @@ exports.WORKFLOW_DEFINITION_TYPE = invariants.WORKFLOW_DEFINITION_TYPE;
|
|
|
14131
15113
|
|
|
14132
15114
|
exports.WorkflowError = invariants.WorkflowError;
|
|
14133
15115
|
|
|
15116
|
+
exports.activeAssignmentMembers = invariants.activeAssignmentMembers;
|
|
15117
|
+
|
|
14134
15118
|
exports.actorFulfillsRole = invariants.actorFulfillsRole;
|
|
14135
15119
|
|
|
15120
|
+
exports.actorMatchesAssignment = invariants.actorMatchesAssignment;
|
|
15121
|
+
|
|
15122
|
+
exports.assignmentMatch = invariants.assignmentMatch;
|
|
15123
|
+
|
|
15124
|
+
exports.assignmentMembers = invariants.assignmentMembers;
|
|
15125
|
+
|
|
15126
|
+
exports.assignmentState = invariants.assignmentState;
|
|
15127
|
+
|
|
15128
|
+
exports.assignmentStateCounts = invariants.assignmentStateCounts;
|
|
15129
|
+
|
|
14136
15130
|
exports.classifyPrincipalId = invariants.classifyPrincipalId;
|
|
14137
15131
|
|
|
14138
15132
|
exports.clientConfigFromResource = invariants.clientConfigFromResource;
|
|
@@ -14151,6 +15145,10 @@ exports.errorMessage = invariants.errorMessage;
|
|
|
14151
15145
|
|
|
14152
15146
|
exports.extractDocumentId = invariants.extractDocumentId;
|
|
14153
15147
|
|
|
15148
|
+
exports.findCurrentActivityEntry = invariants.findCurrentActivityEntry;
|
|
15149
|
+
|
|
15150
|
+
exports.findOpenStageEntry = invariants.findOpenStageEntry;
|
|
15151
|
+
|
|
14154
15152
|
exports.gdrFromResource = invariants.gdrFromResource;
|
|
14155
15153
|
|
|
14156
15154
|
exports.gdrRef = invariants.gdrRef;
|
|
@@ -14159,8 +15157,14 @@ exports.gdrUri = invariants.gdrUri;
|
|
|
14159
15157
|
|
|
14160
15158
|
exports.groupMembershipNames = invariants.groupMembershipNames;
|
|
14161
15159
|
|
|
15160
|
+
exports.identityMatchesAssignment = invariants.identityMatchesAssignment;
|
|
15161
|
+
|
|
15162
|
+
exports.instanceAssignmentStateCounts = invariants.instanceAssignmentStateCounts;
|
|
15163
|
+
|
|
14162
15164
|
exports.isCascadeFired = invariants.isCascadeFired;
|
|
14163
15165
|
|
|
15166
|
+
exports.isFilterScopedOut = invariants.isFilterScopedOut;
|
|
15167
|
+
|
|
14164
15168
|
exports.isGdr = invariants.isGdr;
|
|
14165
15169
|
|
|
14166
15170
|
exports.isInputSourced = invariants.isInputSourced;
|
|
@@ -14183,6 +15187,8 @@ exports.isTodoListItem = invariants.isTodoListItem;
|
|
|
14183
15187
|
|
|
14184
15188
|
exports.lakePrincipalId = invariants.lakePrincipalId;
|
|
14185
15189
|
|
|
15190
|
+
exports.openActivityAssignments = invariants.openActivityAssignments;
|
|
15191
|
+
|
|
14186
15192
|
exports.parseGdr = invariants.parseGdr;
|
|
14187
15193
|
|
|
14188
15194
|
exports.parseResourceGdr = invariants.parseResourceGdr;
|
|
@@ -14337,6 +15343,8 @@ exports.CONTEXT_ENTRY_DISPLAY = CONTEXT_ENTRY_DISPLAY;
|
|
|
14337
15343
|
|
|
14338
15344
|
exports.CascadeLimitError = CascadeLimitError;
|
|
14339
15345
|
|
|
15346
|
+
exports.ConcurrentCascadeError = ConcurrentCascadeError;
|
|
15347
|
+
|
|
14340
15348
|
exports.ConcurrentCommitEffectOpsError = ConcurrentCommitEffectOpsError;
|
|
14341
15349
|
|
|
14342
15350
|
exports.ConcurrentCompleteEffectError = ConcurrentCompleteEffectError;
|
|
@@ -14475,6 +15483,8 @@ exports.assertReadableModel = assertReadableModel;
|
|
|
14475
15483
|
|
|
14476
15484
|
exports.assertReaderModelAcknowledgement = assertReaderModelAcknowledgement;
|
|
14477
15485
|
|
|
15486
|
+
exports.assignmentPrefilter = assignmentPrefilter;
|
|
15487
|
+
|
|
14478
15488
|
exports.autonomySummary = autonomySummary;
|
|
14479
15489
|
|
|
14480
15490
|
exports.availableActions = availableActions;
|
|
@@ -14485,9 +15495,11 @@ exports.buildSnapshot = buildSnapshot;
|
|
|
14485
15495
|
|
|
14486
15496
|
exports.checklistLines = checklistLines;
|
|
14487
15497
|
|
|
15498
|
+
exports.clientGuardDereference = clientGuardDereference;
|
|
15499
|
+
|
|
14488
15500
|
exports.clientProjectUserDirectory = clientProjectUserDirectory;
|
|
14489
15501
|
|
|
14490
|
-
exports.
|
|
15502
|
+
exports.compileGuards = compileGuards;
|
|
14491
15503
|
|
|
14492
15504
|
exports.computeDiffEntries = computeDiffEntries;
|
|
14493
15505
|
|
|
@@ -14511,6 +15523,8 @@ exports.definitionDeployedData = definitionDeployedData;
|
|
|
14511
15523
|
|
|
14512
15524
|
exports.definitionLookupGroq = definitionLookupGroq;
|
|
14513
15525
|
|
|
15526
|
+
exports.definitionRoleNames = definitionRoleNames;
|
|
15527
|
+
|
|
14514
15528
|
exports.definitionTagsGroq = definitionTagsGroq;
|
|
14515
15529
|
|
|
14516
15530
|
exports.definitionsListGroq = definitionsListGroq;
|
|
@@ -14577,10 +15591,6 @@ exports.fieldTreeShape = fieldTreeShape;
|
|
|
14577
15591
|
|
|
14578
15592
|
exports.findActivityNode = findActivityNode;
|
|
14579
15593
|
|
|
14580
|
-
exports.findCurrentActivityEntry = findCurrentActivityEntry;
|
|
14581
|
-
|
|
14582
|
-
exports.findOpenStageEntry = findOpenStageEntry;
|
|
14583
|
-
|
|
14584
15594
|
exports.findStageNode = findStageNode;
|
|
14585
15595
|
|
|
14586
15596
|
exports.groupSitesOf = groupSitesOf;
|
|
@@ -14621,8 +15631,6 @@ exports.isClientProjectUser = isClientProjectUser;
|
|
|
14621
15631
|
|
|
14622
15632
|
exports.isDefinitionApplicable = isDefinitionApplicable;
|
|
14623
15633
|
|
|
14624
|
-
exports.isFilterScopedOut = isFilterScopedOut;
|
|
14625
|
-
|
|
14626
15634
|
exports.isProjectUserNotFoundError = isProjectUserNotFoundError;
|
|
14627
15635
|
|
|
14628
15636
|
exports.isRevisionConflict = isRevisionConflict;
|
|
@@ -14703,6 +15711,8 @@ exports.silentLogger = silentLogger;
|
|
|
14703
15711
|
|
|
14704
15712
|
exports.singleSubjectRequirementRefused = singleSubjectRequirementRefused;
|
|
14705
15713
|
|
|
15714
|
+
exports.snapshotGuardDereference = snapshotGuardDereference;
|
|
15715
|
+
|
|
14706
15716
|
exports.stageAutonomyOf = stageAutonomyOf;
|
|
14707
15717
|
|
|
14708
15718
|
exports.startFieldsParam = startFieldsParam;
|