@sanity/workflow-engine 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +140 -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 +713 -1586
- package/dist/index.d.ts +713 -1586
- package/dist/index.js +1691 -709
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,45 +1,16 @@
|
|
|
1
|
-
import { rethrowWithContext, andConditions, deriveActivityKind, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr,
|
|
1
|
+
import { rethrowWithContext, findOpenStageEntry, findCurrentActivityEntry, andConditions, deriveActivityKind, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, WorkflowError, gdrFromResource, selfGdr, isGdrUri, MUTATION_GUARD_ID_SPACES, mutationGuardActionIdSpace, LAKE_MUTATION_GUARD_ACTIONS, isBareDocumentId, toBareId, normalizeAssignmentMembers, isSingleDocRefKind, actorMatchesAssignment, assignmentMembers, resolvedChildStatus, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, isAssignmentFieldEntry, isAlwaysArrayFieldKind, evaluateCondition, isRecord, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, GUARD_ACTIONS_REQUIRED_MESSAGE, conditionEffectReads, EFFECTS_READ, datasetResourceParts, mutationGuardRequiresSplitEmission, MUTATION_GUARD_ACTIONS, assignmentKindAcceptsRoles, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, liveSubworkflows, isCascadeFired, classifyPrincipalId, directoryBridgeId, parseGdr, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, isParseableInstant, NonEmptyString, tolerantEntries, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, InstanceNotFoundError, evaluateConditionOutcome, runGroq as runGroq$1, FIELD_READ, resourceGdr, condemnSubworkflow, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, lakePrincipalId, firstCarriedGlobalId, driverKind, actorFulfillsRole, condemnedSubworkflows, EffectNotFoundError, isFilterScopedOut, deriveExecutorClassification, validateTag, activeAssignmentMembers, extractDocumentId, UNIVERSAL_ROLE_ALIAS_KEY, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, DefinitionInUseError, groupMembershipNames } from "./_chunks-es/invariants.js";
|
|
2
2
|
|
|
3
|
-
import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, SIGNAL_SEMANTICS, SYSTEM_IDENTITY, clientConfigFromResource, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
|
|
3
|
+
import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, SIGNAL_SEMANTICS, SYSTEM_IDENTITY, assignmentMatch, assignmentState, assignmentStateCounts, clientConfigFromResource, gdrUri, identityMatchesAssignment, instanceAssignmentStateCounts, isNotesEntry, isTodoListEntry, isTodoListItem, openActivityAssignments, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
|
|
4
4
|
|
|
5
|
-
import { atomNode, dedupeBy, analyzeCondition, atomReadsDataset, checklistLines as checklistLines$1, phrase, quoted, listAnd, describeAtom as describeAtom$1, describeCondition as describeCondition$1, guillemets, formatValue, humanize, listOr, scopeReadOf, describeRead, explainCondition,
|
|
5
|
+
import { atomNode, dedupeBy, analyzeCondition, atomReadsDataset, checklistLines as checklistLines$1, phrase, quoted, listAnd, describeAtom as describeAtom$1, describeCondition as describeCondition$1, guillemets, formatValue, humanize, listOr, scopeReadOf, describeRead, explainCondition, _exhaustiveOptions, whatIfCondition, runGroq, formatRead, dedupeReads, MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
|
|
6
6
|
|
|
7
|
-
import { MAX_COUNTERFACTUAL_INDEX as MAX_COUNTERFACTUAL_INDEX2, NEUTRAL_MARK, OUTCOME_MARKS, analyzeCondition as analyzeCondition2, atomReadsDataset as atomReadsDataset2, explainCondition as explainCondition2, formatRead, guillemets as guillemets2, humanize as humanize2, isComparisonOp, quoted as quoted2, sentenceCase, whatIfCondition as whatIfCondition2, withAssignment } from "@sanity/groq-condition-describe";
|
|
7
|
+
import { MAX_COUNTERFACTUAL_INDEX as MAX_COUNTERFACTUAL_INDEX2, NEUTRAL_MARK, OUTCOME_MARKS, analyzeCondition as analyzeCondition2, atomReadsDataset as atomReadsDataset2, explainCondition as explainCondition2, formatRead as formatRead2, guillemets as guillemets2, humanize as humanize2, isComparisonOp, quoted as quoted2, sentenceCase, whatIfCondition as whatIfCondition2, withAssignment } from "@sanity/groq-condition-describe";
|
|
8
8
|
|
|
9
9
|
import { evaluate, parse } from "groq-js";
|
|
10
10
|
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
function isFilterScopedOut(entry) {
|
|
14
|
-
return entry.status === "skipped" && entry.startedAt === void 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function liveSubworkflows(host) {
|
|
18
|
-
return (host.subworkflows ?? []).filter(row => row.resolved === void 0);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function resolvedChildStatus(child) {
|
|
22
|
-
if (!(child.completedAt === void 0 || child.completedAt === null)) return child.abortedAt !== void 0 && child.abortedAt !== null ? "aborted" : "done";
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function condemnedSubworkflows(host) {
|
|
26
|
-
return liveSubworkflows(host).filter(row => row.abortPending !== void 0);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function condemnSubworkflow(row, owed) {
|
|
30
|
-
row.abortPending !== void 0 || row.resolved !== void 0 || (row.abortPending = {
|
|
31
|
-
at: owed.at,
|
|
32
|
-
reason: owed.reason
|
|
33
|
-
});
|
|
34
|
-
}
|
|
11
|
+
import { getPublishedId, getDraftId } from "@sanity/id-utils";
|
|
35
12
|
|
|
36
|
-
|
|
37
|
-
return host.stages.find(s => s.name === host.currentStage && s.exitedAt === void 0);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function findCurrentActivityEntry(host, activityName) {
|
|
41
|
-
return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
|
|
42
|
-
}
|
|
13
|
+
import * as v from "valibot";
|
|
43
14
|
|
|
44
15
|
const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
|
|
45
16
|
|
|
@@ -458,6 +429,11 @@ function rolesGateOf(atom) {
|
|
|
458
429
|
if (!(count.type !== "FuncCall" || count.name !== "count" || count.args.length !== 1)) return rolesFilterList(count.args[0]);
|
|
459
430
|
}
|
|
460
431
|
|
|
432
|
+
function isAssignedGate(atom) {
|
|
433
|
+
const node = atomNode(atom);
|
|
434
|
+
return !atom.negated && node.type === "Parameter" && node.name === "assigned";
|
|
435
|
+
}
|
|
436
|
+
|
|
461
437
|
function rolesFilterList(node) {
|
|
462
438
|
if (node.type !== "Filter") return;
|
|
463
439
|
const base = node.base;
|
|
@@ -1746,27 +1722,38 @@ function startContextSyntaxIssues({groq: groq, vars: vars, context: context, ski
|
|
|
1746
1722
|
return [ ...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(", "));
|
|
1747
1723
|
}
|
|
1748
1724
|
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1725
|
+
const GUARD_DOC_TYPE = "temp.system.guard";
|
|
1726
|
+
|
|
1727
|
+
class MutationGuardDeniedError extends WorkflowError {
|
|
1728
|
+
denied;
|
|
1729
|
+
documentId;
|
|
1730
|
+
action;
|
|
1731
|
+
constructor(args) {
|
|
1732
|
+
const ids = args.denied.map(d => d.guardId).join(", ");
|
|
1733
|
+
super("mutation-guard-denied", `Mutation on "${args.documentId}" (${args.action}) denied by guard(s) [${ids}]`),
|
|
1734
|
+
this.name = "MutationGuardDeniedError", this.denied = args.denied, this.documentId = args.documentId,
|
|
1735
|
+
this.action = args.action;
|
|
1736
|
+
}
|
|
1737
|
+
static fromGuards(args) {
|
|
1738
|
+
return new MutationGuardDeniedError({
|
|
1739
|
+
documentId: args.documentId,
|
|
1740
|
+
action: args.action,
|
|
1741
|
+
denied: deniedGuardRefs(args.guards)
|
|
1742
|
+
});
|
|
1754
1743
|
}
|
|
1755
|
-
return current;
|
|
1756
1744
|
}
|
|
1757
1745
|
|
|
1758
|
-
function
|
|
1759
|
-
return
|
|
1746
|
+
function deniedGuardRefs(guards) {
|
|
1747
|
+
return guards.map(g => ({
|
|
1748
|
+
guardId: g._id,
|
|
1749
|
+
...g.name !== void 0 ? {
|
|
1750
|
+
name: g.name
|
|
1751
|
+
} : {}
|
|
1752
|
+
}));
|
|
1760
1753
|
}
|
|
1761
1754
|
|
|
1762
|
-
function
|
|
1763
|
-
|
|
1764
|
-
for (const part of path.split(".")) {
|
|
1765
|
-
if (current == null || typeof current != "object") return;
|
|
1766
|
-
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.`);
|
|
1767
|
-
current = current[part];
|
|
1768
|
-
}
|
|
1769
|
-
return current;
|
|
1755
|
+
function deniedGuardLabels(denied) {
|
|
1756
|
+
return denied.map(d => d.name ?? d.guardId);
|
|
1770
1757
|
}
|
|
1771
1758
|
|
|
1772
1759
|
function mapJsonStrings(value, transform) {
|
|
@@ -1835,199 +1822,658 @@ function overlayInstanceInSnapshot(snapshot, instance) {
|
|
|
1835
1822
|
};
|
|
1836
1823
|
}
|
|
1837
1824
|
|
|
1838
|
-
function
|
|
1839
|
-
|
|
1840
|
-
if (isSingleDocRefKind(kind)) {
|
|
1841
|
-
if (!isGdr(value)) return null;
|
|
1842
|
-
if (path === void 0 && targetKind !== void 0 && isSingleDocRefKind(targetKind)) return value;
|
|
1843
|
-
const base = derefBase(value, snapshot);
|
|
1844
|
-
return path === void 0 ? base : walkDocPath(base, path);
|
|
1845
|
-
}
|
|
1846
|
-
return path !== void 0 ? getPath(value, path) : value;
|
|
1825
|
+
function lakeGuardId(args) {
|
|
1826
|
+
return `${GUARD_DOC_TYPE}.${args.instanceDocId}.${args.guardName}`;
|
|
1847
1827
|
}
|
|
1848
1828
|
|
|
1849
|
-
function
|
|
1850
|
-
return
|
|
1851
|
-
_id: ref.id,
|
|
1852
|
-
_type: ref.type
|
|
1853
|
-
};
|
|
1829
|
+
function lakeActionsFor(action) {
|
|
1830
|
+
return action === "publish" ? [ "create", "update" ] : action === "unpublish" ? [ "delete" ] : [ action ];
|
|
1854
1831
|
}
|
|
1855
1832
|
|
|
1856
|
-
function
|
|
1857
|
-
const
|
|
1858
|
-
return
|
|
1859
|
-
self: selfGdr(instance),
|
|
1860
|
-
fields: renderedFields(instance.fields ?? [], snapshot),
|
|
1861
|
-
parent: parentRef(instance)?.id ?? null,
|
|
1862
|
-
ancestors: instance.ancestors.map(a => a.id),
|
|
1863
|
-
stage: instance.currentStage,
|
|
1864
|
-
now: now,
|
|
1865
|
-
context: contextMap(instance),
|
|
1866
|
-
effects: effectOutputsMap(instance),
|
|
1867
|
-
effectStatus: effectStatusMap(instance),
|
|
1868
|
-
activities: currentActivities2,
|
|
1869
|
-
subworkflows: subworkflowVarRows(instance, snapshot),
|
|
1870
|
-
...activityGateParams(currentActivities2),
|
|
1871
|
-
...extra
|
|
1872
|
-
};
|
|
1833
|
+
function lakeGuardActions(actions) {
|
|
1834
|
+
const requested = new Set(actions.flatMap(lakeActionsFor));
|
|
1835
|
+
return LAKE_MUTATION_GUARD_ACTIONS.filter(action => requested.has(action));
|
|
1873
1836
|
}
|
|
1874
1837
|
|
|
1875
|
-
function
|
|
1876
|
-
|
|
1877
|
-
return (instance.subworkflows ?? []).map(row => ({
|
|
1878
|
-
_id: toBareId(row.ref.id),
|
|
1879
|
-
rowKey: row.rowKey,
|
|
1880
|
-
activity: row.activity,
|
|
1881
|
-
action: row.action,
|
|
1882
|
-
definition: row.definition,
|
|
1883
|
-
current: row.stageEntry === openKey,
|
|
1884
|
-
...childState(row, snapshot),
|
|
1885
|
-
spawnedAt: row.spawnedAt
|
|
1886
|
-
}));
|
|
1838
|
+
function publishedId(id) {
|
|
1839
|
+
return getPublishedId(id);
|
|
1887
1840
|
}
|
|
1888
1841
|
|
|
1889
|
-
function
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1842
|
+
function draftId(id) {
|
|
1843
|
+
return getDraftId(id);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
function versionPatternTranslation(pattern) {
|
|
1847
|
+
const documentSeparator = pattern.indexOf(".", 9);
|
|
1848
|
+
if (documentSeparator === -1) return {
|
|
1849
|
+
issue: `id pattern "${pattern}" does not identify a versioned document`
|
|
1893
1850
|
};
|
|
1894
|
-
const
|
|
1895
|
-
return
|
|
1896
|
-
|
|
1897
|
-
status: "active"
|
|
1851
|
+
const documentPattern = pattern.slice(documentSeparator + 1);
|
|
1852
|
+
return /^\*+$/.test(documentPattern) ? {
|
|
1853
|
+
issue: `id pattern "${pattern}" cannot be translated from a release version to a draft or published document without broadening it to every document`
|
|
1898
1854
|
} : {
|
|
1899
|
-
|
|
1900
|
-
status: resolvedChildStatus(doc) ?? "active"
|
|
1855
|
+
documentPattern: documentPattern
|
|
1901
1856
|
};
|
|
1902
1857
|
}
|
|
1903
1858
|
|
|
1904
|
-
function
|
|
1905
|
-
return
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1859
|
+
function publishedPattern(pattern) {
|
|
1860
|
+
if (pattern.startsWith("drafts.")) return pattern.slice(7);
|
|
1861
|
+
if (!pattern.startsWith("versions.")) return pattern;
|
|
1862
|
+
const translated = versionPatternTranslation(pattern);
|
|
1863
|
+
if (translated.issue !== void 0) throw new Error(translated.issue);
|
|
1864
|
+
return translated.documentPattern;
|
|
1909
1865
|
}
|
|
1910
1866
|
|
|
1911
|
-
function
|
|
1912
|
-
|
|
1913
|
-
for (const entry of entries) out[entry.name] = renderedValue(entry, snapshot);
|
|
1914
|
-
return out;
|
|
1867
|
+
function draftPattern(pattern) {
|
|
1868
|
+
return `drafts.${publishedPattern(pattern)}`;
|
|
1915
1869
|
}
|
|
1916
1870
|
|
|
1917
|
-
function
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
value: entry.value,
|
|
1921
|
-
path: void 0,
|
|
1922
|
-
snapshot: snapshot
|
|
1923
|
-
});
|
|
1871
|
+
function idsInSpace(args) {
|
|
1872
|
+
const {ids: ids, space: space, sourceInstanceId: sourceInstanceId} = args;
|
|
1873
|
+
return space === "authored" ? ids : space === "published" ? [ ...new Set(ids.map(publishedId)) ] : [ ...new Set(ids.map(id => publishedId(id) === sourceInstanceId ? publishedId(id) : draftId(id))) ];
|
|
1924
1874
|
}
|
|
1925
1875
|
|
|
1926
|
-
function
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1876
|
+
function patternsInSpace(patterns, space) {
|
|
1877
|
+
if (space === "authored") return patterns;
|
|
1878
|
+
const convert = space === "edit" ? draftPattern : publishedPattern;
|
|
1879
|
+
return [ ...new Set(patterns.map(convert)) ];
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
function matchInSpace(args) {
|
|
1883
|
+
const {match: match, actions: actions, space: space, sourceInstanceId: sourceInstanceId} = args;
|
|
1930
1884
|
return {
|
|
1931
|
-
...
|
|
1932
|
-
...
|
|
1885
|
+
...match,
|
|
1886
|
+
...match.idRefs !== void 0 ? {
|
|
1887
|
+
idRefs: idsInSpace({
|
|
1888
|
+
ids: match.idRefs,
|
|
1889
|
+
space: space,
|
|
1890
|
+
sourceInstanceId: sourceInstanceId
|
|
1891
|
+
})
|
|
1892
|
+
} : {},
|
|
1893
|
+
...match.idPatterns !== void 0 ? {
|
|
1894
|
+
idPatterns: patternsInSpace(match.idPatterns, space)
|
|
1895
|
+
} : {},
|
|
1896
|
+
actions: lakeGuardActions(actions)
|
|
1933
1897
|
};
|
|
1934
1898
|
}
|
|
1935
1899
|
|
|
1936
|
-
function
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1900
|
+
function guardPartitions(id, actions) {
|
|
1901
|
+
return MUTATION_GUARD_ID_SPACES.flatMap(space => {
|
|
1902
|
+
const matchingActions = actions.filter(action => mutationGuardActionIdSpace(action) === space);
|
|
1903
|
+
return matchingActions.length > 0 ? [ {
|
|
1904
|
+
space: space,
|
|
1905
|
+
actions: matchingActions
|
|
1906
|
+
} ] : [];
|
|
1907
|
+
}).map((partition, index) => ({
|
|
1908
|
+
...partition,
|
|
1909
|
+
id: index === 0 ? id : `${id}.${partition.space}`
|
|
1943
1910
|
}));
|
|
1944
1911
|
}
|
|
1945
1912
|
|
|
1946
|
-
function
|
|
1947
|
-
|
|
1948
|
-
if (entry === void 0) return {};
|
|
1949
|
-
const out = {};
|
|
1950
|
-
for (const run of instance.effectHistory) run.stageEntryKey === entry._key && (out[run.name] = run.status);
|
|
1951
|
-
return out;
|
|
1913
|
+
function compiledGuardIds(args) {
|
|
1914
|
+
return guardPartitions(args.id, args.actions).map(partition => partition.id);
|
|
1952
1915
|
}
|
|
1953
1916
|
|
|
1954
|
-
function
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1917
|
+
function lakeGuardDocument(args) {
|
|
1918
|
+
return {
|
|
1919
|
+
_id: args.id,
|
|
1920
|
+
_type: GUARD_DOC_TYPE,
|
|
1921
|
+
resourceType: args.resourceType,
|
|
1922
|
+
resourceId: args.resourceId,
|
|
1923
|
+
owner: args.owner,
|
|
1924
|
+
sourceInstanceId: args.sourceInstanceId,
|
|
1925
|
+
sourceDefinition: args.sourceDefinition,
|
|
1926
|
+
sourceStage: args.sourceStage,
|
|
1927
|
+
...args.name !== void 0 ? {
|
|
1928
|
+
name: args.name
|
|
1929
|
+
} : {},
|
|
1930
|
+
...args.description !== void 0 ? {
|
|
1931
|
+
description: args.description
|
|
1932
|
+
} : {},
|
|
1933
|
+
match: args.match,
|
|
1934
|
+
predicate: args.predicate,
|
|
1935
|
+
metadata: args.metadata
|
|
1936
|
+
};
|
|
1958
1937
|
}
|
|
1959
1938
|
|
|
1960
|
-
function
|
|
1961
|
-
const
|
|
1962
|
-
|
|
1963
|
-
|
|
1939
|
+
function compileGuards(args) {
|
|
1940
|
+
const [first, ...remaining] = guardPartitions(args.id, args.match.actions);
|
|
1941
|
+
if (first === void 0) throw new Error("cannot compile a guard without an action");
|
|
1942
|
+
const compilePartition = ({space: space, actions: actions, id: id}) => lakeGuardDocument({
|
|
1943
|
+
...args,
|
|
1944
|
+
id: id,
|
|
1945
|
+
match: matchInSpace({
|
|
1946
|
+
match: args.match,
|
|
1947
|
+
actions: actions,
|
|
1948
|
+
space: space,
|
|
1949
|
+
sourceInstanceId: args.sourceInstanceId
|
|
1950
|
+
})
|
|
1951
|
+
});
|
|
1952
|
+
return [ compilePartition(first), ...remaining.map(compilePartition) ];
|
|
1964
1953
|
}
|
|
1965
1954
|
|
|
1966
|
-
function
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
rethrowWithContext(err, `context entry "${entry.name}" holds unparseable JSON`);
|
|
1971
|
-
}
|
|
1955
|
+
function globMatch(pattern, value) {
|
|
1956
|
+
if (!pattern.includes("*")) return pattern === value;
|
|
1957
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1958
|
+
return new RegExp(`^${escaped}$`).test(value);
|
|
1972
1959
|
}
|
|
1973
1960
|
|
|
1974
|
-
function
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
parent: typeof params.parent == "string" ? toBareId(params.parent) : params.parent,
|
|
1979
|
-
ancestors: Array.isArray(params.ancestors) ? params.ancestors.map(a => typeof a == "string" ? toBareId(a) : a) : params.ancestors,
|
|
1980
|
-
fields: stripFieldsForLake(params.fields)
|
|
1981
|
-
};
|
|
1961
|
+
function guardIdPatternIssue(pattern, actions) {
|
|
1962
|
+
const representativeId = pattern.replaceAll("*", "x");
|
|
1963
|
+
if (!isBareDocumentId(representativeId)) return `id pattern "${pattern}" is not a valid resource-local document-id glob; use document-id characters (letters, digits, \`_\`, \`-\`, \`.\`) and \`*\` wildcards`;
|
|
1964
|
+
if (actions?.some(action => mutationGuardActionIdSpace(action) !== "authored") && pattern.startsWith("versions.")) return versionPatternTranslation(pattern).issue;
|
|
1982
1965
|
}
|
|
1983
1966
|
|
|
1984
|
-
function
|
|
1985
|
-
return
|
|
1967
|
+
function parseGuardPredicate(predicate) {
|
|
1968
|
+
return parse(predicate, {
|
|
1969
|
+
mode: "delta"
|
|
1970
|
+
});
|
|
1986
1971
|
}
|
|
1987
1972
|
|
|
1988
|
-
function
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
return
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1973
|
+
function guardPredicateSyntaxIssue(predicate) {
|
|
1974
|
+
try {
|
|
1975
|
+
parseGuardPredicate(predicate);
|
|
1976
|
+
return;
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
return errorMessage(error);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1995
1981
|
|
|
1996
|
-
|
|
1997
|
-
|
|
1982
|
+
function lakeDocumentIdForAction(id, action) {
|
|
1983
|
+
return mutationGuardActionIdSpace(action) === "published" ? publishedId(id) : id;
|
|
1984
|
+
}
|
|
1998
1985
|
|
|
1999
|
-
|
|
2000
|
-
|
|
1986
|
+
function legacyLifecycleActionFor(action, documentId) {
|
|
1987
|
+
if (publishedId(documentId) === documentId) {
|
|
1988
|
+
if (action === "create" || action === "update") return "publish";
|
|
1989
|
+
if (action === "delete") return "unpublish";
|
|
2001
1990
|
}
|
|
2002
1991
|
}
|
|
2003
1992
|
|
|
2004
|
-
function
|
|
2005
|
-
const
|
|
2006
|
-
|
|
1993
|
+
function guardMatches({guard: guard, doc: doc, action: action}) {
|
|
1994
|
+
const m = guard.match, documentId = lakeDocumentIdForAction(doc.id, action), legacyLifecycleAction = legacyLifecycleActionFor(action, documentId);
|
|
1995
|
+
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;
|
|
1996
|
+
if (m.idRefs && m.idRefs.length > 0 || m.idPatterns && m.idPatterns.length > 0) {
|
|
1997
|
+
const byRef = m.idRefs?.includes(documentId) ?? !1, byPattern = m.idPatterns?.some(p => globMatch(p, documentId)) ?? !1;
|
|
1998
|
+
if (!byRef && !byPattern) return !1;
|
|
1999
|
+
}
|
|
2000
|
+
return !0;
|
|
2007
2001
|
}
|
|
2008
2002
|
|
|
2009
|
-
function
|
|
2010
|
-
return
|
|
2003
|
+
function guardPredicateRoot(args) {
|
|
2004
|
+
return {
|
|
2005
|
+
document: {
|
|
2006
|
+
before: args.context.before,
|
|
2007
|
+
after: args.context.after
|
|
2008
|
+
},
|
|
2009
|
+
guard: args.guard,
|
|
2010
|
+
mutation: {
|
|
2011
|
+
action: args.context.action
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2011
2014
|
}
|
|
2012
2015
|
|
|
2013
|
-
function
|
|
2014
|
-
|
|
2015
|
-
return value == null ? value : isSingleDocRefKind(entryType) || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
|
|
2016
|
-
row: value,
|
|
2017
|
-
shapes: fields ?? [],
|
|
2018
|
-
mapRef: mapRef
|
|
2019
|
-
}) : entryType === "array" ? mapItems(value, row => mapRowRefValues({
|
|
2020
|
-
row: row,
|
|
2021
|
-
shapes: of ?? [],
|
|
2022
|
-
mapRef: mapRef
|
|
2023
|
-
})) : value;
|
|
2016
|
+
function lakeShapedSnapshotDocument(doc) {
|
|
2017
|
+
return mapJsonStrings(doc, (value, key) => key === "_id" || key === "_ref" ? toBareId(value) : value);
|
|
2024
2018
|
}
|
|
2025
2019
|
|
|
2026
|
-
function
|
|
2027
|
-
return
|
|
2020
|
+
function snapshotGuardDereference(args) {
|
|
2021
|
+
return ({_ref: _ref}) => {
|
|
2022
|
+
const lookupId = isGdrUri(_ref) ? _ref : gdrFromResource(args.resource, _ref), found = findSnapshotDoc(args.snapshot, lookupId);
|
|
2023
|
+
return Promise.resolve(found === void 0 ? null : lakeShapedSnapshotDocument(found));
|
|
2024
|
+
};
|
|
2028
2025
|
}
|
|
2029
2026
|
|
|
2030
|
-
function
|
|
2027
|
+
async function evaluateMutationGuard(args) {
|
|
2028
|
+
const {guard: guard, context: context, dereference: dereference} = args;
|
|
2029
|
+
if (guard.predicate === "") return !1;
|
|
2030
|
+
const root = guardPredicateRoot({
|
|
2031
|
+
guard: guard,
|
|
2032
|
+
context: context
|
|
2033
|
+
});
|
|
2034
|
+
let dereferenceFailed = !1;
|
|
2035
|
+
const guardedDereference = dereference === void 0 ? void 0 : async ref => {
|
|
2036
|
+
try {
|
|
2037
|
+
return await dereference(ref);
|
|
2038
|
+
} catch (error) {
|
|
2039
|
+
throw dereferenceFailed = !0, error;
|
|
2040
|
+
}
|
|
2041
|
+
};
|
|
2042
|
+
try {
|
|
2043
|
+
const tree = parseGuardPredicate(guard.predicate);
|
|
2044
|
+
return await (await evaluate(tree, {
|
|
2045
|
+
root: root,
|
|
2046
|
+
before: context.before,
|
|
2047
|
+
after: context.after,
|
|
2048
|
+
...guardedDereference !== void 0 ? {
|
|
2049
|
+
dataset: [],
|
|
2050
|
+
dereference: guardedDereference
|
|
2051
|
+
} : {},
|
|
2052
|
+
...context.identity !== void 0 ? {
|
|
2053
|
+
identity: context.identity
|
|
2054
|
+
} : {}
|
|
2055
|
+
})).get() === !0;
|
|
2056
|
+
} catch (error) {
|
|
2057
|
+
if (dereferenceFailed) throw error;
|
|
2058
|
+
return !1;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
async function denyingGuards(args) {
|
|
2063
|
+
const {guards: guards, doc: doc, context: context, dereference: dereference} = args, denied = [];
|
|
2064
|
+
for (const guard of guards) guardMatches({
|
|
2065
|
+
guard: guard,
|
|
2066
|
+
doc: doc,
|
|
2067
|
+
action: context.action
|
|
2068
|
+
}) && (await evaluateMutationGuard({
|
|
2069
|
+
guard: guard,
|
|
2070
|
+
context: context,
|
|
2071
|
+
...dereference !== void 0 ? {
|
|
2072
|
+
dereference: dereference
|
|
2073
|
+
} : {}
|
|
2074
|
+
}) || denied.push(guard));
|
|
2075
|
+
return denied;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
async function documentActionDenials(args) {
|
|
2079
|
+
const {mutation: mutation, resource: resource, guards: guards, identity: identity, dereference: dereference} = args, document = mutation.after ?? mutation.before;
|
|
2080
|
+
if (document === null) throw new Error("a concrete Lake mutation requires a before or after image");
|
|
2081
|
+
const enforceable = guards.filter(g => g.resourceType === resource.type && g.resourceId === resource.id);
|
|
2082
|
+
return enforceable.length === 0 ? [] : denyingGuards({
|
|
2083
|
+
guards: enforceable,
|
|
2084
|
+
doc: {
|
|
2085
|
+
id: document._id,
|
|
2086
|
+
type: document._type
|
|
2087
|
+
},
|
|
2088
|
+
context: {
|
|
2089
|
+
...mutation,
|
|
2090
|
+
...identity !== void 0 ? {
|
|
2091
|
+
identity: identity
|
|
2092
|
+
} : {}
|
|
2093
|
+
},
|
|
2094
|
+
...dereference !== void 0 ? {
|
|
2095
|
+
dereference: dereference
|
|
2096
|
+
} : {}
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
async function instanceWriteDenials(args) {
|
|
2101
|
+
const {instance: instance, guards: guards, identity: identity, dereference: dereference} = args;
|
|
2102
|
+
return documentActionDenials({
|
|
2103
|
+
mutation: {
|
|
2104
|
+
before: instance,
|
|
2105
|
+
after: instance,
|
|
2106
|
+
action: "update"
|
|
2107
|
+
},
|
|
2108
|
+
resource: instance.workflowResource,
|
|
2109
|
+
guards: guards,
|
|
2110
|
+
dereference: dereference,
|
|
2111
|
+
...identity !== void 0 ? {
|
|
2112
|
+
identity: identity
|
|
2113
|
+
} : {}
|
|
2114
|
+
});
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
async function assertInstanceWriteAllowed(args) {
|
|
2118
|
+
const denied = await instanceWriteDenials(args);
|
|
2119
|
+
if (denied.length !== 0) throw MutationGuardDeniedError.fromGuards({
|
|
2120
|
+
documentId: args.instance._id,
|
|
2121
|
+
action: "update",
|
|
2122
|
+
guards: denied
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
const ASSIGNMENT_LIST_MODEL = 9;
|
|
2127
|
+
|
|
2128
|
+
function isAssignmentListModel(modelVersion) {
|
|
2129
|
+
return modelVersion >= ASSIGNMENT_LIST_MODEL;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
function definitionAssignmentModel(instance) {
|
|
2133
|
+
if (typeof instance.definitionSnapshot != "string") return 0;
|
|
2134
|
+
const modelVersion = parseDefinitionSnapshotValue({
|
|
2135
|
+
_id: instance._id,
|
|
2136
|
+
definitionSnapshot: instance.definitionSnapshot
|
|
2137
|
+
}).modelVersion;
|
|
2138
|
+
return typeof modelVersion == "number" ? modelVersion : 0;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
function writesSingularAssignmentLists(instance) {
|
|
2142
|
+
return isAssignmentListModel(definitionAssignmentModel(instance));
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
function legacyAssigneeValue(entry) {
|
|
2146
|
+
return legacyAssignmentValue(entry.value, entry.name);
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
function legacyAssignmentValue(value, path) {
|
|
2150
|
+
if (!Array.isArray(value)) return value;
|
|
2151
|
+
if (value.length === 0) return null;
|
|
2152
|
+
if (value.length === 1) return value[0];
|
|
2153
|
+
throw new ContractViolationError(`legacy assignee field "${path}" cannot persist ${value.length} members; redeploy the definition at the assignment-list reader model before writing a role pool`);
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
function mapShapeValues(args) {
|
|
2157
|
+
const {value: value, shapes: shapes, mapAssignee: mapAssignee, parentPath: parentPath} = args;
|
|
2158
|
+
if (typeof value != "object" || value === null || Array.isArray(value)) return value;
|
|
2159
|
+
const source = value, next = {
|
|
2160
|
+
...source
|
|
2161
|
+
};
|
|
2162
|
+
for (const shape of shapes) {
|
|
2163
|
+
if (!Object.hasOwn(source, shape.name)) continue;
|
|
2164
|
+
const path = `${parentPath}.${shape.name}`, member = source[shape.name], mapped = mappedShapeValue({
|
|
2165
|
+
shape: shape,
|
|
2166
|
+
member: member,
|
|
2167
|
+
mapAssignee: mapAssignee,
|
|
2168
|
+
path: path
|
|
2169
|
+
});
|
|
2170
|
+
mapped.found && defineOwnValue(next, {
|
|
2171
|
+
name: shape.name,
|
|
2172
|
+
value: mapped.value
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
return next;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
function mappedShapeValue(args) {
|
|
2179
|
+
const {shape: shape, member: member, mapAssignee: mapAssignee, path: path} = args;
|
|
2180
|
+
return shape.type === "assignee" ? {
|
|
2181
|
+
found: !0,
|
|
2182
|
+
value: mapAssignee(member, path)
|
|
2183
|
+
} : shape.type === "object" ? {
|
|
2184
|
+
found: !0,
|
|
2185
|
+
value: mapShapeValues({
|
|
2186
|
+
value: member,
|
|
2187
|
+
shapes: shape.fields ?? [],
|
|
2188
|
+
mapAssignee: mapAssignee,
|
|
2189
|
+
parentPath: path
|
|
2190
|
+
})
|
|
2191
|
+
} : shape.type !== "array" || !Array.isArray(member) ? {
|
|
2192
|
+
found: !1
|
|
2193
|
+
} : {
|
|
2194
|
+
found: !0,
|
|
2195
|
+
value: member.map((row, index) => mapShapeValues({
|
|
2196
|
+
value: row,
|
|
2197
|
+
shapes: shape.of ?? [],
|
|
2198
|
+
mapAssignee: mapAssignee,
|
|
2199
|
+
parentPath: `${path}[${index}]`
|
|
2200
|
+
}))
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
function defineOwnValue(target, property) {
|
|
2205
|
+
Object.defineProperty(target, property.name, {
|
|
2206
|
+
configurable: !0,
|
|
2207
|
+
enumerable: !0,
|
|
2208
|
+
value: property.value,
|
|
2209
|
+
writable: !0
|
|
2210
|
+
});
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
function mapNestedAssignmentValues(entry, mapAssignee) {
|
|
2214
|
+
return entry._type === "object" ? mapShapeValues({
|
|
2215
|
+
value: entry.value,
|
|
2216
|
+
shapes: entry.fields,
|
|
2217
|
+
mapAssignee: mapAssignee,
|
|
2218
|
+
parentPath: entry.name
|
|
2219
|
+
}) : entry.value.map((row, index) => mapShapeValues({
|
|
2220
|
+
value: row,
|
|
2221
|
+
shapes: entry.of,
|
|
2222
|
+
mapAssignee: mapAssignee,
|
|
2223
|
+
parentPath: `${entry.name}[${index}]`
|
|
2224
|
+
}));
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
function normalizeNestedAssignmentValues(entry) {
|
|
2228
|
+
return entry._type !== "object" && entry._type !== "array" ? entry : {
|
|
2229
|
+
...entry,
|
|
2230
|
+
value: mapNestedAssignmentValues(entry, normalizeAssignmentMembers)
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
function assignmentFieldsForWrite(fields, listModel) {
|
|
2235
|
+
return listModel ? fields : fields.map(entry => entry._type === "assignee" ? {
|
|
2236
|
+
...entry,
|
|
2237
|
+
value: legacyAssigneeValue(entry)
|
|
2238
|
+
} : entry._type === "object" || entry._type === "array" ? {
|
|
2239
|
+
...entry,
|
|
2240
|
+
value: mapNestedAssignmentValues(entry, legacyAssignmentValue)
|
|
2241
|
+
} : entry);
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
function activityForWrite(activity, listModel) {
|
|
2245
|
+
return {
|
|
2246
|
+
...activity,
|
|
2247
|
+
...activity.fields === void 0 ? {} : {
|
|
2248
|
+
fields: assignmentFieldsForWrite(activity.fields, listModel)
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
function assignmentStagesForWrite(stages, listModel) {
|
|
2254
|
+
return stages.map(stage => ({
|
|
2255
|
+
...stage,
|
|
2256
|
+
fields: assignmentFieldsForWrite(stage.fields ?? [], listModel),
|
|
2257
|
+
activities: stage.activities.map(activity => activityForWrite(activity, listModel))
|
|
2258
|
+
}));
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
function getPath(value, path) {
|
|
2262
|
+
let current = value;
|
|
2263
|
+
for (const part of path.split(".")) {
|
|
2264
|
+
if (current == null || typeof current != "object") return;
|
|
2265
|
+
current = current[part];
|
|
2266
|
+
}
|
|
2267
|
+
return current;
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
function isReferenceObject(value) {
|
|
2271
|
+
return typeof value._ref == "string";
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
function walkDocPath(value, path) {
|
|
2275
|
+
let current = value;
|
|
2276
|
+
for (const part of path.split(".")) {
|
|
2277
|
+
if (current == null || typeof current != "object") return;
|
|
2278
|
+
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.`);
|
|
2279
|
+
current = current[part];
|
|
2280
|
+
}
|
|
2281
|
+
return current;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
function resolveFieldRead(args) {
|
|
2285
|
+
const {kind: kind, value: value, path: path, snapshot: snapshot, targetKind: targetKind} = args;
|
|
2286
|
+
if (isSingleDocRefKind(kind)) {
|
|
2287
|
+
if (!isGdr(value)) return null;
|
|
2288
|
+
if (path === void 0 && targetKind !== void 0 && isSingleDocRefKind(targetKind)) return value;
|
|
2289
|
+
const base = derefBase(value, snapshot);
|
|
2290
|
+
return path === void 0 ? base : walkDocPath(base, path);
|
|
2291
|
+
}
|
|
2292
|
+
return path !== void 0 ? getPath(value, path) : value;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
function derefBase(ref, snapshot) {
|
|
2296
|
+
return (snapshot !== void 0 ? findSnapshotDoc(snapshot, ref.id) : void 0) ?? {
|
|
2297
|
+
_id: ref.id,
|
|
2298
|
+
_type: ref.type
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
function buildParams(args) {
|
|
2303
|
+
const {instance: instance, now: now, snapshot: snapshot, extra: extra} = args, currentActivities2 = findOpenStageEntry(instance)?.activities ?? [];
|
|
2304
|
+
return {
|
|
2305
|
+
self: selfGdr(instance),
|
|
2306
|
+
fields: renderedFields(instance.fields ?? [], snapshot),
|
|
2307
|
+
parent: parentRef(instance)?.id ?? null,
|
|
2308
|
+
ancestors: instance.ancestors.map(a => a.id),
|
|
2309
|
+
stage: instance.currentStage,
|
|
2310
|
+
now: now,
|
|
2311
|
+
context: contextMap(instance),
|
|
2312
|
+
effects: effectOutputsMap(instance),
|
|
2313
|
+
effectStatus: effectStatusMap(instance),
|
|
2314
|
+
activities: currentActivities2,
|
|
2315
|
+
subworkflows: subworkflowVarRows(instance, snapshot),
|
|
2316
|
+
...activityGateParams(currentActivities2),
|
|
2317
|
+
...extra
|
|
2318
|
+
};
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
function subworkflowVarRows(instance, snapshot) {
|
|
2322
|
+
const openKey = findOpenStageEntry(instance)?._key;
|
|
2323
|
+
return (instance.subworkflows ?? []).map(row => ({
|
|
2324
|
+
_id: toBareId(row.ref.id),
|
|
2325
|
+
rowKey: row.rowKey,
|
|
2326
|
+
activity: row.activity,
|
|
2327
|
+
action: row.action,
|
|
2328
|
+
definition: row.definition,
|
|
2329
|
+
current: row.stageEntry === openKey,
|
|
2330
|
+
...childState(row, snapshot),
|
|
2331
|
+
spawnedAt: row.spawnedAt
|
|
2332
|
+
}));
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
function childState(row, snapshot) {
|
|
2336
|
+
if (row.resolved !== void 0) return {
|
|
2337
|
+
stage: row.resolved.stage ?? null,
|
|
2338
|
+
status: row.resolved.aborted === !0 ? "aborted" : "done"
|
|
2339
|
+
};
|
|
2340
|
+
const doc = snapshot === void 0 ? void 0 : findSnapshotDoc(snapshot, row.ref.id);
|
|
2341
|
+
return doc === void 0 ? {
|
|
2342
|
+
stage: null,
|
|
2343
|
+
status: "active"
|
|
2344
|
+
} : {
|
|
2345
|
+
stage: doc.currentStage ?? null,
|
|
2346
|
+
status: resolvedChildStatus(doc) ?? "active"
|
|
2347
|
+
};
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
function activityGateParams(activities) {
|
|
2351
|
+
return {
|
|
2352
|
+
allActivitiesDone: activities.every(activity => activity.status === "done" || activity.status === "skipped"),
|
|
2353
|
+
anyActivityFailed: activities.some(activity => activity.status === "failed")
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
function renderedFields(entries, snapshot) {
|
|
2358
|
+
const out = {};
|
|
2359
|
+
for (const entry of entries) out[entry.name] = renderedValue(entry, snapshot);
|
|
2360
|
+
return out;
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
function renderedValue(entry, snapshot) {
|
|
2364
|
+
return resolveFieldRead({
|
|
2365
|
+
kind: entry._type,
|
|
2366
|
+
value: entry.value,
|
|
2367
|
+
path: void 0,
|
|
2368
|
+
snapshot: snapshot
|
|
2369
|
+
});
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
function scopedFieldOverlay({instance: instance, snapshot: snapshot, activityName: activityName}) {
|
|
2373
|
+
const stageEntry = findOpenStageEntry(instance);
|
|
2374
|
+
if (stageEntry === void 0) return {};
|
|
2375
|
+
const stageFields = renderedFields(stageEntry.fields ?? [], snapshot), activity = activityName ? stageEntry.activities.find(t => t.name === activityName) : void 0;
|
|
2376
|
+
return {
|
|
2377
|
+
...stageFields,
|
|
2378
|
+
...renderedFields(activity?.fields ?? [], snapshot)
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
function assignedFor({instance: instance, activityName: activityName, actor: actor, roleAliases: roleAliases}) {
|
|
2383
|
+
if (actor === void 0) return !1;
|
|
2384
|
+
const activity = findCurrentActivityEntry(instance, activityName);
|
|
2385
|
+
return actorMatchesAssignment({
|
|
2386
|
+
actor: actor,
|
|
2387
|
+
members: assignmentMembers(activity?.fields ?? []),
|
|
2388
|
+
roleAliases: roleAliases
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
function effectStatusMap(instance) {
|
|
2393
|
+
const entry = findOpenStageEntry(instance);
|
|
2394
|
+
if (entry === void 0) return {};
|
|
2395
|
+
const out = {};
|
|
2396
|
+
for (const run of instance.effectHistory) run.stageEntryKey === entry._key && (out[run.name] = run.status);
|
|
2397
|
+
return out;
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
function contextMap(instance) {
|
|
2401
|
+
const out = {};
|
|
2402
|
+
for (const entry of instance.context) out[entry.name] = entry._type === "context.json" ? parseJsonContextEntry(entry) : entry.value;
|
|
2403
|
+
return out;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
function effectOutputsMap(instance) {
|
|
2407
|
+
const out = {};
|
|
2408
|
+
for (const run of instance.effectHistory) run.outputs !== void 0 && (out[run.name] = run.outputs);
|
|
2409
|
+
return out;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
function parseJsonContextEntry(entry) {
|
|
2413
|
+
try {
|
|
2414
|
+
return JSON.parse(entry.value);
|
|
2415
|
+
} catch (err) {
|
|
2416
|
+
rethrowWithContext(err, `context entry "${entry.name}" holds unparseable JSON`);
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
function paramsForLake(params) {
|
|
2421
|
+
return {
|
|
2422
|
+
...params,
|
|
2423
|
+
self: typeof params.self == "string" ? toBareId(params.self) : params.self,
|
|
2424
|
+
parent: typeof params.parent == "string" ? toBareId(params.parent) : params.parent,
|
|
2425
|
+
ancestors: Array.isArray(params.ancestors) ? params.ancestors.map(a => typeof a == "string" ? toBareId(a) : a) : params.ancestors,
|
|
2426
|
+
fields: stripFieldsForLake(params.fields)
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
function stripFieldsForLake(value) {
|
|
2431
|
+
return mapJsonStrings(value, s => toBareId(s));
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
function resolveStaticValueExpr(src, ctx) {
|
|
2435
|
+
switch (src.type) {
|
|
2436
|
+
case "literal":
|
|
2437
|
+
return src.value;
|
|
2438
|
+
|
|
2439
|
+
case "param":
|
|
2440
|
+
return ctx.params?.[src.param];
|
|
2441
|
+
|
|
2442
|
+
case "actor":
|
|
2443
|
+
return ctx.actor;
|
|
2444
|
+
|
|
2445
|
+
case "now":
|
|
2446
|
+
return ctx.now;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
function randomKey(length = 12) {
|
|
2451
|
+
const bytes = new Uint8Array(length);
|
|
2452
|
+
return globalThis.crypto.getRandomValues(bytes), [ ...bytes ].map(b => b.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
function instanceDocId(tag) {
|
|
2456
|
+
return `${tag}.wf-instance.${randomKey()}`;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
function mapFieldRefValues(args) {
|
|
2460
|
+
const {entryType: entryType, value: value, fields: fields, of: of, mapRef: mapRef} = args;
|
|
2461
|
+
return value == null ? value : isSingleDocRefKind(entryType) || entryType === "release.ref" ? mapRef(value) : entryType === "doc.refs" ? mapItems(value, mapRef) : entryType === "object" ? mapRowRefValues({
|
|
2462
|
+
row: value,
|
|
2463
|
+
shapes: fields ?? [],
|
|
2464
|
+
mapRef: mapRef
|
|
2465
|
+
}) : entryType === "array" ? mapItems(value, row => mapRowRefValues({
|
|
2466
|
+
row: row,
|
|
2467
|
+
shapes: of ?? [],
|
|
2468
|
+
mapRef: mapRef
|
|
2469
|
+
})) : value;
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
function mapItems(value, mapItem) {
|
|
2473
|
+
return Array.isArray(value) ? value.map(mapItem) : value;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
function mapRowRefValues(args) {
|
|
2031
2477
|
const {row: row, shapes: shapes, mapRef: mapRef} = args;
|
|
2032
2478
|
if (typeof row != "object" || row === null || Array.isArray(row)) return row;
|
|
2033
2479
|
const record = row, out = {
|
|
@@ -2254,10 +2700,12 @@ class WorkflowStateDivergedError extends WorkflowError {
|
|
|
2254
2700
|
class PartialGuardDeployError extends WorkflowError {
|
|
2255
2701
|
stageName;
|
|
2256
2702
|
deployed;
|
|
2703
|
+
rollbackError;
|
|
2257
2704
|
constructor(args) {
|
|
2258
2705
|
super("partial-guard-deploy", `Partial guard deploy on stage "${args.stageName}": ${args.deployed} guard(s) deployed before a later one failed.`, {
|
|
2259
2706
|
cause: args.cause
|
|
2260
|
-
}), this.name = "PartialGuardDeployError", this.stageName = args.stageName, this.deployed = args.deployed
|
|
2707
|
+
}), this.name = "PartialGuardDeployError", this.stageName = args.stageName, this.deployed = args.deployed,
|
|
2708
|
+
args.rollbackError !== void 0 && (this.rollbackError = args.rollbackError);
|
|
2261
2709
|
}
|
|
2262
2710
|
}
|
|
2263
2711
|
|
|
@@ -2298,7 +2746,23 @@ function staleClaimDetail(reason) {
|
|
|
2298
2746
|
const CONCURRENT_COMMIT_MAX_ATTEMPTS = 3;
|
|
2299
2747
|
|
|
2300
2748
|
function lostRaceMessage(args) {
|
|
2301
|
-
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
|
|
2749
|
+
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."}`;
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
function isRetryableInstanceCommitConflict(error) {
|
|
2753
|
+
return !isCreateIdCollision(error) && isRevisionConflict(error);
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
class InstanceCommitRevisionConflict extends Error {
|
|
2757
|
+
constructor(cause) {
|
|
2758
|
+
super("Instance commit lost its revision fence", {
|
|
2759
|
+
cause: cause
|
|
2760
|
+
}), this.name = "InstanceCommitRevisionConflict";
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
function isInstanceCommitRevisionConflict(error) {
|
|
2765
|
+
return error instanceof InstanceCommitRevisionConflict;
|
|
2302
2766
|
}
|
|
2303
2767
|
|
|
2304
2768
|
class ConcurrentFireActionError extends WorkflowError {
|
|
@@ -2316,6 +2780,19 @@ class ConcurrentFireActionError extends WorkflowError {
|
|
|
2316
2780
|
}
|
|
2317
2781
|
}
|
|
2318
2782
|
|
|
2783
|
+
class ConcurrentCascadeError extends WorkflowError {
|
|
2784
|
+
instanceId;
|
|
2785
|
+
attempts;
|
|
2786
|
+
constructor(args) {
|
|
2787
|
+
super("concurrent-cascade", lostRaceMessage({
|
|
2788
|
+
what: "Automatic cascade",
|
|
2789
|
+
instanceId: args.instanceId,
|
|
2790
|
+
attempts: args.attempts,
|
|
2791
|
+
recovery: "An earlier verb commit may already have landed. Re-read the instance and invoke tick after contention subsides."
|
|
2792
|
+
})), this.name = "ConcurrentCascadeError", this.instanceId = args.instanceId, this.attempts = args.attempts;
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2319
2796
|
function isRevisionConflict(error) {
|
|
2320
2797
|
if (typeof error != "object" || error === null) return !1;
|
|
2321
2798
|
const {statusCode: statusCode, message: message} = error;
|
|
@@ -2598,11 +3075,15 @@ function applyFieldSet(op, ctx) {
|
|
|
2598
3075
|
...entryShape(entry),
|
|
2599
3076
|
memberRoles: ctx.memberRoles,
|
|
2600
3077
|
roleAliases: ctx.roleAliases,
|
|
2601
|
-
...entry._type === "assignees" || entry._type === "object" || entry._type === "array" ? {
|
|
3078
|
+
...entry._type === "assignee" || entry._type === "assignees" || entry._type === "object" || entry._type === "array" ? {
|
|
2602
3079
|
previousValue: entry.value
|
|
2603
3080
|
} : {}
|
|
2604
3081
|
});
|
|
2605
|
-
return
|
|
3082
|
+
return assertLegacySingularValue({
|
|
3083
|
+
entry: entry,
|
|
3084
|
+
value: validated,
|
|
3085
|
+
ctx: ctx
|
|
3086
|
+
}), assertRuntimeRefsWithinSurface({
|
|
2606
3087
|
entryType: entry._type,
|
|
2607
3088
|
entryName: entry.name,
|
|
2608
3089
|
value: validated,
|
|
@@ -2619,12 +3100,12 @@ function applyFieldSet(op, ctx) {
|
|
|
2619
3100
|
}
|
|
2620
3101
|
|
|
2621
3102
|
function applyFieldSetIfMissing(op, ctx) {
|
|
2622
|
-
const entry = locateEntry(ctx, op.target);
|
|
2623
|
-
return isAlwaysArrayFieldKind(entry._type) && rejectFieldOpTarget({
|
|
3103
|
+
const entry = locateEntry(ctx, op.target), legacySingular = isLegacySingularAssignment(entry, ctx);
|
|
3104
|
+
return isAlwaysArrayFieldKind(entry._type) && !legacySingular && rejectFieldOpTarget({
|
|
2624
3105
|
entry: entry,
|
|
2625
3106
|
op: op,
|
|
2626
3107
|
issue: "is always array-valued — setIfMissing applies to nullable entries only; an empty array entry already holds []"
|
|
2627
|
-
}), entry.value !== null && entry.value !== void 0 ? {
|
|
3108
|
+
}), entry.value !== null && entry.value !== void 0 && !(legacySingular && Array.isArray(entry.value) && entry.value.length === 0) ? {
|
|
2628
3109
|
opType: op.type,
|
|
2629
3110
|
target: op.target
|
|
2630
3111
|
} : {
|
|
@@ -2744,7 +3225,14 @@ function applyFieldUnset(op, ctx) {
|
|
|
2744
3225
|
}
|
|
2745
3226
|
|
|
2746
3227
|
function applyFieldAppend(op, ctx) {
|
|
2747
|
-
const entry = locateEntry(ctx, op.target)
|
|
3228
|
+
const entry = locateEntry(ctx, op.target);
|
|
3229
|
+
if (isLegacySingularAssignment(entry, ctx)) throw new FieldValueShapeError({
|
|
3230
|
+
entryType: entry._type,
|
|
3231
|
+
entryName: entry.name,
|
|
3232
|
+
mode: "item",
|
|
3233
|
+
issues: [ "legacy singular assignee entries do not support append; redeploy at model 9" ]
|
|
3234
|
+
});
|
|
3235
|
+
const slot = appendItemSlot(entry), item = resolveOpValue({
|
|
2748
3236
|
src: op.value,
|
|
2749
3237
|
ctx: ctx,
|
|
2750
3238
|
...slot !== void 0 ? {
|
|
@@ -2756,7 +3244,7 @@ function applyFieldAppend(op, ctx) {
|
|
|
2756
3244
|
item: item,
|
|
2757
3245
|
types: entry._type === "doc.refs" ? entry.types : void 0,
|
|
2758
3246
|
of: entry._type === "array" ? entry.of : void 0,
|
|
2759
|
-
roles: entry
|
|
3247
|
+
roles: isAssignmentFieldEntry(entry) ? entry.roles : void 0,
|
|
2760
3248
|
memberRoles: ctx.memberRoles,
|
|
2761
3249
|
roleAliases: ctx.roleAliases
|
|
2762
3250
|
});
|
|
@@ -2768,8 +3256,16 @@ function applyFieldAppend(op, ctx) {
|
|
|
2768
3256
|
ctx: ctx,
|
|
2769
3257
|
src: op.value
|
|
2770
3258
|
});
|
|
2771
|
-
const
|
|
2772
|
-
|
|
3259
|
+
const next = [ ...Array.isArray(entry.value) ? entry.value : [], withRowKey(validated) ], value = isAssignmentFieldEntry(entry) ? validateFieldValue({
|
|
3260
|
+
entryType: entry._type,
|
|
3261
|
+
entryName: entry.name,
|
|
3262
|
+
value: next,
|
|
3263
|
+
...assignmentEntryShape(entry),
|
|
3264
|
+
previousValue: entry.value,
|
|
3265
|
+
memberRoles: ctx.memberRoles,
|
|
3266
|
+
roleAliases: ctx.roleAliases
|
|
3267
|
+
}) : next;
|
|
3268
|
+
return setEntryValue(entry, value), {
|
|
2773
3269
|
opType: op.type,
|
|
2774
3270
|
target: op.target,
|
|
2775
3271
|
resolved: {
|
|
@@ -2846,7 +3342,14 @@ async function applyFieldUpdateWhere(op, ctx) {
|
|
|
2846
3342
|
}
|
|
2847
3343
|
|
|
2848
3344
|
async function applyFieldRemoveWhere(op, ctx) {
|
|
2849
|
-
const entry = locateEntry(ctx, op.target)
|
|
3345
|
+
const entry = locateEntry(ctx, op.target);
|
|
3346
|
+
if (isLegacySingularAssignment(entry, ctx)) throw new FieldValueShapeError({
|
|
3347
|
+
entryType: entry._type,
|
|
3348
|
+
entryName: entry.name,
|
|
3349
|
+
mode: "value",
|
|
3350
|
+
issues: [ "legacy singular assignee entries do not support removeWhere; redeploy at model 9" ]
|
|
3351
|
+
});
|
|
3352
|
+
const rows = requireArrayValue(entry, op), matches = await rowMatches({
|
|
2850
3353
|
where: op.where,
|
|
2851
3354
|
rows: rows,
|
|
2852
3355
|
ctx: ctx
|
|
@@ -2857,6 +3360,20 @@ async function applyFieldRemoveWhere(op, ctx) {
|
|
|
2857
3360
|
};
|
|
2858
3361
|
}
|
|
2859
3362
|
|
|
3363
|
+
function assertLegacySingularValue(args) {
|
|
3364
|
+
const {entry: entry, value: value, ctx: ctx} = args;
|
|
3365
|
+
if (!(!isLegacySingularAssignment(entry, ctx) || !Array.isArray(value) || value.length <= 1)) throw new FieldValueShapeError({
|
|
3366
|
+
entryType: entry._type,
|
|
3367
|
+
entryName: entry.name,
|
|
3368
|
+
mode: "value",
|
|
3369
|
+
issues: [ "legacy singular assignee entries accept at most one total member; redeploy at model 9" ]
|
|
3370
|
+
});
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3373
|
+
function isLegacySingularAssignment(entry, ctx) {
|
|
3374
|
+
return entry._type === "assignee" && !isAssignmentListModel(ctx.mutation.definitionModelVersion);
|
|
3375
|
+
}
|
|
3376
|
+
|
|
2860
3377
|
function requireMergeableRows(entry, op) {
|
|
2861
3378
|
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`);
|
|
2862
3379
|
}
|
|
@@ -3032,6 +3549,14 @@ function whereParams(ctx) {
|
|
|
3032
3549
|
|
|
3033
3550
|
function validateDefinition(definition) {
|
|
3034
3551
|
const v2 = createDefinitionValidator();
|
|
3552
|
+
validateConditionSites(v2, definition), validateStart(v2, definition);
|
|
3553
|
+
for (const entry of definition.fields ?? []) v2.checkEntry(entry, `workflow.fields "${entry.name}"`);
|
|
3554
|
+
for (const stage of definition.stages) validateStage(v2, stage);
|
|
3555
|
+
for (const issue of checkWorkflowInvariants(definition)) v2.errors.push(` · ${formatIssuePath(issue.path)}: ${issue.message}`);
|
|
3556
|
+
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`));
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
function validateConditionSites(v2, definition) {
|
|
3035
3560
|
for (const site of conditionSitesOf(definition)) {
|
|
3036
3561
|
const {address: address} = site;
|
|
3037
3562
|
address.kind !== "editable-field" && v2.checkCondition(site.condition, conditionSiteLabel({
|
|
@@ -3039,12 +3564,11 @@ function validateDefinition(definition) {
|
|
|
3039
3564
|
address: address
|
|
3040
3565
|
}));
|
|
3041
3566
|
}
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
function validateStart(v2, definition) {
|
|
3042
3570
|
definition.start?.filter !== void 0 && v2.report("start.filter", startFilterSyntaxIssues(definition.start.filter));
|
|
3043
3571
|
for (const [index, requirement] of (definition.start?.requirements ?? []).entries()) requirement.type === "groq" && v2.report(`start.requirements[${index}].query`, startRequirementSyntaxIssues(requirement.query));
|
|
3044
|
-
for (const entry of definition.fields ?? []) v2.checkEntry(entry, `workflow.fields "${entry.name}"`);
|
|
3045
|
-
for (const stage of definition.stages) validateStage(v2, stage);
|
|
3046
|
-
for (const issue of checkWorkflowInvariants(definition)) v2.errors.push(` · ${formatIssuePath(issue.path)}: ${issue.message}`);
|
|
3047
|
-
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`));
|
|
3048
3572
|
}
|
|
3049
3573
|
|
|
3050
3574
|
function createDefinitionValidator() {
|
|
@@ -3073,35 +3597,14 @@ function createDefinitionValidator() {
|
|
|
3073
3597
|
};
|
|
3074
3598
|
}
|
|
3075
3599
|
|
|
3076
|
-
function conditionSiteLabel({stage: stage, address: address}) {
|
|
3077
|
-
const at = `stage "${stage}"`;
|
|
3078
|
-
|
|
3079
|
-
case "predicate":
|
|
3080
|
-
return `predicate "${address.predicate}"`;
|
|
3081
|
-
|
|
3082
|
-
case "transition":
|
|
3083
|
-
return `${at} transition "${address.transition}" when`;
|
|
3084
|
-
|
|
3085
|
-
case "activity-filter":
|
|
3086
|
-
return `${at} activity "${address.activity}".filter`;
|
|
3087
|
-
|
|
3088
|
-
case "requirement":
|
|
3089
|
-
return `${at} activity "${address.activity}".requirements "${address.requirement}"`;
|
|
3090
|
-
|
|
3091
|
-
case "action":
|
|
3092
|
-
return `${at} activity "${address.activity}" action "${address.action}".filter`;
|
|
3093
|
-
|
|
3094
|
-
case "action-when":
|
|
3095
|
-
return `${at} activity "${address.activity}" action "${address.action}".when`;
|
|
3096
|
-
|
|
3097
|
-
case "editable-override":
|
|
3098
|
-
return `${at}.editable "${address.name}"`;
|
|
3099
|
-
}
|
|
3600
|
+
function conditionSiteLabel({stage: stage, address: address}) {
|
|
3601
|
+
const at = `stage "${stage}"`;
|
|
3602
|
+
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}"`;
|
|
3100
3603
|
}
|
|
3101
3604
|
|
|
3102
3605
|
function validateStage(v2, stage) {
|
|
3103
3606
|
for (const entry of stage.fields ?? []) v2.checkEntry(entry, `stage "${stage.name}".fields "${entry.name}"`);
|
|
3104
|
-
for (const guard of stage.guards ?? [])
|
|
3607
|
+
for (const guard of stage.guards ?? []) validateGuard({
|
|
3105
3608
|
v: v2,
|
|
3106
3609
|
stageName: stage.name,
|
|
3107
3610
|
guard: guard
|
|
@@ -3113,12 +3616,28 @@ function validateStage(v2, stage) {
|
|
|
3113
3616
|
});
|
|
3114
3617
|
}
|
|
3115
3618
|
|
|
3116
|
-
function
|
|
3619
|
+
function validateGuard({v: v2, stageName: stageName, guard: guard}) {
|
|
3117
3620
|
const where = `stage "${stageName}" guard "${guard.name}"`;
|
|
3118
|
-
|
|
3621
|
+
if (validateGuardMatch({
|
|
3622
|
+
v: v2,
|
|
3623
|
+
where: where,
|
|
3624
|
+
guard: guard
|
|
3625
|
+
}), guard.predicate !== void 0 && guard.predicate !== "") {
|
|
3626
|
+
const issue = guardPredicateSyntaxIssue(guard.predicate);
|
|
3627
|
+
issue !== void 0 && v2.report(`${where} predicate`, [ issue ]);
|
|
3628
|
+
}
|
|
3119
3629
|
for (const [key, expr] of Object.entries(guard.metadata ?? {})) v2.checkGuardRead(expr, `${where} metadata "${key}"`);
|
|
3120
3630
|
}
|
|
3121
3631
|
|
|
3632
|
+
function validateGuardMatch({v: v2, where: where, guard: guard}) {
|
|
3633
|
+
guard.match.actions.length === 0 && v2.report(`${where} match.actions`, [ GUARD_ACTIONS_REQUIRED_MESSAGE ]);
|
|
3634
|
+
for (const pattern of guard.match.idPatterns ?? []) {
|
|
3635
|
+
const issue = guardIdPatternIssue(pattern, guard.match.actions);
|
|
3636
|
+
issue !== void 0 && v2.report(`${where} match.idPatterns`, [ issue ]);
|
|
3637
|
+
}
|
|
3638
|
+
for (const expr of guard.match.idRefs ?? []) v2.checkGuardRead(expr, `${where} match.idRefs`);
|
|
3639
|
+
}
|
|
3640
|
+
|
|
3122
3641
|
function validateActivity({v: v2, stageName: stageName, activity: activity}) {
|
|
3123
3642
|
const where = `stage "${stageName}" activity "${activity.name}"`;
|
|
3124
3643
|
for (const entry of activity.fields ?? []) v2.checkEntry(entry, `${where}.fields "${entry.name}"`);
|
|
@@ -3259,175 +3778,7 @@ function hasPassed(instant, now) {
|
|
|
3259
3778
|
return Date.parse(instant) <= Date.parse(now);
|
|
3260
3779
|
}
|
|
3261
3780
|
|
|
3262
|
-
const
|
|
3263
|
-
|
|
3264
|
-
class MutationGuardDeniedError extends WorkflowError {
|
|
3265
|
-
denied;
|
|
3266
|
-
documentId;
|
|
3267
|
-
action;
|
|
3268
|
-
constructor(args) {
|
|
3269
|
-
const ids = args.denied.map(d => d.guardId).join(", ");
|
|
3270
|
-
super("mutation-guard-denied", `Mutation on "${args.documentId}" (${args.action}) denied by guard(s) [${ids}]`),
|
|
3271
|
-
this.name = "MutationGuardDeniedError", this.denied = args.denied, this.documentId = args.documentId,
|
|
3272
|
-
this.action = args.action;
|
|
3273
|
-
}
|
|
3274
|
-
static fromGuards(args) {
|
|
3275
|
-
return new MutationGuardDeniedError({
|
|
3276
|
-
documentId: args.documentId,
|
|
3277
|
-
action: args.action,
|
|
3278
|
-
denied: deniedGuardRefs(args.guards)
|
|
3279
|
-
});
|
|
3280
|
-
}
|
|
3281
|
-
}
|
|
3282
|
-
|
|
3283
|
-
function deniedGuardRefs(guards) {
|
|
3284
|
-
return guards.map(g => ({
|
|
3285
|
-
guardId: g._id,
|
|
3286
|
-
...g.name !== void 0 ? {
|
|
3287
|
-
name: g.name
|
|
3288
|
-
} : {}
|
|
3289
|
-
}));
|
|
3290
|
-
}
|
|
3291
|
-
|
|
3292
|
-
function deniedGuardLabels(denied) {
|
|
3293
|
-
return denied.map(d => d.name ?? d.guardId);
|
|
3294
|
-
}
|
|
3295
|
-
|
|
3296
|
-
function lakeGuardId(args) {
|
|
3297
|
-
return `${GUARD_DOC_TYPE}.${args.instanceDocId}.${args.guardName}`;
|
|
3298
|
-
}
|
|
3299
|
-
|
|
3300
|
-
function compileGuard(args) {
|
|
3301
|
-
return {
|
|
3302
|
-
_id: args.id,
|
|
3303
|
-
_type: GUARD_DOC_TYPE,
|
|
3304
|
-
resourceType: args.resourceType,
|
|
3305
|
-
resourceId: args.resourceId,
|
|
3306
|
-
owner: args.owner,
|
|
3307
|
-
sourceInstanceId: args.sourceInstanceId,
|
|
3308
|
-
sourceDefinition: args.sourceDefinition,
|
|
3309
|
-
sourceStage: args.sourceStage,
|
|
3310
|
-
...args.name !== void 0 ? {
|
|
3311
|
-
name: args.name
|
|
3312
|
-
} : {},
|
|
3313
|
-
...args.description !== void 0 ? {
|
|
3314
|
-
description: args.description
|
|
3315
|
-
} : {},
|
|
3316
|
-
match: args.match,
|
|
3317
|
-
predicate: args.predicate,
|
|
3318
|
-
metadata: args.metadata
|
|
3319
|
-
};
|
|
3320
|
-
}
|
|
3321
|
-
|
|
3322
|
-
function toGroqJsPredicate(predicate) {
|
|
3323
|
-
return predicate.replace(new RegExp("(?<!\\$)\\bguard\\.", "g"), "$guard.").replace(new RegExp("(?<!\\$)\\bmutation\\.", "g"), "$mutation.");
|
|
3324
|
-
}
|
|
3325
|
-
|
|
3326
|
-
function globMatch(pattern, value) {
|
|
3327
|
-
if (!pattern.includes("*")) return pattern === value;
|
|
3328
|
-
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
3329
|
-
return new RegExp(`^${escaped}$`).test(value);
|
|
3330
|
-
}
|
|
3331
|
-
|
|
3332
|
-
function guardMatches({guard: guard, doc: doc, action: action}) {
|
|
3333
|
-
const m = guard.match;
|
|
3334
|
-
if (!m.actions.includes(action) || m.types && m.types.length > 0 && !(doc.type !== void 0 && m.types.includes(doc.type))) return !1;
|
|
3335
|
-
if (m.idRefs && m.idRefs.length > 0 || m.idPatterns && m.idPatterns.length > 0) {
|
|
3336
|
-
const byRef = m.idRefs?.includes(doc.id) ?? !1, byPattern = m.idPatterns?.some(p => globMatch(p, doc.id)) ?? !1;
|
|
3337
|
-
if (!byRef && !byPattern) return !1;
|
|
3338
|
-
}
|
|
3339
|
-
return !0;
|
|
3340
|
-
}
|
|
3341
|
-
|
|
3342
|
-
function guardPredicateParams(args) {
|
|
3343
|
-
return {
|
|
3344
|
-
guard: args.guard,
|
|
3345
|
-
mutation: {
|
|
3346
|
-
action: args.action
|
|
3347
|
-
}
|
|
3348
|
-
};
|
|
3349
|
-
}
|
|
3350
|
-
|
|
3351
|
-
async function evaluateMutationGuard(args) {
|
|
3352
|
-
const {guard: guard, context: context} = args;
|
|
3353
|
-
if (guard.predicate === "") return !1;
|
|
3354
|
-
const params = guardPredicateParams({
|
|
3355
|
-
guard: guard,
|
|
3356
|
-
action: context.action
|
|
3357
|
-
});
|
|
3358
|
-
try {
|
|
3359
|
-
const tree = parse(toGroqJsPredicate(guard.predicate), {
|
|
3360
|
-
mode: "delta",
|
|
3361
|
-
params: params
|
|
3362
|
-
});
|
|
3363
|
-
return await (await evaluate(tree, {
|
|
3364
|
-
before: context.before,
|
|
3365
|
-
after: context.after,
|
|
3366
|
-
params: params,
|
|
3367
|
-
...context.identity !== void 0 ? {
|
|
3368
|
-
identity: context.identity
|
|
3369
|
-
} : {}
|
|
3370
|
-
})).get() === !0;
|
|
3371
|
-
} catch {
|
|
3372
|
-
return !1;
|
|
3373
|
-
}
|
|
3374
|
-
}
|
|
3375
|
-
|
|
3376
|
-
async function denyingGuards(args) {
|
|
3377
|
-
const {guards: guards, doc: doc, context: context} = args, denied = [];
|
|
3378
|
-
for (const guard of guards) guardMatches({
|
|
3379
|
-
guard: guard,
|
|
3380
|
-
doc: doc,
|
|
3381
|
-
action: context.action
|
|
3382
|
-
}) && (await evaluateMutationGuard({
|
|
3383
|
-
guard: guard,
|
|
3384
|
-
context: context
|
|
3385
|
-
}) || denied.push(guard));
|
|
3386
|
-
return denied;
|
|
3387
|
-
}
|
|
3388
|
-
|
|
3389
|
-
async function documentActionDenials(args) {
|
|
3390
|
-
const {doc: doc, resource: resource, action: action, guards: guards, identity: identity} = args, enforceable = guards.filter(g => g.resourceType === resource.type && g.resourceId === resource.id);
|
|
3391
|
-
return enforceable.length === 0 ? [] : denyingGuards({
|
|
3392
|
-
guards: enforceable,
|
|
3393
|
-
doc: {
|
|
3394
|
-
id: doc._id,
|
|
3395
|
-
type: doc._type
|
|
3396
|
-
},
|
|
3397
|
-
context: {
|
|
3398
|
-
action: action,
|
|
3399
|
-
before: doc,
|
|
3400
|
-
after: doc,
|
|
3401
|
-
...identity !== void 0 ? {
|
|
3402
|
-
identity: identity
|
|
3403
|
-
} : {}
|
|
3404
|
-
}
|
|
3405
|
-
});
|
|
3406
|
-
}
|
|
3407
|
-
|
|
3408
|
-
async function instanceWriteDenials(args) {
|
|
3409
|
-
const {instance: instance, guards: guards, identity: identity} = args;
|
|
3410
|
-
return documentActionDenials({
|
|
3411
|
-
doc: instance,
|
|
3412
|
-
resource: instance.workflowResource,
|
|
3413
|
-
action: "update",
|
|
3414
|
-
guards: guards,
|
|
3415
|
-
...identity !== void 0 ? {
|
|
3416
|
-
identity: identity
|
|
3417
|
-
} : {}
|
|
3418
|
-
});
|
|
3419
|
-
}
|
|
3420
|
-
|
|
3421
|
-
async function assertInstanceWriteAllowed(args) {
|
|
3422
|
-
const denied = await instanceWriteDenials(args);
|
|
3423
|
-
if (denied.length !== 0) throw MutationGuardDeniedError.fromGuards({
|
|
3424
|
-
documentId: args.instance._id,
|
|
3425
|
-
action: "update",
|
|
3426
|
-
guards: denied
|
|
3427
|
-
});
|
|
3428
|
-
}
|
|
3429
|
-
|
|
3430
|
-
const DATA_MODEL_VERSION = 8, DATA_MODEL_MIN_READER = 4, DATA_MODEL_MAX_READER = 8, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
|
|
3781
|
+
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";
|
|
3431
3782
|
|
|
3432
3783
|
class ReaderModelAcknowledgementError extends WorkflowError {
|
|
3433
3784
|
code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
|
|
@@ -3567,6 +3918,22 @@ const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
|
|
|
3567
3918
|
compatibility: "reader-floor",
|
|
3568
3919
|
applicability: "detectable",
|
|
3569
3920
|
summary: "Assignee fields may restrict newly assigned users and collective roles by role."
|
|
3921
|
+
}), Object.freeze({
|
|
3922
|
+
id: "split-guard-id-spaces",
|
|
3923
|
+
introducedInModel: 9,
|
|
3924
|
+
minReaderModel: 9,
|
|
3925
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
3926
|
+
compatibility: "reader-floor",
|
|
3927
|
+
applicability: "detectable",
|
|
3928
|
+
summary: "Guards spanning edit and lifecycle id spaces emit independently retractable documents."
|
|
3929
|
+
}), Object.freeze({
|
|
3930
|
+
id: "singular-assignee-lists",
|
|
3931
|
+
introducedInModel: 9,
|
|
3932
|
+
minReaderModel: 9,
|
|
3933
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
3934
|
+
compatibility: "reader-floor",
|
|
3935
|
+
applicability: "detectable",
|
|
3936
|
+
summary: "Singular assignee fields use member lists with at most one user and any number of roles."
|
|
3570
3937
|
}) ]);
|
|
3571
3938
|
|
|
3572
3939
|
function recordOf(value) {
|
|
@@ -3690,6 +4057,25 @@ function hasRoleConstrainedAssignments(document) {
|
|
|
3690
4057
|
return persistedFieldEntries(document).some(entry => entryKindMatches(entry, assignmentKindAcceptsRoles) && Array.isArray(entry.roles) && entry.roles.length > 0);
|
|
3691
4058
|
}
|
|
3692
4059
|
|
|
4060
|
+
function hasSingularAssigneeLists(document) {
|
|
4061
|
+
const root = recordOf(document);
|
|
4062
|
+
if (root === void 0) return !1;
|
|
4063
|
+
if (typeof root.definitionSnapshot != "string") return persistedFieldEntries(document).some(entry => entryHasKind(entry, "assignee"));
|
|
4064
|
+
const snapshot = parsedDefinitionSnapshot(root);
|
|
4065
|
+
return typeof snapshot?.modelVersion == "number" && isAssignmentListModel(snapshot.modelVersion) && persistedFieldEntries(document).some(entry => entryHasKind(entry, "assignee"));
|
|
4066
|
+
}
|
|
4067
|
+
|
|
4068
|
+
function isMutationGuardAction(action) {
|
|
4069
|
+
return typeof action == "string" && MUTATION_GUARD_ACTIONS.some(candidate => candidate === action);
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
function hasSplitGuardIdSpaces(document) {
|
|
4073
|
+
return persistedDefinitionTree(document)?.stages.some(stage => recordsAt(stage, "guards").some(guard => {
|
|
4074
|
+
const actions = recordOf(guard.match)?.actions;
|
|
4075
|
+
return Array.isArray(actions) && mutationGuardRequiresSplitEmission(actions.filter(isMutationGuardAction));
|
|
4076
|
+
})) ?? !1;
|
|
4077
|
+
}
|
|
4078
|
+
|
|
3693
4079
|
const featureDetectors = {
|
|
3694
4080
|
"governed-model-stamps": () => !0,
|
|
3695
4081
|
"subject-field-kind": document => hasFieldKind(document, "subject"),
|
|
@@ -3702,6 +4088,8 @@ const featureDetectors = {
|
|
|
3702
4088
|
"readiness-requirements": hasReadinessRequirements,
|
|
3703
4089
|
"due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime"),
|
|
3704
4090
|
"role-constrained-assignment-fields": hasRoleConstrainedAssignments,
|
|
4091
|
+
"singular-assignee-lists": hasSingularAssigneeLists,
|
|
4092
|
+
"split-guard-id-spaces": hasSplitGuardIdSpaces,
|
|
3705
4093
|
"node-semantics": hasNodeSemantics,
|
|
3706
4094
|
"field-patch-ops": document => hasPersistedOpType(document, [ "field.inc", "field.dec", "field.setIfMissing" ]),
|
|
3707
4095
|
"attributes-condition-var": () => !0
|
|
@@ -3837,8 +4225,93 @@ function findStageNode(args) {
|
|
|
3837
4225
|
return args.definition?.stages.find(entry => entry.name === args.stageName);
|
|
3838
4226
|
}
|
|
3839
4227
|
|
|
3840
|
-
function findActivityNode(args) {
|
|
3841
|
-
return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
|
|
4228
|
+
function findActivityNode(args) {
|
|
4229
|
+
return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
|
|
4230
|
+
}
|
|
4231
|
+
|
|
4232
|
+
function requirementDescriptor(requirement) {
|
|
4233
|
+
return {
|
|
4234
|
+
name: requirement.name,
|
|
4235
|
+
...requirement.title !== void 0 ? {
|
|
4236
|
+
title: requirement.title
|
|
4237
|
+
} : {},
|
|
4238
|
+
...requirement.description !== void 0 ? {
|
|
4239
|
+
description: requirement.description
|
|
4240
|
+
} : {}
|
|
4241
|
+
};
|
|
4242
|
+
}
|
|
4243
|
+
|
|
4244
|
+
function subjectDenialLabels(denied) {
|
|
4245
|
+
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
class ActionDisabledError extends WorkflowError {
|
|
4249
|
+
reason;
|
|
4250
|
+
activity;
|
|
4251
|
+
action;
|
|
4252
|
+
constructor(args) {
|
|
4253
|
+
super("action-disabled", formatDisabledReason({
|
|
4254
|
+
activity: args.activity,
|
|
4255
|
+
action: args.action,
|
|
4256
|
+
reason: args.reason
|
|
4257
|
+
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
4258
|
+
this.action = args.action;
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
|
|
4262
|
+
class StartNotAllowedError extends WorkflowError {
|
|
4263
|
+
definition;
|
|
4264
|
+
unmetRequirements;
|
|
4265
|
+
constructor(args) {
|
|
4266
|
+
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
4267
|
+
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
|
|
4271
|
+
function actionRendering(action) {
|
|
4272
|
+
const kind = action.disabledReason?.kind;
|
|
4273
|
+
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
const disabledReasonDetail = {
|
|
4277
|
+
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
4278
|
+
"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`,
|
|
4279
|
+
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
4280
|
+
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
4281
|
+
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
4282
|
+
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
4283
|
+
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.map(requirement => requirement.name).join(", ")}`,
|
|
4284
|
+
"subject-permission-denied": r => `missing subject permission(s): ${subjectDenialLabels(r.denied).join(", ")}`
|
|
4285
|
+
};
|
|
4286
|
+
|
|
4287
|
+
function actionDisabledDetail(reason) {
|
|
4288
|
+
return disabledReasonDetail[reason.kind](reason);
|
|
4289
|
+
}
|
|
4290
|
+
|
|
4291
|
+
function formatDisabledReason({activity: activity, action: action, reason: reason}) {
|
|
4292
|
+
return `Action "${activity}:${action}" is not allowed: ${actionDisabledDetail(reason)}`;
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
class EditFieldDeniedError extends WorkflowError {
|
|
4296
|
+
reason;
|
|
4297
|
+
target;
|
|
4298
|
+
constructor(args) {
|
|
4299
|
+
super("edit-field-denied", formatEditDisabledReason(args.target, args.reason)),
|
|
4300
|
+
this.name = "EditFieldDeniedError", this.reason = args.reason, this.target = args.target;
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
const editDisabledReasonDetail = {
|
|
4305
|
+
"not-editable": () => "field is not declared editable",
|
|
4306
|
+
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
4307
|
+
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
4308
|
+
"edit-window-closed": r => `edit window closed (${r.detail})`,
|
|
4309
|
+
"editor-not-permitted": r => `editor not permitted (${r.predicate})`
|
|
4310
|
+
};
|
|
4311
|
+
|
|
4312
|
+
function formatEditDisabledReason(target, reason) {
|
|
4313
|
+
const detail = editDisabledReasonDetail[reason.kind](reason), where = target.activity !== void 0 ? `${target.activity}.${target.field}` : target.field;
|
|
4314
|
+
return `Field "${target.scope}:${where}" is not editable: ${detail}`;
|
|
3842
4315
|
}
|
|
3843
4316
|
|
|
3844
4317
|
function liveChildrenField(instance) {
|
|
@@ -3867,7 +4340,8 @@ function openStage(instance) {
|
|
|
3867
4340
|
}
|
|
3868
4341
|
|
|
3869
4342
|
function assigneesOf(stage, activityName) {
|
|
3870
|
-
|
|
4343
|
+
const entry = stage?.activities.find(t => t.name === activityName);
|
|
4344
|
+
return [ ...assignmentMembers(entry?.fields ?? []) ];
|
|
3871
4345
|
}
|
|
3872
4346
|
|
|
3873
4347
|
function isResolved(status) {
|
|
@@ -3900,11 +4374,16 @@ function failedActivityCause(input) {
|
|
|
3900
4374
|
|
|
3901
4375
|
function waitingState(input) {
|
|
3902
4376
|
const active = input.activities.find(t => t.status === "active" && (t.activity.actions ?? []).length > 0 && (t.unmetRequirements ?? []).length === 0);
|
|
3903
|
-
if (active
|
|
4377
|
+
if (active === void 0) return;
|
|
4378
|
+
const actions = active.actions.filter(action => actionRendering(action) === "button" && action.allowed).map(action => action.action.name), hasManualAction = active.actions.some(action => !isCascadeFired(action.action));
|
|
4379
|
+
let waitingFor = "automation";
|
|
4380
|
+
return actions.length > 0 ? waitingFor = "caller" : hasManualAction && (waitingFor = "manual-action"),
|
|
4381
|
+
{
|
|
3904
4382
|
state: "waiting",
|
|
3905
4383
|
activity: active.activity.name,
|
|
3906
4384
|
assignees: input.assignees[active.activity.name] ?? [],
|
|
3907
|
-
actions:
|
|
4385
|
+
actions: actions,
|
|
4386
|
+
waitingFor: waitingFor
|
|
3908
4387
|
};
|
|
3909
4388
|
}
|
|
3910
4389
|
|
|
@@ -4030,7 +4509,7 @@ function isClaimExpired(claim, now) {
|
|
|
4030
4509
|
return claim.leaseExpiresAt === void 0 || hasPassed(claim.leaseExpiresAt, now);
|
|
4031
4510
|
}
|
|
4032
4511
|
|
|
4033
|
-
const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ];
|
|
4512
|
+
const EFFECT_RUN_STATUSES = _exhaustiveOptions()([ "done", "failed", "cancelled" ]);
|
|
4034
4513
|
|
|
4035
4514
|
function userLoginProvider(user) {
|
|
4036
4515
|
return user?.provider ?? user?.loginProvider;
|
|
@@ -4812,6 +5291,96 @@ function coerceToGdr(raw, workflowResource) {
|
|
|
4812
5291
|
} : null;
|
|
4813
5292
|
}
|
|
4814
5293
|
|
|
5294
|
+
const NOW = {
|
|
5295
|
+
variable: "now",
|
|
5296
|
+
path: []
|
|
5297
|
+
}, LAST_REPRESENTABLE_MS = 864e13;
|
|
5298
|
+
|
|
5299
|
+
function readsNowIn(reads) {
|
|
5300
|
+
return reads.some(read => read.variable === "now");
|
|
5301
|
+
}
|
|
5302
|
+
|
|
5303
|
+
function readsNow(condition) {
|
|
5304
|
+
return readsNowIn(analyzeCondition(condition).reads);
|
|
5305
|
+
}
|
|
5306
|
+
|
|
5307
|
+
async function stageTimeSites(args) {
|
|
5308
|
+
const {definition: definition, stage: stage, scopeFor: scopeFor} = args, sites = [];
|
|
5309
|
+
for (const site of conditionSitesOf(definition)) {
|
|
5310
|
+
if (site.stage !== stage || site.address.kind === "editable-override" || !readsNow(site.condition)) continue;
|
|
5311
|
+
const activity = "activity" in site.address ? site.address.activity : void 0;
|
|
5312
|
+
sites.push({
|
|
5313
|
+
condition: site.condition,
|
|
5314
|
+
params: await scopeFor(activity)
|
|
5315
|
+
});
|
|
5316
|
+
}
|
|
5317
|
+
return sites;
|
|
5318
|
+
}
|
|
5319
|
+
|
|
5320
|
+
async function nextEvaluationInstant(args) {
|
|
5321
|
+
const {sites: sites, dataset: dataset, now: now} = args, boundaries = [];
|
|
5322
|
+
for (const site of sites) {
|
|
5323
|
+
const boundary = await siteBoundary({
|
|
5324
|
+
...site,
|
|
5325
|
+
dataset: dataset,
|
|
5326
|
+
now: now
|
|
5327
|
+
});
|
|
5328
|
+
boundary !== void 0 && boundaries.push(boundary);
|
|
5329
|
+
}
|
|
5330
|
+
return [ ...boundaries ].sort(byInstant)[0];
|
|
5331
|
+
}
|
|
5332
|
+
|
|
5333
|
+
function byInstant(a, b) {
|
|
5334
|
+
return Date.parse(a) - Date.parse(b);
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
async function siteBoundary(args) {
|
|
5338
|
+
const {condition: condition, params: params, dataset: dataset, now: now} = args, insight = await explainCondition({
|
|
5339
|
+
condition: condition,
|
|
5340
|
+
dataset: dataset,
|
|
5341
|
+
params: params
|
|
5342
|
+
});
|
|
5343
|
+
for (const candidate of await candidateInstants({
|
|
5344
|
+
insight: insight,
|
|
5345
|
+
params: params,
|
|
5346
|
+
dataset: dataset,
|
|
5347
|
+
now: now
|
|
5348
|
+
})) if ((await whatIfCondition({
|
|
5349
|
+
condition: condition,
|
|
5350
|
+
dataset: dataset,
|
|
5351
|
+
params: params,
|
|
5352
|
+
assign: {
|
|
5353
|
+
target: NOW,
|
|
5354
|
+
value: candidate
|
|
5355
|
+
}
|
|
5356
|
+
})).changed) return candidate;
|
|
5357
|
+
}
|
|
5358
|
+
|
|
5359
|
+
async function candidateInstants(args) {
|
|
5360
|
+
const {insight: insight, params: params, dataset: dataset, now: now} = args, comparands = [];
|
|
5361
|
+
for (const atom of insight.atoms) readsNowIn(atom.atom.reads) && comparands.push(...await comparandsOf({
|
|
5362
|
+
atom: atom,
|
|
5363
|
+
params: params,
|
|
5364
|
+
dataset: dataset
|
|
5365
|
+
}));
|
|
5366
|
+
const instants = comparands.filter(isParseableInstant).map(normalizeInstant).filter(instant => Date.parse(instant) < LAST_REPRESENTABLE_MS).flatMap(instant => [ instant, addMs(instant, 1) ]).filter(instant => !hasPassed(instant, now));
|
|
5367
|
+
return [ ...new Set(instants) ].sort(byInstant);
|
|
5368
|
+
}
|
|
5369
|
+
|
|
5370
|
+
function normalizeInstant(value) {
|
|
5371
|
+
return new Date(Date.parse(value)).toISOString();
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5374
|
+
async function comparandsOf(args) {
|
|
5375
|
+
const {atom: atom, params: params, dataset: dataset} = args, requirement = atom.requirement, values = requirement !== void 0 && requirement.target.variable === "now" && "value" in requirement ? [ requirement.value ] : [];
|
|
5376
|
+
for (const read of atom.atom.reads) read.variable !== "now" && values.push(await runGroq({
|
|
5377
|
+
groq: formatRead(read),
|
|
5378
|
+
params: params,
|
|
5379
|
+
dataset: dataset
|
|
5380
|
+
}));
|
|
5381
|
+
return values;
|
|
5382
|
+
}
|
|
5383
|
+
|
|
4815
5384
|
const NonEmpty = NonEmptyString, PersistedAssignmentRolesSchema = v.pipe(v.array(NonEmptyString), v.minLength(1, "assignment roles must not be empty")), UnknownRecord = v.record(v.string(), v.unknown()), PersistedChoiceOptionsSchema = v.looseObject({
|
|
4816
5385
|
list: v.array(v.looseObject({
|
|
4817
5386
|
title: v.string(),
|
|
@@ -4864,7 +5433,7 @@ function fieldArm(kind, value) {
|
|
|
4864
5433
|
};
|
|
4865
5434
|
}
|
|
4866
5435
|
|
|
4867
|
-
const OptionalRefTypes = v.exactOptional(v.array(v.string())),
|
|
5436
|
+
const OptionalRefTypes = v.exactOptional(v.array(v.string())), RawResolvedFieldEntrySchema = v.variant("_type", [ v.looseObject(tolerantEntries()({
|
|
4868
5437
|
...fieldArm("doc.ref", fieldValueSchemas["doc.ref"]),
|
|
4869
5438
|
types: OptionalRefTypes
|
|
4870
5439
|
})), v.looseObject(tolerantEntries()({
|
|
@@ -4885,7 +5454,7 @@ const OptionalRefTypes = v.exactOptional(v.array(v.string())), ResolvedFieldEntr
|
|
|
4885
5454
|
})), v.looseObject(tolerantEntries()({
|
|
4886
5455
|
...fieldArm("array", v.array(UnknownRecord)),
|
|
4887
5456
|
of: v.array(PersistedFieldShapeSchema)
|
|
4888
|
-
})) ]), EffectOriginSchema = tolerantObject()({
|
|
5457
|
+
})) ]), ResolvedFieldEntrySchema = v.pipe(RawResolvedFieldEntrySchema, v.transform(normalizeNestedAssignmentValues)), EffectOriginSchema = tolerantObject()({
|
|
4889
5458
|
kind: v.literal("action"),
|
|
4890
5459
|
name: NonEmpty
|
|
4891
5460
|
}), PendingEffectClaimSchema = tolerantObject()({
|
|
@@ -5746,6 +6315,25 @@ function buildInstanceBase(args) {
|
|
|
5746
6315
|
};
|
|
5747
6316
|
}
|
|
5748
6317
|
|
|
6318
|
+
function instanceDocumentForWrite(instance) {
|
|
6319
|
+
const listModel = writesSingularAssignmentLists(instance);
|
|
6320
|
+
return {
|
|
6321
|
+
...instance,
|
|
6322
|
+
fields: assignmentFieldsForWrite(instance.fields, listModel),
|
|
6323
|
+
stages: assignmentStagesForWrite(instance.stages, listModel)
|
|
6324
|
+
};
|
|
6325
|
+
}
|
|
6326
|
+
|
|
6327
|
+
function memoizedBy(compute) {
|
|
6328
|
+
const cache = /* @__PURE__ */ new Map;
|
|
6329
|
+
return key => {
|
|
6330
|
+
const hit = cache.get(key);
|
|
6331
|
+
if (hit !== void 0) return hit;
|
|
6332
|
+
const value = (async () => compute(key))();
|
|
6333
|
+
return cache.set(key, value), value;
|
|
6334
|
+
};
|
|
6335
|
+
}
|
|
6336
|
+
|
|
5749
6337
|
async function hydrateSnapshot(args) {
|
|
5750
6338
|
const {client: client, clientForGdr: clientForGdr, instance: instance, overlay: overlay} = args, loaded = [], visited = /* @__PURE__ */ new Set;
|
|
5751
6339
|
loaded.push({
|
|
@@ -5896,16 +6484,26 @@ function loadCallContext({client: client, instanceId: instanceId, options: optio
|
|
|
5896
6484
|
|
|
5897
6485
|
async function retryOnRevisionConflict(args) {
|
|
5898
6486
|
const {client: client, instanceId: instanceId, options: options, commit: commit, onExhausted: onExhausted} = args;
|
|
5899
|
-
|
|
5900
|
-
|
|
6487
|
+
return retryCommit({
|
|
6488
|
+
load: () => loadCallContext({
|
|
5901
6489
|
client: client,
|
|
5902
6490
|
instanceId: instanceId,
|
|
5903
6491
|
options: options
|
|
5904
|
-
})
|
|
6492
|
+
}),
|
|
6493
|
+
commit: commit,
|
|
6494
|
+
shouldRetry: isInstanceCommitRevisionConflict,
|
|
6495
|
+
onExhausted: onExhausted
|
|
6496
|
+
});
|
|
6497
|
+
}
|
|
6498
|
+
|
|
6499
|
+
async function retryCommit(args) {
|
|
6500
|
+
const {load: load, commit: commit, shouldRetry: shouldRetry, onExhausted: onExhausted} = args;
|
|
6501
|
+
for (let attempt = 1; attempt <= CONCURRENT_COMMIT_MAX_ATTEMPTS; attempt++) {
|
|
6502
|
+
const ctx = await load();
|
|
5905
6503
|
try {
|
|
5906
6504
|
return await commit(ctx);
|
|
5907
6505
|
} catch (error) {
|
|
5908
|
-
if (!
|
|
6506
|
+
if (!shouldRetry(error)) throw error;
|
|
5909
6507
|
}
|
|
5910
6508
|
}
|
|
5911
6509
|
throw onExhausted();
|
|
@@ -5953,6 +6551,22 @@ async function ctxConditionParams(ctx, opts) {
|
|
|
5953
6551
|
}, opts);
|
|
5954
6552
|
}
|
|
5955
6553
|
|
|
6554
|
+
async function ctxNextEvaluationAt(ctx) {
|
|
6555
|
+
if (ctx.instance.completedAt !== void 0) return;
|
|
6556
|
+
const scopeFor = memoizedBy(activityName => ctxConditionParams(ctx, activityName === void 0 ? void 0 : {
|
|
6557
|
+
activityName: activityName
|
|
6558
|
+
})), sites = await stageTimeSites({
|
|
6559
|
+
definition: ctx.definition,
|
|
6560
|
+
stage: ctx.instance.currentStage,
|
|
6561
|
+
scopeFor: scopeFor
|
|
6562
|
+
});
|
|
6563
|
+
if (sites.length !== 0) return nextEvaluationInstant({
|
|
6564
|
+
sites: sites,
|
|
6565
|
+
dataset: ctx.snapshot.docs,
|
|
6566
|
+
now: ctx.now
|
|
6567
|
+
});
|
|
6568
|
+
}
|
|
6569
|
+
|
|
5956
6570
|
async function ctxEvaluateConditionOutcome({ctx: ctx, condition: condition, opts: opts}) {
|
|
5957
6571
|
return condition === void 0 ? "satisfied" : evaluateConditionOutcome({
|
|
5958
6572
|
condition: condition,
|
|
@@ -6124,7 +6738,7 @@ async function resolveActivityFieldEntries(args) {
|
|
|
6124
6738
|
|
|
6125
6739
|
async function resolveBindings(args) {
|
|
6126
6740
|
const resolved = {};
|
|
6127
|
-
for (const [key, groq] of Object.entries(args.bindings ?? {})) resolved[key] = await runGroq({
|
|
6741
|
+
for (const [key, groq] of Object.entries(args.bindings ?? {})) resolved[key] = await runGroq$1({
|
|
6128
6742
|
groq: groq,
|
|
6129
6743
|
params: args.params,
|
|
6130
6744
|
snapshot: args.snapshot
|
|
@@ -6581,7 +7195,7 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
6581
7195
|
if (route === null) return null;
|
|
6582
7196
|
const resource = assertSingleResource(route.targets), types = resolveMatchTypes(route.targets, guard.match.types);
|
|
6583
7197
|
return {
|
|
6584
|
-
|
|
7198
|
+
docs: compileGuards({
|
|
6585
7199
|
id: route.guardId,
|
|
6586
7200
|
resourceType: resource.type,
|
|
6587
7201
|
resourceId: resource.id,
|
|
@@ -6613,19 +7227,63 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
6613
7227
|
async function upsertGuard(args) {
|
|
6614
7228
|
const {client: client, doc: doc, exists: exists} = args;
|
|
6615
7229
|
if (!exists) try {
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
7230
|
+
return {
|
|
7231
|
+
created: await client.create(doc, {
|
|
7232
|
+
...SYNC_COMMIT,
|
|
7233
|
+
tag: REQUEST_TAG.guardDeploy
|
|
7234
|
+
})
|
|
7235
|
+
};
|
|
6621
7236
|
} catch (error) {
|
|
6622
7237
|
if (!isCreateIdCollision(error)) throw error;
|
|
6623
7238
|
}
|
|
6624
7239
|
const {_id: _id, _type: _type, _rev: _rev, _createdAt: _createdAt, _updatedAt: _updatedAt, ...body} = doc;
|
|
6625
|
-
await client.patch(doc._id).set(body).commit({
|
|
7240
|
+
return await client.patch(doc._id).set(body).commit({
|
|
6626
7241
|
...SYNC_COMMIT,
|
|
6627
7242
|
tag: REQUEST_TAG.guardRefresh
|
|
7243
|
+
}), {
|
|
7244
|
+
created: void 0
|
|
7245
|
+
};
|
|
7246
|
+
}
|
|
7247
|
+
|
|
7248
|
+
async function retractCreatedGuards(guards) {
|
|
7249
|
+
for (const {client: client, doc: doc} of guards.toReversed()) {
|
|
7250
|
+
if (doc._rev === void 0) return new Error(`Cannot roll back guard ${doc._id}: created document has no revision`);
|
|
7251
|
+
try {
|
|
7252
|
+
const revisionCheck = client.patch(doc._id).set({
|
|
7253
|
+
predicate: doc.predicate
|
|
7254
|
+
}).ifRevisionId(doc._rev);
|
|
7255
|
+
await client.transaction().patch(revisionCheck).delete(doc._id).commit({
|
|
7256
|
+
tag: REQUEST_TAG.guardDeploy
|
|
7257
|
+
});
|
|
7258
|
+
} catch (error) {
|
|
7259
|
+
return error;
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
|
|
7264
|
+
async function deployResolvedGuard(args) {
|
|
7265
|
+
const {client: client, resourceKey: resourceKey, doc: doc, guard: guard, stageArgs: stageArgs, existingByResource: existingByResource} = args, localized = await localizeGuardMetadata({
|
|
7266
|
+
doc: doc,
|
|
7267
|
+
guard: guard,
|
|
7268
|
+
client: client,
|
|
7269
|
+
instance: stageArgs.instance,
|
|
7270
|
+
definition: stageArgs.definition
|
|
6628
7271
|
});
|
|
7272
|
+
return (await upsertGuard({
|
|
7273
|
+
client: client,
|
|
7274
|
+
doc: localized,
|
|
7275
|
+
exists: existingByResource.get(resourceKey)?.has(doc._id) ?? !1
|
|
7276
|
+
})).created;
|
|
7277
|
+
}
|
|
7278
|
+
|
|
7279
|
+
async function failGuardDeploy(args) {
|
|
7280
|
+
const {cause: cause, stageName: stageName, deployed: deployed, createdGuards: createdGuards, updatedExistingGuard: updatedExistingGuard} = args, rollbackError = updatedExistingGuard ? void 0 : await retractCreatedGuards(createdGuards);
|
|
7281
|
+
throw deployed > 0 && (updatedExistingGuard || rollbackError !== void 0) ? new PartialGuardDeployError({
|
|
7282
|
+
stageName: stageName,
|
|
7283
|
+
deployed: deployed,
|
|
7284
|
+
cause: cause,
|
|
7285
|
+
rollbackError: rollbackError
|
|
7286
|
+
}) : cause;
|
|
6629
7287
|
}
|
|
6630
7288
|
|
|
6631
7289
|
function resolvedStageGuards(args) {
|
|
@@ -6638,10 +7296,12 @@ function resolvedStageGuards(args) {
|
|
|
6638
7296
|
now: args.now,
|
|
6639
7297
|
snapshot: args.snapshot
|
|
6640
7298
|
});
|
|
6641
|
-
resolved
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
7299
|
+
if (resolved === null) continue;
|
|
7300
|
+
const client = args.clientForGdr(resolved.routeGdr), resourceKey = resourceGdr(resourceFromParsed(resolved.routeGdr));
|
|
7301
|
+
for (const doc of resolved.docs) out.push({
|
|
7302
|
+
client: client,
|
|
7303
|
+
resourceKey: resourceKey,
|
|
7304
|
+
value: doc,
|
|
6645
7305
|
guard: guard
|
|
6646
7306
|
});
|
|
6647
7307
|
}
|
|
@@ -6657,10 +7317,15 @@ function resolvedStageGuardRoutes(args) {
|
|
|
6657
7317
|
}, out = [];
|
|
6658
7318
|
for (const guard of stage?.guards ?? []) {
|
|
6659
7319
|
const route = resolveGuardRoute(guard, ctx);
|
|
6660
|
-
route
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
7320
|
+
if (route === null) continue;
|
|
7321
|
+
const client = args.clientForGdr(route.routeGdr), resourceKey = resourceGdr(resourceFromParsed(route.routeGdr));
|
|
7322
|
+
for (const guardId of compiledGuardIds({
|
|
7323
|
+
id: route.guardId,
|
|
7324
|
+
actions: guard.match.actions
|
|
7325
|
+
})) out.push({
|
|
7326
|
+
client: client,
|
|
7327
|
+
resourceKey: resourceKey,
|
|
7328
|
+
value: guardId
|
|
6664
7329
|
});
|
|
6665
7330
|
}
|
|
6666
7331
|
return out;
|
|
@@ -6716,26 +7381,30 @@ async function deployStageGuards(args) {
|
|
|
6716
7381
|
if (live === void 0 || live.currentStage !== args.stageName || live.abortedAt !== void 0) return;
|
|
6717
7382
|
const routed = resolvedStageGuards(args), existingByResource = await existingGuardIds(groupByResource(routed));
|
|
6718
7383
|
let deployed = 0;
|
|
7384
|
+
const createdGuards = [];
|
|
7385
|
+
let updatedExistingGuard = !1;
|
|
6719
7386
|
for (const {client: client, resourceKey: resourceKey, value: doc, guard: guard} of routed) {
|
|
6720
7387
|
try {
|
|
6721
|
-
const
|
|
7388
|
+
const created = await deployResolvedGuard({
|
|
7389
|
+
client: client,
|
|
7390
|
+
resourceKey: resourceKey,
|
|
6722
7391
|
doc: doc,
|
|
6723
7392
|
guard: guard,
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
definition: args.definition
|
|
7393
|
+
stageArgs: args,
|
|
7394
|
+
existingByResource: existingByResource
|
|
6727
7395
|
});
|
|
6728
|
-
|
|
7396
|
+
created === void 0 ? updatedExistingGuard = !0 : createdGuards.push({
|
|
6729
7397
|
client: client,
|
|
6730
|
-
doc:
|
|
6731
|
-
exists: existingByResource.get(resourceKey)?.has(doc._id) ?? !1
|
|
7398
|
+
doc: created
|
|
6732
7399
|
});
|
|
6733
7400
|
} catch (cause) {
|
|
6734
|
-
|
|
7401
|
+
await failGuardDeploy({
|
|
7402
|
+
cause: cause,
|
|
6735
7403
|
stageName: args.stageName,
|
|
6736
7404
|
deployed: deployed,
|
|
6737
|
-
|
|
6738
|
-
|
|
7405
|
+
createdGuards: createdGuards,
|
|
7406
|
+
updatedExistingGuard: updatedExistingGuard
|
|
7407
|
+
});
|
|
6739
7408
|
}
|
|
6740
7409
|
deployed += 1;
|
|
6741
7410
|
}
|
|
@@ -6967,7 +7636,8 @@ async function persistThenDeploy({ctx: ctx, mutation: mutation, deploy: deploy})
|
|
|
6967
7636
|
committedRev: committed._rev,
|
|
6968
7637
|
restore: instanceStateFields({
|
|
6969
7638
|
...ctx.instance,
|
|
6970
|
-
minReaderModel: minReaderModelOf(ctx.instance)
|
|
7639
|
+
minReaderModel: minReaderModelOf(ctx.instance),
|
|
7640
|
+
definitionModelVersion: definitionAssignmentModel(ctx.instance)
|
|
6971
7641
|
}),
|
|
6972
7642
|
unset: ctx.instance.completedAt === void 0 ? [ "completedAt" ] : [],
|
|
6973
7643
|
reversible: !spawned,
|
|
@@ -7232,7 +7902,7 @@ async function projectRowFields({ctx: ctx, sub: sub, childDefinition: childDefin
|
|
|
7232
7902
|
for (const [name, groq] of Object.entries(sub.with ?? {})) {
|
|
7233
7903
|
const declared = (childDefinition.fields ?? []).find(e => e.name === name);
|
|
7234
7904
|
if (declared === void 0) throw new Error(`spawn.with["${name}"]: subworkflow "${childDefinition.name}" declares no field entry "${name}"`);
|
|
7235
|
-
const raw = await runGroq({
|
|
7905
|
+
const raw = await runGroq$1({
|
|
7236
7906
|
groq: groq,
|
|
7237
7907
|
params: {
|
|
7238
7908
|
...parentScope,
|
|
@@ -7275,7 +7945,7 @@ async function projectRowFields({ctx: ctx, sub: sub, childDefinition: childDefin
|
|
|
7275
7945
|
async function resolveContextHandoff({ctx: ctx, sub: sub, parentScope: parentScope}) {
|
|
7276
7946
|
const out = {};
|
|
7277
7947
|
for (const [name, groq] of Object.entries(sub.context ?? {})) {
|
|
7278
|
-
const v2 = await runGroq({
|
|
7948
|
+
const v2 = await runGroq$1({
|
|
7279
7949
|
groq: groq,
|
|
7280
7950
|
params: parentScope,
|
|
7281
7951
|
snapshot: ctx.snapshot
|
|
@@ -8061,91 +8731,6 @@ async function callerBoundVarsForCall(args) {
|
|
|
8061
8731
|
});
|
|
8062
8732
|
}
|
|
8063
8733
|
|
|
8064
|
-
function requirementDescriptor(requirement) {
|
|
8065
|
-
return {
|
|
8066
|
-
name: requirement.name,
|
|
8067
|
-
...requirement.title !== void 0 ? {
|
|
8068
|
-
title: requirement.title
|
|
8069
|
-
} : {},
|
|
8070
|
-
...requirement.description !== void 0 ? {
|
|
8071
|
-
description: requirement.description
|
|
8072
|
-
} : {}
|
|
8073
|
-
};
|
|
8074
|
-
}
|
|
8075
|
-
|
|
8076
|
-
function subjectDenialLabels(denied) {
|
|
8077
|
-
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
8078
|
-
}
|
|
8079
|
-
|
|
8080
|
-
class ActionDisabledError extends WorkflowError {
|
|
8081
|
-
reason;
|
|
8082
|
-
activity;
|
|
8083
|
-
action;
|
|
8084
|
-
constructor(args) {
|
|
8085
|
-
super("action-disabled", formatDisabledReason({
|
|
8086
|
-
activity: args.activity,
|
|
8087
|
-
action: args.action,
|
|
8088
|
-
reason: args.reason
|
|
8089
|
-
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
8090
|
-
this.action = args.action;
|
|
8091
|
-
}
|
|
8092
|
-
}
|
|
8093
|
-
|
|
8094
|
-
class StartNotAllowedError extends WorkflowError {
|
|
8095
|
-
definition;
|
|
8096
|
-
unmetRequirements;
|
|
8097
|
-
constructor(args) {
|
|
8098
|
-
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
8099
|
-
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
8100
|
-
}
|
|
8101
|
-
}
|
|
8102
|
-
|
|
8103
|
-
function actionRendering(action) {
|
|
8104
|
-
const kind = action.disabledReason?.kind;
|
|
8105
|
-
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
8106
|
-
}
|
|
8107
|
-
|
|
8108
|
-
const disabledReasonDetail = {
|
|
8109
|
-
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
8110
|
-
"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`,
|
|
8111
|
-
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
8112
|
-
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
8113
|
-
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
8114
|
-
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
8115
|
-
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.map(requirement => requirement.name).join(", ")}`,
|
|
8116
|
-
"subject-permission-denied": r => `missing subject permission(s): ${subjectDenialLabels(r.denied).join(", ")}`
|
|
8117
|
-
};
|
|
8118
|
-
|
|
8119
|
-
function actionDisabledDetail(reason) {
|
|
8120
|
-
return disabledReasonDetail[reason.kind](reason);
|
|
8121
|
-
}
|
|
8122
|
-
|
|
8123
|
-
function formatDisabledReason({activity: activity, action: action, reason: reason}) {
|
|
8124
|
-
return `Action "${activity}:${action}" is not allowed: ${actionDisabledDetail(reason)}`;
|
|
8125
|
-
}
|
|
8126
|
-
|
|
8127
|
-
class EditFieldDeniedError extends WorkflowError {
|
|
8128
|
-
reason;
|
|
8129
|
-
target;
|
|
8130
|
-
constructor(args) {
|
|
8131
|
-
super("edit-field-denied", formatEditDisabledReason(args.target, args.reason)),
|
|
8132
|
-
this.name = "EditFieldDeniedError", this.reason = args.reason, this.target = args.target;
|
|
8133
|
-
}
|
|
8134
|
-
}
|
|
8135
|
-
|
|
8136
|
-
const editDisabledReasonDetail = {
|
|
8137
|
-
"not-editable": () => "field is not declared editable",
|
|
8138
|
-
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
8139
|
-
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
8140
|
-
"edit-window-closed": r => `edit window closed (${r.detail})`,
|
|
8141
|
-
"editor-not-permitted": r => `editor not permitted (${r.predicate})`
|
|
8142
|
-
};
|
|
8143
|
-
|
|
8144
|
-
function formatEditDisabledReason(target, reason) {
|
|
8145
|
-
const detail = editDisabledReasonDetail[reason.kind](reason), where = target.activity !== void 0 ? `${target.activity}.${target.field}` : target.field;
|
|
8146
|
-
return `Field "${target.scope}:${where}" is not editable: ${detail}`;
|
|
8147
|
-
}
|
|
8148
|
-
|
|
8149
8734
|
async function fireAction(args) {
|
|
8150
8735
|
const {client: client, instanceId: instanceId, activity: activity, action: action, params: params, requestRecord: requestRecord, options: options} = args;
|
|
8151
8736
|
return retryOnRevisionConflict({
|
|
@@ -8313,7 +8898,7 @@ async function commitAction({ctx: ctx, activityName: activityName, actionName: a
|
|
|
8313
8898
|
actionName: actionName,
|
|
8314
8899
|
callerParams: callerParams,
|
|
8315
8900
|
options: options
|
|
8316
|
-
}), mutation =
|
|
8901
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
8317
8902
|
recordProcessedRequest({
|
|
8318
8903
|
mutation: mutation,
|
|
8319
8904
|
record: requestRecord,
|
|
@@ -8479,7 +9064,7 @@ async function primeInitialStage(args) {
|
|
|
8479
9064
|
})
|
|
8480
9065
|
});
|
|
8481
9066
|
const terminal = isTerminalStage(stage), committed = await client.patch(instance._id).set({
|
|
8482
|
-
stages: [ initialStageEntry ],
|
|
9067
|
+
stages: assignmentStagesForWrite([ initialStageEntry ], writesSingularAssignmentLists(instance)),
|
|
8483
9068
|
lastChangedAt: now,
|
|
8484
9069
|
...terminal ? {
|
|
8485
9070
|
completedAt: now
|
|
@@ -8537,32 +9122,59 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
8537
9122
|
settlingCohorts: settlingCohorts
|
|
8538
9123
|
} : {},
|
|
8539
9124
|
memberRolesLoader: memberRolesLoader
|
|
8540
|
-
}
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
9125
|
+
};
|
|
9126
|
+
let preloadedInstance = instance;
|
|
9127
|
+
return retryCommit({
|
|
9128
|
+
load: async () => {
|
|
9129
|
+
if (preloadedInstance === void 0) return loadContext({
|
|
9130
|
+
client: client,
|
|
9131
|
+
instanceId: instanceId,
|
|
9132
|
+
options: contextOptions
|
|
9133
|
+
});
|
|
9134
|
+
const loaded = preloadedInstance;
|
|
9135
|
+
return preloadedInstance = void 0, buildEngineContext({
|
|
9136
|
+
client: client,
|
|
9137
|
+
instance: loaded,
|
|
9138
|
+
definition: parseDefinitionSnapshot(loaded),
|
|
9139
|
+
...contextOptions
|
|
9140
|
+
});
|
|
9141
|
+
},
|
|
9142
|
+
commit: ctx => commitCascadeHop({
|
|
9143
|
+
ctx: ctx,
|
|
9144
|
+
actor: actor
|
|
9145
|
+
}),
|
|
9146
|
+
shouldRetry: isInstanceCommitRevisionConflict,
|
|
9147
|
+
onExhausted: () => new ConcurrentCascadeError({
|
|
9148
|
+
instanceId: instanceId,
|
|
9149
|
+
attempts: CONCURRENT_COMMIT_MAX_ATTEMPTS
|
|
9150
|
+
})
|
|
8549
9151
|
});
|
|
9152
|
+
}
|
|
9153
|
+
|
|
9154
|
+
async function commitCascadeHop({ctx: ctx, actor: actor}) {
|
|
8550
9155
|
if (isTerminal(ctx)) return {
|
|
8551
9156
|
moved: !1
|
|
8552
9157
|
};
|
|
8553
|
-
const stage = findStage(ctx.definition, ctx.instance.currentStage), mutation =
|
|
9158
|
+
const stage = findStage(ctx.definition, ctx.instance.currentStage), mutation = startRevisionRetryMutation(ctx.instance), fired = await runTriggeredActions({
|
|
8554
9159
|
ctx: ctx,
|
|
8555
9160
|
mutation: mutation,
|
|
8556
9161
|
stage: stage
|
|
8557
9162
|
}), hopCtx = liveViewContext(ctx, mutation), transition = await pickTransition(hopCtx, stage);
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
9163
|
+
if (transition === void 0) {
|
|
9164
|
+
const nextEvaluationAt = await ctxNextEvaluationAt(hopCtx);
|
|
9165
|
+
return fired.fires > 0 && await persistThenMaybeRefresh({
|
|
9166
|
+
ctx: ctx,
|
|
9167
|
+
mutation: mutation,
|
|
9168
|
+
stageName: stage.name,
|
|
9169
|
+
didChangeState: fired.ranFieldOps
|
|
9170
|
+
}), {
|
|
9171
|
+
moved: !1,
|
|
9172
|
+
...nextEvaluationAt !== void 0 ? {
|
|
9173
|
+
nextEvaluationAt: nextEvaluationAt
|
|
9174
|
+
} : {}
|
|
9175
|
+
};
|
|
9176
|
+
}
|
|
9177
|
+
return await commitStageMove({
|
|
8566
9178
|
ctx: ctx,
|
|
8567
9179
|
mutation: mutation,
|
|
8568
9180
|
fromStage: stage,
|
|
@@ -8572,7 +9184,7 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
8572
9184
|
actor: actor
|
|
8573
9185
|
}), {
|
|
8574
9186
|
moved: !0
|
|
8575
|
-
}
|
|
9187
|
+
};
|
|
8576
9188
|
}
|
|
8577
9189
|
|
|
8578
9190
|
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}) {
|
|
@@ -8588,8 +9200,7 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
8588
9200
|
clock: clock,
|
|
8589
9201
|
executionContext: executionContext,
|
|
8590
9202
|
telemetry: telemetry
|
|
8591
|
-
})
|
|
8592
|
-
if (!(await runCascadeHop({
|
|
9203
|
+
}), hop = await runCascadeHop({
|
|
8593
9204
|
client: client,
|
|
8594
9205
|
instanceId: instanceId,
|
|
8595
9206
|
actor: actor,
|
|
@@ -8604,7 +9215,13 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
8604
9215
|
...drained.drained ? {} : {
|
|
8605
9216
|
instance: drained.instance
|
|
8606
9217
|
}
|
|
8607
|
-
})
|
|
9218
|
+
});
|
|
9219
|
+
if (!hop.moved) return {
|
|
9220
|
+
cascaded: count,
|
|
9221
|
+
...hop.nextEvaluationAt !== void 0 ? {
|
|
9222
|
+
nextEvaluationAt: hop.nextEvaluationAt
|
|
9223
|
+
} : {}
|
|
9224
|
+
};
|
|
8608
9225
|
if (count++, count >= CASCADE_LIMIT) throw new CascadeLimitError({
|
|
8609
9226
|
instanceId: instanceId,
|
|
8610
9227
|
limit: CASCADE_LIMIT
|
|
@@ -8904,6 +9521,8 @@ async function recordOrphanedPropagation({ctx: ctx, mutation: mutation, child: c
|
|
|
8904
9521
|
function startMutation(instance) {
|
|
8905
9522
|
return {
|
|
8906
9523
|
minReaderModel: minReaderModelOf(instance),
|
|
9524
|
+
definitionSnapshot: instance.definitionSnapshot,
|
|
9525
|
+
definitionModelVersion: definitionAssignmentModel(instance),
|
|
8907
9526
|
currentStage: instance.currentStage,
|
|
8908
9527
|
fields: (instance.fields ?? []).map(s => ({
|
|
8909
9528
|
...s
|
|
@@ -8951,11 +9570,17 @@ function startMutation(instance) {
|
|
|
8951
9570
|
};
|
|
8952
9571
|
}
|
|
8953
9572
|
|
|
9573
|
+
function startRevisionRetryMutation(instance) {
|
|
9574
|
+
const mutation = startMutation(instance);
|
|
9575
|
+
return mutation.commitErrorMapper = error => isRetryableInstanceCommitConflict(error) ? new InstanceCommitRevisionConflict(error) : error,
|
|
9576
|
+
mutation;
|
|
9577
|
+
}
|
|
9578
|
+
|
|
8954
9579
|
function instanceStateFields(src) {
|
|
8955
|
-
const state = {
|
|
9580
|
+
const listModel = isAssignmentListModel(src.definitionModelVersion), state = {
|
|
8956
9581
|
currentStage: src.currentStage,
|
|
8957
|
-
fields: src.fields,
|
|
8958
|
-
stages: src.stages,
|
|
9582
|
+
fields: assignmentFieldsForWrite(src.fields, listModel),
|
|
9583
|
+
stages: assignmentStagesForWrite(src.stages, listModel),
|
|
8959
9584
|
subworkflows: src.subworkflows ?? [],
|
|
8960
9585
|
pendingEffects: src.pendingEffects,
|
|
8961
9586
|
effectHistory: src.effectHistory,
|
|
@@ -8972,7 +9597,10 @@ function instanceStateFields(src) {
|
|
|
8972
9597
|
return {
|
|
8973
9598
|
...modelStampFor({
|
|
8974
9599
|
documentType: "instance",
|
|
8975
|
-
document:
|
|
9600
|
+
document: {
|
|
9601
|
+
...state,
|
|
9602
|
+
definitionSnapshot: src.definitionSnapshot
|
|
9603
|
+
},
|
|
8976
9604
|
storedMinReaderModel: src.minReaderModel
|
|
8977
9605
|
}),
|
|
8978
9606
|
...state
|
|
@@ -9007,11 +9635,11 @@ async function persist(ctx, mutation) {
|
|
|
9007
9635
|
...instanceStateFields(mutation),
|
|
9008
9636
|
lastChangedAt: ctx.now
|
|
9009
9637
|
}, pendingCreates = mutation.pendingCreates;
|
|
9010
|
-
if (pendingCreates.length === 0) return ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit(SYNC_COMMIT);
|
|
9638
|
+
if (pendingCreates.length === 0) return commitInstanceWrite(() => ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit(SYNC_COMMIT), mutation.commitErrorMapper);
|
|
9011
9639
|
const tx = ctx.client.transaction();
|
|
9012
|
-
for (const {body: body} of pendingCreates) tx.create(body);
|
|
9640
|
+
for (const {body: body} of pendingCreates) tx.create(instanceDocumentForWrite(body));
|
|
9013
9641
|
tx.patch(ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev)),
|
|
9014
|
-
await tx.commit(), mutation.pendingCreates = [];
|
|
9642
|
+
await commitInstanceWrite(() => tx.commit(), mutation.commitErrorMapper), mutation.pendingCreates = [];
|
|
9015
9643
|
const actorForPriming = ctx.actor, settlingCohorts = new Set(ctx.settlingCohorts).add(ctx.instance._id);
|
|
9016
9644
|
for (const {body: body} of pendingCreates) try {
|
|
9017
9645
|
const stepArgs = spawnStepArgs(ctx, {
|
|
@@ -9038,6 +9666,14 @@ async function persist(ctx, mutation) {
|
|
|
9038
9666
|
return reloaded;
|
|
9039
9667
|
}
|
|
9040
9668
|
|
|
9669
|
+
async function commitInstanceWrite(write, mapError) {
|
|
9670
|
+
try {
|
|
9671
|
+
return await write();
|
|
9672
|
+
} catch (error) {
|
|
9673
|
+
throw mapError?.(error) ?? error;
|
|
9674
|
+
}
|
|
9675
|
+
}
|
|
9676
|
+
|
|
9041
9677
|
async function settleSpawnBatch(ctx, args) {
|
|
9042
9678
|
try {
|
|
9043
9679
|
await propagateSpawnBatch({
|
|
@@ -9300,7 +9936,7 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
|
|
|
9300
9936
|
outputs: outputs,
|
|
9301
9937
|
memberRoles: ctx.memberRoles,
|
|
9302
9938
|
roleAliases: ctx.definition.roleAliases
|
|
9303
|
-
}), mutation =
|
|
9939
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
9304
9940
|
recordProcessedRequest({
|
|
9305
9941
|
mutation: mutation,
|
|
9306
9942
|
record: requestRecord,
|
|
@@ -9479,7 +10115,7 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
9479
10115
|
effect: pending.name,
|
|
9480
10116
|
issues: [ "a mid-dispatch report must carry at least one field op — there is nothing to commit" ]
|
|
9481
10117
|
});
|
|
9482
|
-
const mutation =
|
|
10118
|
+
const mutation = startRevisionRetryMutation(ctx.instance);
|
|
9483
10119
|
return recordProcessedRequest({
|
|
9484
10120
|
mutation: mutation,
|
|
9485
10121
|
record: requestRecord,
|
|
@@ -9515,7 +10151,7 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
9515
10151
|
};
|
|
9516
10152
|
}
|
|
9517
10153
|
|
|
9518
|
-
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
10154
|
+
const RESET_ACTIVITY_TARGETS = _exhaustiveOptions()([ "active", "skipped" ]);
|
|
9519
10155
|
|
|
9520
10156
|
function isResetActivityTarget(value) {
|
|
9521
10157
|
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
@@ -9627,6 +10263,10 @@ function replayable(args) {
|
|
|
9627
10263
|
return (stage.activities ?? []).every(declared => primed.has(declared.name)) ? !(stage.activities ?? []).flatMap(declared => declared.actions ?? []).some(sibling => isCascadeFired(sibling) && sibling.spawn !== void 0) : !1;
|
|
9628
10264
|
}
|
|
9629
10265
|
|
|
10266
|
+
function clientGuardDereference(client) {
|
|
10267
|
+
return async ({_ref: _ref}) => await client.getDocument(toBareId(_ref)) ?? null;
|
|
10268
|
+
}
|
|
10269
|
+
|
|
9630
10270
|
async function buildFieldInsights({sites: sites, snapshot: snapshot}) {
|
|
9631
10271
|
const insights = [];
|
|
9632
10272
|
for (const field of fieldsReadAcross(sites)) {
|
|
@@ -9782,6 +10422,7 @@ async function evaluateInstance(args) {
|
|
|
9782
10422
|
guards: guards,
|
|
9783
10423
|
now: now,
|
|
9784
10424
|
resourceGrants: resourceGrants,
|
|
10425
|
+
guardDereference: clientGuardDereference(client),
|
|
9785
10426
|
...localPrincipalId !== void 0 ? {
|
|
9786
10427
|
localPrincipalId: localPrincipalId
|
|
9787
10428
|
} : {},
|
|
@@ -9794,16 +10435,6 @@ async function evaluateInstance(args) {
|
|
|
9794
10435
|
});
|
|
9795
10436
|
}
|
|
9796
10437
|
|
|
9797
|
-
function memoizedByName(render) {
|
|
9798
|
-
const rendered = /* @__PURE__ */ new Map;
|
|
9799
|
-
return activityName => {
|
|
9800
|
-
const hit = rendered.get(activityName);
|
|
9801
|
-
if (hit !== void 0) return hit;
|
|
9802
|
-
const scope = render(activityName);
|
|
9803
|
-
return rendered.set(activityName, scope), scope;
|
|
9804
|
-
};
|
|
9805
|
-
}
|
|
9806
|
-
|
|
9807
10438
|
async function callerBoundProjectionScopes(args) {
|
|
9808
10439
|
const can = await advisoryCan({
|
|
9809
10440
|
instance: args.instance,
|
|
@@ -9824,13 +10455,17 @@ async function callerBoundProjectionScopes(args) {
|
|
|
9824
10455
|
};
|
|
9825
10456
|
return {
|
|
9826
10457
|
scope: await renderConditionScope(args.scopeSource, opts),
|
|
9827
|
-
scopeForActivity:
|
|
10458
|
+
scopeForActivity: memoizedBy(activityName => renderConditionScope(args.scopeSource, {
|
|
9828
10459
|
activityName: activityName,
|
|
9829
10460
|
...opts
|
|
9830
10461
|
}))
|
|
9831
10462
|
};
|
|
9832
10463
|
}
|
|
9833
10464
|
|
|
10465
|
+
function clockSitesOf(instance, sites) {
|
|
10466
|
+
return terminalState(instance) !== "in-flight" ? [] : sites.filter(entry => readsNowIn(entry.insight.analysis.reads));
|
|
10467
|
+
}
|
|
10468
|
+
|
|
9834
10469
|
function currentStageOf(instance, definition) {
|
|
9835
10470
|
try {
|
|
9836
10471
|
return findStage(definition, instance.currentStage);
|
|
@@ -9880,12 +10515,13 @@ async function evaluateFromSnapshot(args) {
|
|
|
9880
10515
|
grants: grants,
|
|
9881
10516
|
attributes: attributes,
|
|
9882
10517
|
identity: anchorIdentity
|
|
9883
|
-
}), cascadeScopeForActivity =
|
|
10518
|
+
}), cascadeScopeForActivity = memoizedBy(activityName => renderConditionScope(scopeSource, {
|
|
9884
10519
|
activityName: activityName
|
|
9885
10520
|
})), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
9886
10521
|
instance: instance,
|
|
9887
10522
|
identity: anchorIdentity,
|
|
9888
|
-
guards: args.guards
|
|
10523
|
+
guards: args.guards,
|
|
10524
|
+
dereference: args.guardDereference
|
|
9889
10525
|
}), subjectDenials = await forecastSubjectDenials({
|
|
9890
10526
|
instance: instance,
|
|
9891
10527
|
snapshot: snapshot,
|
|
@@ -9942,6 +10578,10 @@ async function evaluateFromSnapshot(args) {
|
|
|
9942
10578
|
scopeForActivity: scopeForActivity,
|
|
9943
10579
|
guardDenial: editGuardDenial,
|
|
9944
10580
|
sites: sites
|
|
10581
|
+
}), nextEvaluationAt = await nextEvaluationInstant({
|
|
10582
|
+
sites: clockSitesOf(instance, sites),
|
|
10583
|
+
dataset: snapshot.docs,
|
|
10584
|
+
now: now
|
|
9945
10585
|
});
|
|
9946
10586
|
return {
|
|
9947
10587
|
instance: instance,
|
|
@@ -9956,7 +10596,10 @@ async function evaluateFromSnapshot(args) {
|
|
|
9956
10596
|
sites: sites,
|
|
9957
10597
|
snapshot: snapshot
|
|
9958
10598
|
}),
|
|
9959
|
-
autonomy: autonomy
|
|
10599
|
+
autonomy: autonomy,
|
|
10600
|
+
...nextEvaluationAt !== void 0 ? {
|
|
10601
|
+
nextEvaluationAt: nextEvaluationAt
|
|
10602
|
+
} : {}
|
|
9960
10603
|
};
|
|
9961
10604
|
}
|
|
9962
10605
|
|
|
@@ -10104,7 +10747,8 @@ async function evaluateActivity(args) {
|
|
|
10104
10747
|
subjectPermissionReason: subjectPermissionReason,
|
|
10105
10748
|
requirementsReason: requirementsReason,
|
|
10106
10749
|
sites: sites,
|
|
10107
|
-
fireConsequence: a => fireConsequence(activity, a)
|
|
10750
|
+
fireConsequence: a => fireConsequence(activity, a),
|
|
10751
|
+
assignment: assignmentMembers(statusEntry?.fields ?? [])
|
|
10108
10752
|
}));
|
|
10109
10753
|
return {
|
|
10110
10754
|
activity: activity,
|
|
@@ -10261,19 +10905,31 @@ function fireableActionVerdict({args: args, insights: insights}) {
|
|
|
10261
10905
|
reason: args.requirementsReason,
|
|
10262
10906
|
...insights
|
|
10263
10907
|
});
|
|
10264
|
-
const
|
|
10265
|
-
return
|
|
10908
|
+
const filterFailure = filterFailureVerdict(args, insights);
|
|
10909
|
+
return filterFailure !== void 0 ? filterFailure : {
|
|
10910
|
+
...actionEvaluationIdentity(action),
|
|
10911
|
+
allowed: !0,
|
|
10912
|
+
...insights
|
|
10913
|
+
};
|
|
10914
|
+
}
|
|
10915
|
+
|
|
10916
|
+
function filterFailureVerdict(args, insights) {
|
|
10917
|
+
const {action: action} = args, {insight: insight} = insights;
|
|
10918
|
+
if (action.filter === void 0 || insight === void 0 || insight.outcome === "satisfied") return;
|
|
10919
|
+
const holderGate = insight.blockedBy.some(entry => isAssignedGate(entry.atom)) ? {
|
|
10920
|
+
holders: [ ...activeAssignmentMembers(args.assignment) ]
|
|
10921
|
+
} : void 0;
|
|
10922
|
+
return disabled({
|
|
10266
10923
|
action: action,
|
|
10267
10924
|
reason: {
|
|
10268
10925
|
kind: "filter-failed",
|
|
10269
10926
|
filter: action.filter
|
|
10270
10927
|
},
|
|
10271
|
-
...insights
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
};
|
|
10928
|
+
...insights,
|
|
10929
|
+
...holderGate === void 0 ? {} : {
|
|
10930
|
+
holderGate: holderGate
|
|
10931
|
+
}
|
|
10932
|
+
});
|
|
10277
10933
|
}
|
|
10278
10934
|
|
|
10279
10935
|
function actionEvaluationIdentity(action) {
|
|
@@ -10289,12 +10945,13 @@ function semanticsOf(node) {
|
|
|
10289
10945
|
};
|
|
10290
10946
|
}
|
|
10291
10947
|
|
|
10292
|
-
async function instanceGuardReason({instance: instance, identity: identity, guards: guards}) {
|
|
10948
|
+
async function instanceGuardReason({instance: instance, identity: identity, guards: guards, dereference: dereference}) {
|
|
10293
10949
|
if (guards === void 0 || guards.length === 0) return;
|
|
10294
10950
|
const denied = await instanceWriteDenials({
|
|
10295
10951
|
instance: instance,
|
|
10296
10952
|
guards: guards,
|
|
10297
|
-
identity: identity
|
|
10953
|
+
identity: identity,
|
|
10954
|
+
dereference: dereference ?? (() => Promise.resolve(null))
|
|
10298
10955
|
});
|
|
10299
10956
|
if (denied.length !== 0) return {
|
|
10300
10957
|
kind: "mutation-guard-denied",
|
|
@@ -10325,10 +10982,29 @@ function disabled(args) {
|
|
|
10325
10982
|
} : {},
|
|
10326
10983
|
...args.whenInsight !== void 0 ? {
|
|
10327
10984
|
whenInsight: args.whenInsight
|
|
10985
|
+
} : {},
|
|
10986
|
+
...args.holderGate !== void 0 ? {
|
|
10987
|
+
holderGate: args.holderGate
|
|
10328
10988
|
} : {}
|
|
10329
10989
|
};
|
|
10330
10990
|
}
|
|
10331
10991
|
|
|
10992
|
+
const ASSIGNMENT_KINDS = '["assignee", "assignees"]', HAS_USER = '(count(value[@.type == "user"]) > 0 || value.type == "user")', HAS_MEMBER = "(count(value) > 0 || defined(value.type))";
|
|
10993
|
+
|
|
10994
|
+
function assignmentActivityArm(state) {
|
|
10995
|
+
const assignmentFields = `fields[_type in ${ASSIGNMENT_KINDS}]`;
|
|
10996
|
+
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`;
|
|
10997
|
+
}
|
|
10998
|
+
|
|
10999
|
+
function assignmentPrefilter(assignment, params) {
|
|
11000
|
+
if (assignment.userId.length === 0) throw new ContractViolationError("instancesQuery: assignment.userId must be non-empty");
|
|
11001
|
+
const states = [ ...new Set(assignment.states ?? [ "unrouted", "routed", "held" ]) ];
|
|
11002
|
+
if (states.length === 0) throw new ContractViolationError("instancesQuery: assignment.states must not be empty");
|
|
11003
|
+
if (states.some(state => state !== "unrouted" && state !== "routed" && state !== "held")) throw new ContractViolationError("instancesQuery: assignment.states contains an unknown state");
|
|
11004
|
+
return params.assignmentUserId = assignment.userId, params.assignmentRoles = [ ...new Set(assignment.roles ?? []) ].sort(),
|
|
11005
|
+
`count(stages[!defined(exitedAt)].activities[status == "active" && (${states.map(assignmentActivityArm).join(" || ")})]) > 0`;
|
|
11006
|
+
}
|
|
11007
|
+
|
|
10332
11008
|
function inFlightFilter() {
|
|
10333
11009
|
return "!defined(completedAt)";
|
|
10334
11010
|
}
|
|
@@ -10368,7 +11044,7 @@ function compiledConditions(filter, params) {
|
|
|
10368
11044
|
const conditions = [ `_type == "${WORKFLOW_INSTANCE_TYPE}"`, tagScopeFilter() ];
|
|
10369
11045
|
filter.includeCompleted !== !0 && conditions.push(inFlightFilter()), filter.definition !== void 0 && (conditions.push("definition == $definition"),
|
|
10370
11046
|
params.definition = filter.definition), filter.stage !== void 0 && (conditions.push("currentStage == $stage"),
|
|
10371
|
-
params.stage = filter.stage);
|
|
11047
|
+
params.stage = filter.stage), filter.assignment !== void 0 && conditions.push(assignmentPrefilter(filter.assignment, params));
|
|
10372
11048
|
const cursor = beforeArm(filter, params);
|
|
10373
11049
|
cursor !== void 0 && conditions.push(cursor);
|
|
10374
11050
|
const arms = [ documentArm(filter, params), idsArm(filter, params) ].filter(arm => arm !== void 0);
|
|
@@ -10471,6 +11147,222 @@ function stripClaim(entry) {
|
|
|
10471
11147
|
return rest;
|
|
10472
11148
|
}
|
|
10473
11149
|
|
|
11150
|
+
function isProjectRole(value) {
|
|
11151
|
+
return isRecord(value) && typeof value.name == "string";
|
|
11152
|
+
}
|
|
11153
|
+
|
|
11154
|
+
async function projectRoleNames(request, projectId) {
|
|
11155
|
+
const result = await request({
|
|
11156
|
+
uri: `/projects/${encodeURIComponent(projectId)}/roles`
|
|
11157
|
+
});
|
|
11158
|
+
if (!Array.isArray(result) || !result.every(isProjectRole)) throw new Error(`Project role catalog response is invalid for project "${projectId}"`);
|
|
11159
|
+
return new Set(result.map(role => role.name));
|
|
11160
|
+
}
|
|
11161
|
+
|
|
11162
|
+
function memberRoleNames(member, projectId) {
|
|
11163
|
+
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}"`);
|
|
11164
|
+
return member.roles.map(role => role.name);
|
|
11165
|
+
}
|
|
11166
|
+
|
|
11167
|
+
function heldRoleNames(members, projectId) {
|
|
11168
|
+
return new Set(members.flatMap(member => member.isRobot === !0 ? [] : memberRoleNames(member, projectId)));
|
|
11169
|
+
}
|
|
11170
|
+
|
|
11171
|
+
function addRoles(collector, args) {
|
|
11172
|
+
for (const role of args.roles ?? []) collector.references.push({
|
|
11173
|
+
definition: collector.definition,
|
|
11174
|
+
path: args.path,
|
|
11175
|
+
role: role
|
|
11176
|
+
});
|
|
11177
|
+
}
|
|
11178
|
+
|
|
11179
|
+
function visitAssigneeValue(collector, args) {
|
|
11180
|
+
const members = Array.isArray(args.value) ? args.value : [ args.value ];
|
|
11181
|
+
for (const [index, member] of members.entries()) !isRecord(member) || member.type !== "role" || typeof member.role != "string" || collector.references.push({
|
|
11182
|
+
definition: collector.definition,
|
|
11183
|
+
path: `${args.path}[${index}].role`,
|
|
11184
|
+
role: member.role
|
|
11185
|
+
});
|
|
11186
|
+
}
|
|
11187
|
+
|
|
11188
|
+
function visitObjectValue(collector, args) {
|
|
11189
|
+
for (const shape of args.fields ?? []) visitShapeValue(collector, {
|
|
11190
|
+
path: `${args.path}.${shape.name}`,
|
|
11191
|
+
shape: shape,
|
|
11192
|
+
value: args.value[shape.name]
|
|
11193
|
+
});
|
|
11194
|
+
}
|
|
11195
|
+
|
|
11196
|
+
function visitArrayValue(collector, args) {
|
|
11197
|
+
for (const [index, row] of args.rows.entries()) if (isRecord(row)) for (const shape of args.shapes ?? []) visitShapeValue(collector, {
|
|
11198
|
+
path: `${args.path}[${index}].${shape.name}`,
|
|
11199
|
+
shape: shape,
|
|
11200
|
+
value: row[shape.name]
|
|
11201
|
+
});
|
|
11202
|
+
}
|
|
11203
|
+
|
|
11204
|
+
function visitAssignmentValue(collector, args) {
|
|
11205
|
+
args.kind === "assignee" || args.kind === "assignees" ? visitAssigneeValue(collector, args) : args.kind === "object" && isRecord(args.value) ? visitObjectValue(collector, {
|
|
11206
|
+
...args,
|
|
11207
|
+
value: args.value
|
|
11208
|
+
}) : args.kind === "array" && Array.isArray(args.value) && visitArrayValue(collector, {
|
|
11209
|
+
path: args.path,
|
|
11210
|
+
rows: args.value,
|
|
11211
|
+
shapes: args.of
|
|
11212
|
+
});
|
|
11213
|
+
}
|
|
11214
|
+
|
|
11215
|
+
function visitShapeValue(collector, args) {
|
|
11216
|
+
visitAssignmentValue(collector, {
|
|
11217
|
+
path: args.path,
|
|
11218
|
+
kind: args.shape.type,
|
|
11219
|
+
value: args.value,
|
|
11220
|
+
fields: args.shape.fields,
|
|
11221
|
+
of: args.shape.of
|
|
11222
|
+
});
|
|
11223
|
+
}
|
|
11224
|
+
|
|
11225
|
+
function visitField(collector, args) {
|
|
11226
|
+
addRoles(collector, {
|
|
11227
|
+
path: `${args.path}.roles`,
|
|
11228
|
+
roles: args.field.roles
|
|
11229
|
+
});
|
|
11230
|
+
for (const shape of args.field.fields ?? args.field.of ?? []) visitFieldShape(collector, {
|
|
11231
|
+
parentPath: args.path,
|
|
11232
|
+
shape: shape
|
|
11233
|
+
});
|
|
11234
|
+
args.field.initialValue?.type === "literal" && visitAssignmentValue(collector, {
|
|
11235
|
+
path: `${args.path}.initialValue.value`,
|
|
11236
|
+
kind: args.field.type,
|
|
11237
|
+
value: args.field.initialValue.value,
|
|
11238
|
+
fields: args.field.fields,
|
|
11239
|
+
of: args.field.of
|
|
11240
|
+
});
|
|
11241
|
+
}
|
|
11242
|
+
|
|
11243
|
+
function visitFieldShape(collector, args) {
|
|
11244
|
+
const path = `${args.parentPath}.${args.shape.name}`;
|
|
11245
|
+
addRoles(collector, {
|
|
11246
|
+
path: `${path}.roles`,
|
|
11247
|
+
roles: args.shape.roles
|
|
11248
|
+
});
|
|
11249
|
+
for (const child of args.shape.fields ?? args.shape.of ?? []) visitFieldShape(collector, {
|
|
11250
|
+
parentPath: path,
|
|
11251
|
+
shape: child
|
|
11252
|
+
});
|
|
11253
|
+
}
|
|
11254
|
+
|
|
11255
|
+
function rolesFromConditions(definition) {
|
|
11256
|
+
return conditionSitesOf(definition).flatMap(site => {
|
|
11257
|
+
try {
|
|
11258
|
+
return analyzeCondition(site.condition).atoms.flatMap(atom => rolesGateOf(atom) ?? []);
|
|
11259
|
+
} catch {
|
|
11260
|
+
return [];
|
|
11261
|
+
}
|
|
11262
|
+
});
|
|
11263
|
+
}
|
|
11264
|
+
|
|
11265
|
+
function visitRoleAliases(collector, aliases) {
|
|
11266
|
+
for (const [role, fulfillers] of Object.entries(aliases ?? {})) role !== UNIVERSAL_ROLE_ALIAS_KEY && collector.references.push({
|
|
11267
|
+
definition: collector.definition,
|
|
11268
|
+
path: `roleAliases.${role}`,
|
|
11269
|
+
role: role
|
|
11270
|
+
}), addRoles(collector, {
|
|
11271
|
+
path: `roleAliases.${role}`,
|
|
11272
|
+
roles: fulfillers
|
|
11273
|
+
});
|
|
11274
|
+
}
|
|
11275
|
+
|
|
11276
|
+
function visitFields(collector, args) {
|
|
11277
|
+
for (const [index, field] of (args.fields ?? []).entries()) visitField(collector, {
|
|
11278
|
+
path: `${args.parentPath}[${index}]`,
|
|
11279
|
+
field: field
|
|
11280
|
+
});
|
|
11281
|
+
}
|
|
11282
|
+
|
|
11283
|
+
function visitAction(collector, args) {
|
|
11284
|
+
addRoles(collector, {
|
|
11285
|
+
path: `${args.path}.roles`,
|
|
11286
|
+
roles: args.action.roles
|
|
11287
|
+
});
|
|
11288
|
+
for (const [effectIndex, effect] of (args.action.effects ?? []).entries()) for (const shape of effect.outputs ?? []) visitFieldShape(collector, {
|
|
11289
|
+
parentPath: `${args.path}.effects[${effectIndex}].outputs`,
|
|
11290
|
+
shape: shape
|
|
11291
|
+
});
|
|
11292
|
+
}
|
|
11293
|
+
|
|
11294
|
+
function visitStage(collector, args) {
|
|
11295
|
+
const stagePath = `stages[${args.stageIndex}]`;
|
|
11296
|
+
visitFields(collector, {
|
|
11297
|
+
fields: args.stage.fields,
|
|
11298
|
+
parentPath: `${stagePath}.fields`
|
|
11299
|
+
});
|
|
11300
|
+
for (const [activityIndex, activity] of (args.stage.activities ?? []).entries()) {
|
|
11301
|
+
const activityPath = `${stagePath}.activities[${activityIndex}]`;
|
|
11302
|
+
visitFields(collector, {
|
|
11303
|
+
fields: activity.fields,
|
|
11304
|
+
parentPath: `${activityPath}.fields`
|
|
11305
|
+
});
|
|
11306
|
+
for (const [actionIndex, action] of (activity.actions ?? []).entries()) visitAction(collector, {
|
|
11307
|
+
action: action,
|
|
11308
|
+
path: `${activityPath}.actions[${actionIndex}]`
|
|
11309
|
+
});
|
|
11310
|
+
}
|
|
11311
|
+
}
|
|
11312
|
+
|
|
11313
|
+
function addConditionReferences(collector, definition) {
|
|
11314
|
+
for (const role of rolesFromConditions(definition)) collector.references.push({
|
|
11315
|
+
definition: collector.definition,
|
|
11316
|
+
path: "generated role condition",
|
|
11317
|
+
role: role
|
|
11318
|
+
});
|
|
11319
|
+
}
|
|
11320
|
+
|
|
11321
|
+
function definitionRoleReferences(definition) {
|
|
11322
|
+
const collector = {
|
|
11323
|
+
references: [],
|
|
11324
|
+
definition: definition.name
|
|
11325
|
+
};
|
|
11326
|
+
visitRoleAliases(collector, definition.roleAliases), visitFields(collector, {
|
|
11327
|
+
fields: definition.fields,
|
|
11328
|
+
parentPath: "fields"
|
|
11329
|
+
});
|
|
11330
|
+
for (const [stageIndex, stage] of definition.stages.entries()) visitStage(collector, {
|
|
11331
|
+
stage: stage,
|
|
11332
|
+
stageIndex: stageIndex
|
|
11333
|
+
});
|
|
11334
|
+
return addConditionReferences(collector, definition), collector.references;
|
|
11335
|
+
}
|
|
11336
|
+
|
|
11337
|
+
function definitionRoleNames(definition) {
|
|
11338
|
+
return [ ...new Set(definitionRoleReferences(definition).map(reference => reference.role)) ];
|
|
11339
|
+
}
|
|
11340
|
+
|
|
11341
|
+
function roleCatalogProjectId(client, resource) {
|
|
11342
|
+
if (resource.type === "dataset") return datasetResourceParts(resource.id).projectId;
|
|
11343
|
+
const projectId = client.config?.().projectId;
|
|
11344
|
+
if (typeof projectId == "string" && projectId.length > 0) return projectId;
|
|
11345
|
+
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`);
|
|
11346
|
+
}
|
|
11347
|
+
|
|
11348
|
+
async function validateDefinitionRoles(args) {
|
|
11349
|
+
const references = args.definitions.flatMap(definitionRoleReferences);
|
|
11350
|
+
if (references.length === 0) /* @__PURE__ */ return new Map;
|
|
11351
|
+
if (args.client.request === void 0) throw new Error("workflow.deployDefinitions: definitions reference project roles, but the client cannot read the project role catalog");
|
|
11352
|
+
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));
|
|
11353
|
+
if (unknown.length > 0) {
|
|
11354
|
+
const lines = unknown.map(({definition: definition, path: path, role: role}) => ` - ${definition}: ${path} references unknown role "${role}"`);
|
|
11355
|
+
throw new Error(`workflow.deployDefinitions: unknown project roles for project "${projectId}":\n${lines.join(`\n`)}`);
|
|
11356
|
+
}
|
|
11357
|
+
const held = heldRoleNames(members, projectId), warnings = /* @__PURE__ */ new Map;
|
|
11358
|
+
for (const {definition: definition, role: role} of references) {
|
|
11359
|
+
if (held.has(role)) continue;
|
|
11360
|
+
const message = `Project role "${role}" has no current user holder; work routed to it has no recipient.`, definitionWarnings = warnings.get(definition) ?? [];
|
|
11361
|
+
definitionWarnings.includes(message) || definitionWarnings.push(message), warnings.set(definition, definitionWarnings);
|
|
11362
|
+
}
|
|
11363
|
+
return warnings;
|
|
11364
|
+
}
|
|
11365
|
+
|
|
10474
11366
|
async function sortByDependencies({client: client, definitions: definitions, tag: tag}) {
|
|
10475
11367
|
const byName = /* @__PURE__ */ new Map;
|
|
10476
11368
|
for (const def of definitions) {
|
|
@@ -10771,7 +11663,7 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
|
|
|
10771
11663
|
site: site,
|
|
10772
11664
|
mode: mode,
|
|
10773
11665
|
value: value
|
|
10774
|
-
}), mutation =
|
|
11666
|
+
}), mutation = startRevisionRetryMutation(ctx.instance);
|
|
10775
11667
|
recordProcessedRequest({
|
|
10776
11668
|
mutation: mutation,
|
|
10777
11669
|
record: requestRecord,
|
|
@@ -10915,14 +11807,14 @@ async function runCommitVerb(params) {
|
|
|
10915
11807
|
client: client,
|
|
10916
11808
|
instanceId: instanceId,
|
|
10917
11809
|
tag: tag
|
|
10918
|
-
});
|
|
11810
|
+
}), now = clock();
|
|
10919
11811
|
return runDeduped({
|
|
10920
11812
|
client: client,
|
|
10921
11813
|
tag: tag,
|
|
10922
11814
|
instanceId: instanceId,
|
|
10923
11815
|
record: record,
|
|
10924
11816
|
before: before,
|
|
10925
|
-
now:
|
|
11817
|
+
now: now,
|
|
10926
11818
|
actor: context.actor,
|
|
10927
11819
|
clientForGdr: context.clientForGdr,
|
|
10928
11820
|
refSurface: context.refSurface,
|
|
@@ -10933,6 +11825,7 @@ async function runCommitVerb(params) {
|
|
|
10933
11825
|
run: () => run({
|
|
10934
11826
|
...context,
|
|
10935
11827
|
clock: clock,
|
|
11828
|
+
now: now,
|
|
10936
11829
|
record: record,
|
|
10937
11830
|
before: before
|
|
10938
11831
|
})
|
|
@@ -10956,7 +11849,7 @@ async function runDeduped(args) {
|
|
|
10956
11849
|
client: client,
|
|
10957
11850
|
instanceId: instanceId,
|
|
10958
11851
|
tag: tag
|
|
10959
|
-
}),
|
|
11852
|
+
}), settled = await cascadeAndReload({
|
|
10960
11853
|
client: client,
|
|
10961
11854
|
tag: tag,
|
|
10962
11855
|
instanceId: instanceId,
|
|
@@ -10968,11 +11861,10 @@ async function runDeduped(args) {
|
|
|
10968
11861
|
executionContext: executionContext,
|
|
10969
11862
|
telemetry: telemetry
|
|
10970
11863
|
});
|
|
10971
|
-
return {
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
};
|
|
11864
|
+
return settledResult({
|
|
11865
|
+
...settled,
|
|
11866
|
+
changed: settled.instance._rev !== pre._rev
|
|
11867
|
+
});
|
|
10976
11868
|
};
|
|
10977
11869
|
if (record !== void 0 && before !== void 0 && findProcessedRequest({
|
|
10978
11870
|
instance: before,
|
|
@@ -10988,7 +11880,7 @@ async function runDeduped(args) {
|
|
|
10988
11880
|
}
|
|
10989
11881
|
|
|
10990
11882
|
async function cascade({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
|
|
10991
|
-
const
|
|
11883
|
+
const settled = await cascadeAutoTransitions({
|
|
10992
11884
|
client: client,
|
|
10993
11885
|
instanceId: instanceId,
|
|
10994
11886
|
actor: actor,
|
|
@@ -11024,13 +11916,13 @@ async function cascade({client: client, instanceId: instanceId, actor: actor, cl
|
|
|
11024
11916
|
...telemetry !== void 0 ? {
|
|
11025
11917
|
telemetry: telemetry
|
|
11026
11918
|
} : {}
|
|
11027
|
-
}),
|
|
11919
|
+
}), settled;
|
|
11028
11920
|
}
|
|
11029
11921
|
|
|
11030
11922
|
async function cascadeAndReload(args) {
|
|
11031
11923
|
const {client: client, tag: tag, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock} = args;
|
|
11032
11924
|
return {
|
|
11033
|
-
|
|
11925
|
+
...await cascade({
|
|
11034
11926
|
client: client,
|
|
11035
11927
|
instanceId: instanceId,
|
|
11036
11928
|
actor: actor,
|
|
@@ -11053,6 +11945,84 @@ async function cascadeAndReload(args) {
|
|
|
11053
11945
|
};
|
|
11054
11946
|
}
|
|
11055
11947
|
|
|
11948
|
+
async function unchangedNextEvaluationAt(args) {
|
|
11949
|
+
const {client: client, instance: instance, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, now: now} = args;
|
|
11950
|
+
if (terminalState(instance) !== "in-flight") return;
|
|
11951
|
+
const ctx = await buildEngineContext({
|
|
11952
|
+
client: client,
|
|
11953
|
+
instance: instance,
|
|
11954
|
+
definition: parseDefinitionSnapshot(instance),
|
|
11955
|
+
clientForGdr: clientForGdr,
|
|
11956
|
+
refSurface: refSurface,
|
|
11957
|
+
memberRolesLoader: memberRolesLoader,
|
|
11958
|
+
clock: () => now,
|
|
11959
|
+
...actor !== void 0 ? {
|
|
11960
|
+
actor: actor
|
|
11961
|
+
} : {},
|
|
11962
|
+
...args.executionContext !== void 0 ? {
|
|
11963
|
+
executionContext: args.executionContext
|
|
11964
|
+
} : {},
|
|
11965
|
+
...args.telemetry !== void 0 ? {
|
|
11966
|
+
telemetry: args.telemetry
|
|
11967
|
+
} : {}
|
|
11968
|
+
});
|
|
11969
|
+
return ctxNextEvaluationAt(ctx);
|
|
11970
|
+
}
|
|
11971
|
+
|
|
11972
|
+
async function adminOverrideResult(args) {
|
|
11973
|
+
const {client: client, tag: tag, instanceId: instanceId, fired: fired, now: now, executionContext: executionContext, telemetry: telemetry, ...scope} = args, optional = {
|
|
11974
|
+
...executionContext !== void 0 ? {
|
|
11975
|
+
executionContext: executionContext
|
|
11976
|
+
} : {},
|
|
11977
|
+
...telemetry !== void 0 ? {
|
|
11978
|
+
telemetry: telemetry
|
|
11979
|
+
} : {}
|
|
11980
|
+
}, settled = fired ? await cascade({
|
|
11981
|
+
client: client,
|
|
11982
|
+
instanceId: instanceId,
|
|
11983
|
+
...scope,
|
|
11984
|
+
...optional
|
|
11985
|
+
}) : {
|
|
11986
|
+
cascaded: 0
|
|
11987
|
+
}, instance = await reload({
|
|
11988
|
+
client: client,
|
|
11989
|
+
instanceId: instanceId,
|
|
11990
|
+
tag: tag
|
|
11991
|
+
});
|
|
11992
|
+
return settledResult({
|
|
11993
|
+
...settled,
|
|
11994
|
+
instance: instance,
|
|
11995
|
+
changed: fired,
|
|
11996
|
+
...fired ? {} : {
|
|
11997
|
+
nextEvaluationAt: await unchangedNextEvaluationAt({
|
|
11998
|
+
client: client,
|
|
11999
|
+
instance: instance,
|
|
12000
|
+
now: now,
|
|
12001
|
+
actor: scope.actor,
|
|
12002
|
+
clientForGdr: scope.clientForGdr,
|
|
12003
|
+
refSurface: scope.refSurface,
|
|
12004
|
+
memberRolesLoader: scope.memberRolesLoader,
|
|
12005
|
+
...optional
|
|
12006
|
+
})
|
|
12007
|
+
}
|
|
12008
|
+
});
|
|
12009
|
+
}
|
|
12010
|
+
|
|
12011
|
+
function settledResult(args) {
|
|
12012
|
+
const {instance: instance, cascaded: cascaded, changed: changed, ranOps: ranOps, nextEvaluationAt: nextEvaluationAt} = args;
|
|
12013
|
+
return {
|
|
12014
|
+
instance: instance,
|
|
12015
|
+
cascaded: cascaded,
|
|
12016
|
+
changed: changed,
|
|
12017
|
+
...ranOps !== void 0 ? {
|
|
12018
|
+
ranOps: ranOps
|
|
12019
|
+
} : {},
|
|
12020
|
+
...nextEvaluationAt !== void 0 ? {
|
|
12021
|
+
nextEvaluationAt: nextEvaluationAt
|
|
12022
|
+
} : {}
|
|
12023
|
+
};
|
|
12024
|
+
}
|
|
12025
|
+
|
|
11056
12026
|
async function settleStart(args) {
|
|
11057
12027
|
const runArgs = {
|
|
11058
12028
|
client: args.client,
|
|
@@ -11114,7 +12084,7 @@ async function resumeStart(args) {
|
|
|
11114
12084
|
instance: existing,
|
|
11115
12085
|
initialFieldCount: initialFieldCount,
|
|
11116
12086
|
viaSpawn: !1
|
|
11117
|
-
})),
|
|
12087
|
+
})), settled = await settleStart({
|
|
11118
12088
|
...settlementArgs,
|
|
11119
12089
|
instanceId: existing._id,
|
|
11120
12090
|
...completesStart ? {
|
|
@@ -11125,11 +12095,11 @@ async function resumeStart(args) {
|
|
|
11125
12095
|
instanceId: existing._id,
|
|
11126
12096
|
tag: args.tag
|
|
11127
12097
|
});
|
|
11128
|
-
return {
|
|
12098
|
+
return settledResult({
|
|
12099
|
+
...settled,
|
|
11129
12100
|
instance: instance,
|
|
11130
|
-
cascaded: cascaded,
|
|
11131
12101
|
changed: instance._rev !== existing._rev
|
|
11132
|
-
};
|
|
12102
|
+
});
|
|
11133
12103
|
}
|
|
11134
12104
|
|
|
11135
12105
|
function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, executionContext: executionContext, telemetry: telemetry}) {
|
|
@@ -11228,7 +12198,7 @@ async function dispatchGatedWrite(args) {
|
|
|
11228
12198
|
...resourceClients !== void 0 ? {
|
|
11229
12199
|
resourceClients: resourceClients
|
|
11230
12200
|
} : {}
|
|
11231
|
-
}), ranOps = await apply(args.before, evaluation),
|
|
12201
|
+
}), ranOps = await apply(args.before, evaluation), settled = await cascadeAndReload({
|
|
11232
12202
|
client: client,
|
|
11233
12203
|
tag: tag,
|
|
11234
12204
|
instanceId: instanceId,
|
|
@@ -11240,14 +12210,13 @@ async function dispatchGatedWrite(args) {
|
|
|
11240
12210
|
executionContext: args.executionContext,
|
|
11241
12211
|
telemetry: args.telemetry
|
|
11242
12212
|
});
|
|
11243
|
-
return {
|
|
11244
|
-
|
|
11245
|
-
cascaded: cascaded,
|
|
12213
|
+
return settledResult({
|
|
12214
|
+
...settled,
|
|
11246
12215
|
changed: !0,
|
|
11247
12216
|
...ranOps !== void 0 ? {
|
|
11248
12217
|
ranOps: ranOps
|
|
11249
12218
|
} : {}
|
|
11250
|
-
};
|
|
12219
|
+
});
|
|
11251
12220
|
}
|
|
11252
12221
|
|
|
11253
12222
|
function guardDeniedError(instanceId, reason) {
|
|
@@ -11461,6 +12430,10 @@ async function abortInstances(args) {
|
|
|
11461
12430
|
return aborted;
|
|
11462
12431
|
}
|
|
11463
12432
|
|
|
12433
|
+
function lintDeadActivityInputSeeds(definition) {
|
|
12434
|
+
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.`)));
|
|
12435
|
+
}
|
|
12436
|
+
|
|
11464
12437
|
function projectStartSliceRow(instance) {
|
|
11465
12438
|
const subject = (instance.fields ?? []).find(field => field._type === "subject")?.value;
|
|
11466
12439
|
return {
|
|
@@ -11488,14 +12461,18 @@ const workflow = {
|
|
|
11488
12461
|
definitions.forEach(validateDefinition), assertReaderModelAcknowledgement(args.expectedMinReaderModel, {
|
|
11489
12462
|
requiredMinReaderModel: requiredDefinitionReaderModel(definitions)
|
|
11490
12463
|
});
|
|
11491
|
-
const
|
|
12464
|
+
const roleWarnings = await validateDefinitionRoles({
|
|
12465
|
+
client: client,
|
|
12466
|
+
definitions: definitions,
|
|
12467
|
+
workflowResource: workflowResource
|
|
12468
|
+
}), ordered = await sortByDependencies({
|
|
11492
12469
|
client: client,
|
|
11493
12470
|
definitions: definitions,
|
|
11494
12471
|
tag: tag
|
|
11495
12472
|
}), results = [], deployed = [], tx = client.transaction();
|
|
11496
12473
|
let hasWrites = !1;
|
|
11497
12474
|
for (const def of ordered) {
|
|
11498
|
-
const lint = lintEffectOutputs(def), warnings = lint.length > 0 ? {
|
|
12475
|
+
const lint = [ ...lintEffectOutputs(def), ...lintDeadActivityInputSeeds(def), ...roleWarnings.get(def.name) ?? [] ], warnings = lint.length > 0 ? {
|
|
11499
12476
|
warnings: lint
|
|
11500
12477
|
} : {}, latest = await loadLatestDeployed({
|
|
11501
12478
|
client: client,
|
|
@@ -11588,12 +12565,27 @@ const workflow = {
|
|
|
11588
12565
|
return runCommitVerb({
|
|
11589
12566
|
args: args,
|
|
11590
12567
|
op: "fireAction",
|
|
11591
|
-
run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
11592
|
-
if (findCurrentActivityEntry(before, activity) === void 0 && idempotent === !0) return {
|
|
12568
|
+
run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
12569
|
+
if (findCurrentActivityEntry(before, activity) === void 0 && idempotent === !0) return settledResult({
|
|
11593
12570
|
instance: before,
|
|
11594
12571
|
cascaded: 0,
|
|
11595
|
-
changed: !1
|
|
11596
|
-
|
|
12572
|
+
changed: !1,
|
|
12573
|
+
nextEvaluationAt: await unchangedNextEvaluationAt({
|
|
12574
|
+
client: client,
|
|
12575
|
+
instance: before,
|
|
12576
|
+
actor: actor,
|
|
12577
|
+
clientForGdr: clientForGdr,
|
|
12578
|
+
refSurface: refSurface,
|
|
12579
|
+
memberRolesLoader: memberRolesLoader,
|
|
12580
|
+
now: now,
|
|
12581
|
+
...executionContext !== void 0 ? {
|
|
12582
|
+
executionContext: executionContext
|
|
12583
|
+
} : {},
|
|
12584
|
+
...args.telemetry !== void 0 ? {
|
|
12585
|
+
telemetry: args.telemetry
|
|
12586
|
+
} : {}
|
|
12587
|
+
})
|
|
12588
|
+
});
|
|
11597
12589
|
const result = await dispatchGatedWrite({
|
|
11598
12590
|
client: client,
|
|
11599
12591
|
tag: tag,
|
|
@@ -11730,7 +12722,7 @@ const workflow = {
|
|
|
11730
12722
|
});
|
|
11731
12723
|
},
|
|
11732
12724
|
completeEffect: async rawArgs => {
|
|
11733
|
-
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({
|
|
12725
|
+
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({
|
|
11734
12726
|
idempotencyKey: args.idempotencyKey,
|
|
11735
12727
|
op: "completeEffect",
|
|
11736
12728
|
idempotencyTtlMs: args.idempotencyTtlMs
|
|
@@ -11740,7 +12732,7 @@ const workflow = {
|
|
|
11740
12732
|
tag: tag,
|
|
11741
12733
|
instanceId: instanceId,
|
|
11742
12734
|
record: record,
|
|
11743
|
-
now:
|
|
12735
|
+
now: now,
|
|
11744
12736
|
...operationContext,
|
|
11745
12737
|
clock: clock,
|
|
11746
12738
|
executionContext: executionContext,
|
|
@@ -11775,7 +12767,7 @@ const workflow = {
|
|
|
11775
12767
|
executionContext: executionContext,
|
|
11776
12768
|
telemetry: args.telemetry
|
|
11777
12769
|
})
|
|
11778
|
-
}),
|
|
12770
|
+
}), settled = await cascadeAndReload({
|
|
11779
12771
|
client: client,
|
|
11780
12772
|
tag: tag,
|
|
11781
12773
|
instanceId: instanceId,
|
|
@@ -11785,22 +12777,21 @@ const workflow = {
|
|
|
11785
12777
|
telemetry: args.telemetry
|
|
11786
12778
|
});
|
|
11787
12779
|
return resolveTelemetry(args.telemetry).log(WorkflowEffectCompleted, {
|
|
11788
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12780
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11789
12781
|
instanceId: instanceId,
|
|
11790
12782
|
effect: completion.effect,
|
|
11791
12783
|
status: status,
|
|
11792
12784
|
origin: completion.origin,
|
|
11793
|
-
cascaded: cascaded
|
|
11794
|
-
}), {
|
|
11795
|
-
|
|
11796
|
-
cascaded: cascaded,
|
|
12785
|
+
cascaded: settled.cascaded
|
|
12786
|
+
}), settledResult({
|
|
12787
|
+
...settled,
|
|
11797
12788
|
changed: !0
|
|
11798
|
-
};
|
|
12789
|
+
});
|
|
11799
12790
|
}
|
|
11800
12791
|
});
|
|
11801
12792
|
},
|
|
11802
12793
|
commitEffectOps: async rawArgs => {
|
|
11803
|
-
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({
|
|
12794
|
+
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({
|
|
11804
12795
|
idempotencyKey: args.idempotencyKey,
|
|
11805
12796
|
op: "commitEffectOps",
|
|
11806
12797
|
idempotencyTtlMs: args.idempotencyTtlMs
|
|
@@ -11811,7 +12802,7 @@ const workflow = {
|
|
|
11811
12802
|
tag: tag,
|
|
11812
12803
|
instanceId: instanceId,
|
|
11813
12804
|
record: record,
|
|
11814
|
-
now:
|
|
12805
|
+
now: now,
|
|
11815
12806
|
...operationContext,
|
|
11816
12807
|
clock: clock,
|
|
11817
12808
|
executionContext: executionContext,
|
|
@@ -11831,7 +12822,7 @@ const workflow = {
|
|
|
11831
12822
|
executionContext: executionContext,
|
|
11832
12823
|
telemetry: args.telemetry
|
|
11833
12824
|
})
|
|
11834
|
-
}),
|
|
12825
|
+
}), settled = await cascadeAndReload({
|
|
11835
12826
|
client: client,
|
|
11836
12827
|
tag: tag,
|
|
11837
12828
|
instanceId: instanceId,
|
|
@@ -11841,15 +12832,14 @@ const workflow = {
|
|
|
11841
12832
|
telemetry: args.telemetry
|
|
11842
12833
|
});
|
|
11843
12834
|
return resolveTelemetry(args.telemetry).log(WorkflowEffectStateReported, {
|
|
11844
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12835
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11845
12836
|
instanceId: instanceId,
|
|
11846
12837
|
effect: report.effect,
|
|
11847
|
-
cascaded: cascaded
|
|
11848
|
-
}), {
|
|
11849
|
-
|
|
11850
|
-
cascaded: cascaded,
|
|
12838
|
+
cascaded: settled.cascaded
|
|
12839
|
+
}), settledResult({
|
|
12840
|
+
...settled,
|
|
11851
12841
|
changed: !0
|
|
11852
|
-
};
|
|
12842
|
+
});
|
|
11853
12843
|
}
|
|
11854
12844
|
});
|
|
11855
12845
|
},
|
|
@@ -11862,9 +12852,10 @@ const workflow = {
|
|
|
11862
12852
|
await assertInstanceWriteAllowed({
|
|
11863
12853
|
instance: current,
|
|
11864
12854
|
guards: guards,
|
|
11865
|
-
identity: lakePrincipalId(access)
|
|
12855
|
+
identity: lakePrincipalId(access),
|
|
12856
|
+
dereference: clientGuardDereference(client)
|
|
11866
12857
|
});
|
|
11867
|
-
const
|
|
12858
|
+
const settled = await cascadeAndReload({
|
|
11868
12859
|
client: client,
|
|
11869
12860
|
tag: tag,
|
|
11870
12861
|
instanceId: instanceId,
|
|
@@ -11874,21 +12865,20 @@ const workflow = {
|
|
|
11874
12865
|
telemetry: args.telemetry
|
|
11875
12866
|
});
|
|
11876
12867
|
return resolveTelemetry(args.telemetry).log(WorkflowInstanceTicked, {
|
|
11877
|
-
...definitionHashFragment(instance.pinnedContentHash),
|
|
12868
|
+
...definitionHashFragment(settled.instance.pinnedContentHash),
|
|
11878
12869
|
instanceId: instanceId,
|
|
11879
|
-
cascaded: cascaded
|
|
11880
|
-
}), {
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
};
|
|
12870
|
+
cascaded: settled.cascaded
|
|
12871
|
+
}), settledResult({
|
|
12872
|
+
...settled,
|
|
12873
|
+
changed: settled.instance._rev !== current._rev
|
|
12874
|
+
});
|
|
11885
12875
|
},
|
|
11886
12876
|
setStage: async rawArgs => {
|
|
11887
12877
|
const args = taggedScope(rawArgs, REQUEST_TAG.setStage), {client: client, tag: tag, instanceId: instanceId, targetStage: targetStage, reason: reason, executionContext: executionContext} = args;
|
|
11888
12878
|
return runCommitVerb({
|
|
11889
12879
|
args: args,
|
|
11890
12880
|
op: "setStage",
|
|
11891
|
-
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
12881
|
+
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
11892
12882
|
const result = await setStage({
|
|
11893
12883
|
client: client,
|
|
11894
12884
|
instanceId: instanceId,
|
|
@@ -11908,34 +12898,29 @@ const workflow = {
|
|
|
11908
12898
|
executionContext: executionContext,
|
|
11909
12899
|
telemetry: args.telemetry
|
|
11910
12900
|
})
|
|
11911
|
-
})
|
|
12901
|
+
});
|
|
12902
|
+
return resolveTelemetry(args.telemetry).log(WorkflowStageSet, {
|
|
12903
|
+
...definitionHashFragment(before.pinnedContentHash),
|
|
12904
|
+
instanceId: instanceId,
|
|
12905
|
+
changed: result.fired
|
|
12906
|
+
}), adminOverrideResult({
|
|
11912
12907
|
client: client,
|
|
12908
|
+
tag: tag,
|
|
11913
12909
|
instanceId: instanceId,
|
|
12910
|
+
fired: result.fired,
|
|
11914
12911
|
actor: actor,
|
|
11915
12912
|
clientForGdr: clientForGdr,
|
|
11916
12913
|
refSurface: refSurface,
|
|
11917
12914
|
memberRolesLoader: memberRolesLoader,
|
|
11918
12915
|
clock: clock,
|
|
12916
|
+
now: now,
|
|
11919
12917
|
...executionContext !== void 0 ? {
|
|
11920
12918
|
executionContext: executionContext
|
|
11921
12919
|
} : {},
|
|
11922
12920
|
...args.telemetry !== void 0 ? {
|
|
11923
12921
|
telemetry: args.telemetry
|
|
11924
12922
|
} : {}
|
|
11925
|
-
})
|
|
11926
|
-
return resolveTelemetry(args.telemetry).log(WorkflowStageSet, {
|
|
11927
|
-
...definitionHashFragment(before.pinnedContentHash),
|
|
11928
|
-
instanceId: instanceId,
|
|
11929
|
-
changed: result.fired
|
|
11930
|
-
}), {
|
|
11931
|
-
instance: await reload({
|
|
11932
|
-
client: client,
|
|
11933
|
-
instanceId: instanceId,
|
|
11934
|
-
tag: tag
|
|
11935
|
-
}),
|
|
11936
|
-
cascaded: cascaded,
|
|
11937
|
-
changed: result.fired
|
|
11938
|
-
};
|
|
12923
|
+
});
|
|
11939
12924
|
}
|
|
11940
12925
|
});
|
|
11941
12926
|
},
|
|
@@ -11968,7 +12953,7 @@ const workflow = {
|
|
|
11968
12953
|
...definitionHashFragment(before.pinnedContentHash),
|
|
11969
12954
|
instanceId: instanceId,
|
|
11970
12955
|
changed: changed
|
|
11971
|
-
}), {
|
|
12956
|
+
}), settledResult({
|
|
11972
12957
|
instance: await reload({
|
|
11973
12958
|
client: client,
|
|
11974
12959
|
instanceId: instanceId,
|
|
@@ -11976,7 +12961,7 @@ const workflow = {
|
|
|
11976
12961
|
}),
|
|
11977
12962
|
cascaded: 0,
|
|
11978
12963
|
changed: changed
|
|
11979
|
-
};
|
|
12964
|
+
});
|
|
11980
12965
|
}
|
|
11981
12966
|
});
|
|
11982
12967
|
},
|
|
@@ -11986,7 +12971,7 @@ const workflow = {
|
|
|
11986
12971
|
return runCommitVerb({
|
|
11987
12972
|
args: args,
|
|
11988
12973
|
op: "resetActivity",
|
|
11989
|
-
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
|
|
12974
|
+
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, now: now, record: record, before: before}) => {
|
|
11990
12975
|
const result = await resetActivity({
|
|
11991
12976
|
client: client,
|
|
11992
12977
|
instanceId: instanceId,
|
|
@@ -12004,34 +12989,29 @@ const workflow = {
|
|
|
12004
12989
|
executionContext: executionContext,
|
|
12005
12990
|
telemetry: args.telemetry
|
|
12006
12991
|
})
|
|
12007
|
-
})
|
|
12992
|
+
});
|
|
12993
|
+
return resolveTelemetry(args.telemetry).log(WorkflowActivityReset, {
|
|
12994
|
+
...definitionHashFragment(before.pinnedContentHash),
|
|
12995
|
+
instanceId: instanceId,
|
|
12996
|
+
changed: result.fired
|
|
12997
|
+
}), adminOverrideResult({
|
|
12008
12998
|
client: client,
|
|
12999
|
+
tag: tag,
|
|
12009
13000
|
instanceId: instanceId,
|
|
13001
|
+
fired: result.fired,
|
|
12010
13002
|
actor: actor,
|
|
12011
13003
|
clientForGdr: clientForGdr,
|
|
12012
13004
|
refSurface: refSurface,
|
|
12013
13005
|
memberRolesLoader: memberRolesLoader,
|
|
12014
13006
|
clock: clock,
|
|
13007
|
+
now: now,
|
|
12015
13008
|
...executionContext !== void 0 ? {
|
|
12016
13009
|
executionContext: executionContext
|
|
12017
13010
|
} : {},
|
|
12018
13011
|
...args.telemetry !== void 0 ? {
|
|
12019
13012
|
telemetry: args.telemetry
|
|
12020
13013
|
} : {}
|
|
12021
|
-
})
|
|
12022
|
-
return resolveTelemetry(args.telemetry).log(WorkflowActivityReset, {
|
|
12023
|
-
...definitionHashFragment(before.pinnedContentHash),
|
|
12024
|
-
instanceId: instanceId,
|
|
12025
|
-
changed: result.fired
|
|
12026
|
-
}), {
|
|
12027
|
-
instance: await reload({
|
|
12028
|
-
client: client,
|
|
12029
|
-
instanceId: instanceId,
|
|
12030
|
-
tag: tag
|
|
12031
|
-
}),
|
|
12032
|
-
cascaded: cascaded,
|
|
12033
|
-
changed: result.fired
|
|
12034
|
-
};
|
|
13014
|
+
});
|
|
12035
13015
|
}
|
|
12036
13016
|
});
|
|
12037
13017
|
},
|
|
@@ -12364,8 +13344,8 @@ async function startFreshInstance(args) {
|
|
|
12364
13344
|
extraHistory: fieldDiscards
|
|
12365
13345
|
} : {}
|
|
12366
13346
|
});
|
|
12367
|
-
await client.create(base, SYNC_COMMIT);
|
|
12368
|
-
const
|
|
13347
|
+
await client.create(instanceDocumentForWrite(base), SYNC_COMMIT);
|
|
13348
|
+
const settled = await settleStart({
|
|
12369
13349
|
client: client,
|
|
12370
13350
|
tag: tag,
|
|
12371
13351
|
instanceId: id,
|
|
@@ -12387,15 +13367,15 @@ async function startFreshInstance(args) {
|
|
|
12387
13367
|
viaSpawn: !1
|
|
12388
13368
|
}))
|
|
12389
13369
|
});
|
|
12390
|
-
return {
|
|
13370
|
+
return settledResult({
|
|
13371
|
+
...settled,
|
|
12391
13372
|
instance: await reload({
|
|
12392
13373
|
client: client,
|
|
12393
13374
|
instanceId: id,
|
|
12394
13375
|
tag: tag
|
|
12395
13376
|
}),
|
|
12396
|
-
cascaded: cascaded,
|
|
12397
13377
|
changed: !0
|
|
12398
|
-
};
|
|
13378
|
+
});
|
|
12399
13379
|
}
|
|
12400
13380
|
|
|
12401
13381
|
function assertInitialStageExists(definition) {
|
|
@@ -12570,7 +13550,7 @@ function missingHandlerMessage(info) {
|
|
|
12570
13550
|
}
|
|
12571
13551
|
|
|
12572
13552
|
async function verifyDeployedDefinitionsInternal(args) {
|
|
12573
|
-
const {tag: tag,
|
|
13553
|
+
const {tag: tag, handlers: handlers, missingHandler: missingHandler, logger: logger} = args, client = withRequestTag(args.client, REQUEST_TAG.verifyDefinitions);
|
|
12574
13554
|
validateTag(tag);
|
|
12575
13555
|
const log = logger("verifyDeployedDefinitions"), definitions = (await client.fetch(definitionsListGroq("asc"), {
|
|
12576
13556
|
tag: tag
|
|
@@ -12580,7 +13560,7 @@ async function verifyDeployedDefinitionsInternal(args) {
|
|
|
12580
13560
|
version: def.version,
|
|
12581
13561
|
_id: def._id
|
|
12582
13562
|
}), walkEffectNames(def, (name, location) => {
|
|
12583
|
-
if (
|
|
13563
|
+
if (handlers[name] !== void 0) return;
|
|
12584
13564
|
const key = `${name}@@${def._id}`;
|
|
12585
13565
|
let bucket = missingByName.get(key);
|
|
12586
13566
|
bucket === void 0 && (bucket = {
|
|
@@ -12639,7 +13619,7 @@ function isCancelledCompletion(data) {
|
|
|
12639
13619
|
}
|
|
12640
13620
|
|
|
12641
13621
|
async function drainEffectsInternal(args) {
|
|
12642
|
-
const {tag: tag, workflowResource: workflowResource, instanceId: instanceId,
|
|
13622
|
+
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({
|
|
12643
13623
|
client: handlerClient,
|
|
12644
13624
|
workflowResource: workflowResource,
|
|
12645
13625
|
resourceClients: handlerResourceClients
|
|
@@ -12659,7 +13639,7 @@ async function drainEffectsInternal(args) {
|
|
|
12659
13639
|
resourceClients: resourceClients
|
|
12660
13640
|
} : {},
|
|
12661
13641
|
instanceId: instanceId,
|
|
12662
|
-
|
|
13642
|
+
handlers: handlers,
|
|
12663
13643
|
missingHandler: missingHandler,
|
|
12664
13644
|
logger: logger,
|
|
12665
13645
|
log: log,
|
|
@@ -12691,7 +13671,7 @@ async function drainOneCandidate(pass) {
|
|
|
12691
13671
|
skippedKeys: skippedKeys
|
|
12692
13672
|
});
|
|
12693
13673
|
if (candidate === void 0) return !1;
|
|
12694
|
-
const handler = pass.
|
|
13674
|
+
const handler = pass.handlers[candidate.name];
|
|
12695
13675
|
if (handler === void 0) return await assertSkippableOrThrow({
|
|
12696
13676
|
missingHandler: pass.missingHandler,
|
|
12697
13677
|
candidate: candidate,
|
|
@@ -13100,6 +14080,7 @@ function createInstanceSession(args) {
|
|
|
13100
14080
|
snapshot: snapshotFrom(held, normalizedSelf),
|
|
13101
14081
|
guards: guards,
|
|
13102
14082
|
resourceGrants: resourceGrants,
|
|
14083
|
+
guardDereference: clientGuardDereference(evalScope.client),
|
|
13103
14084
|
...localPrincipalId !== void 0 ? {
|
|
13104
14085
|
localPrincipalId: localPrincipalId
|
|
13105
14086
|
} : {},
|
|
@@ -13114,7 +14095,7 @@ function createInstanceSession(args) {
|
|
|
13114
14095
|
} : {}
|
|
13115
14096
|
});
|
|
13116
14097
|
}, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope, memberRolesLoader: memberRolesLoader}) => {
|
|
13117
|
-
const
|
|
14098
|
+
const settled = await cascadeHeld({
|
|
13118
14099
|
scope: scope,
|
|
13119
14100
|
actor: actor,
|
|
13120
14101
|
held: held,
|
|
@@ -13124,14 +14105,14 @@ function createInstanceSession(args) {
|
|
|
13124
14105
|
client: scope.client,
|
|
13125
14106
|
instanceId: instance._id,
|
|
13126
14107
|
tag: tag
|
|
13127
|
-
}), {
|
|
14108
|
+
}), settledResult({
|
|
14109
|
+
...settled,
|
|
13128
14110
|
instance: instance,
|
|
13129
|
-
cascaded: cascaded,
|
|
13130
14111
|
changed: !0,
|
|
13131
14112
|
...ranOps !== void 0 ? {
|
|
13132
14113
|
ranOps: ranOps
|
|
13133
14114
|
} : {}
|
|
13134
|
-
};
|
|
14115
|
+
});
|
|
13135
14116
|
}, cascadeHeld = ({scope: scope, actor: actor, held: held, memberRolesLoader: memberRolesLoader}) => cascade({
|
|
13136
14117
|
client: scope.client,
|
|
13137
14118
|
instanceId: instance._id,
|
|
@@ -13242,13 +14223,14 @@ function createInstanceSession(args) {
|
|
|
13242
14223
|
identity: lakePrincipalId({
|
|
13243
14224
|
actor: actor,
|
|
13244
14225
|
localPrincipalId: localPrincipalId
|
|
13245
|
-
})
|
|
14226
|
+
}),
|
|
14227
|
+
dereference: clientGuardDereference(tickScope.client)
|
|
13246
14228
|
});
|
|
13247
14229
|
const before = await reload({
|
|
13248
14230
|
client: tickScope.client,
|
|
13249
14231
|
instanceId: instance._id,
|
|
13250
14232
|
tag: tag
|
|
13251
|
-
}),
|
|
14233
|
+
}), settled = await cascadeHeld({
|
|
13252
14234
|
scope: tickScope,
|
|
13253
14235
|
actor: actor,
|
|
13254
14236
|
held: held,
|
|
@@ -13261,12 +14243,12 @@ function createInstanceSession(args) {
|
|
|
13261
14243
|
}), telemetry.log(WorkflowInstanceTicked, {
|
|
13262
14244
|
...definitionHashFragment(instance.pinnedContentHash),
|
|
13263
14245
|
instanceId: instance._id,
|
|
13264
|
-
cascaded: cascaded
|
|
13265
|
-
}), {
|
|
14246
|
+
cascaded: settled.cascaded
|
|
14247
|
+
}), settledResult({
|
|
14248
|
+
...settled,
|
|
13266
14249
|
instance: instance,
|
|
13267
|
-
cascaded: cascaded,
|
|
13268
14250
|
changed: instance._rev !== before._rev
|
|
13269
|
-
};
|
|
14251
|
+
});
|
|
13270
14252
|
});
|
|
13271
14253
|
},
|
|
13272
14254
|
fireAction({activity: activity, action: action, params: params}) {
|
|
@@ -13416,7 +14398,10 @@ const silentLogger = {
|
|
|
13416
14398
|
function createEngine(args) {
|
|
13417
14399
|
const {workflowResource: workflowResource, clock: clock, tag: tag, executionContext: executionContext} = args, {client: client, resourceClients: resourceClients} = taggedScope(args, REQUEST_TAG.engine);
|
|
13418
14400
|
validateTag(tag);
|
|
13419
|
-
const
|
|
14401
|
+
const effects = {
|
|
14402
|
+
handlers: args.effects?.handlers ?? {},
|
|
14403
|
+
missingHandler: args.effects?.missingHandler ?? "fail"
|
|
14404
|
+
}, logger = args.loggerFactory ?? defaultLoggerFactory, telemetry = resolveTelemetry(args.telemetry), EMPTY_DRAIN_LOG_INTERVAL_MS = 6e4;
|
|
13420
14405
|
let lastEmptyDrainLoggedAt;
|
|
13421
14406
|
const emptyDrainDue = () => {
|
|
13422
14407
|
const now = Date.parse((clock ?? wallClock)());
|
|
@@ -13447,8 +14432,7 @@ function createEngine(args) {
|
|
|
13447
14432
|
client: client,
|
|
13448
14433
|
tag: tag,
|
|
13449
14434
|
workflowResource: workflowResource,
|
|
13450
|
-
|
|
13451
|
-
missingHandler: missingHandler,
|
|
14435
|
+
effects: effects,
|
|
13452
14436
|
logger: logger,
|
|
13453
14437
|
telemetry: telemetry,
|
|
13454
14438
|
resolveActor: rest => resolveClientActor(client, rest),
|
|
@@ -13502,12 +14486,11 @@ function createEngine(args) {
|
|
|
13502
14486
|
workflowResource: workflowResource,
|
|
13503
14487
|
...optionalScope,
|
|
13504
14488
|
instanceId: instanceId,
|
|
13505
|
-
|
|
13506
|
-
missingHandler: missingHandler,
|
|
14489
|
+
...effects,
|
|
13507
14490
|
logger: logger,
|
|
13508
14491
|
telemetry: telemetry,
|
|
13509
|
-
...args.
|
|
13510
|
-
leaseMs: args.
|
|
14492
|
+
...args.effects?.leaseMs !== void 0 ? {
|
|
14493
|
+
leaseMs: args.effects.leaseMs
|
|
13511
14494
|
} : {}
|
|
13512
14495
|
}), drained = result.drained;
|
|
13513
14496
|
return (drained.length > 0 || emptyDrainDue()) && telemetry.log(WorkflowEffectsDrained, {
|
|
@@ -13520,8 +14503,7 @@ function createEngine(args) {
|
|
|
13520
14503
|
verifyDeployedDefinitions: () => verifyDeployedDefinitionsInternal({
|
|
13521
14504
|
client: client,
|
|
13522
14505
|
tag: tag,
|
|
13523
|
-
|
|
13524
|
-
missingHandler: missingHandler,
|
|
14506
|
+
...effects,
|
|
13525
14507
|
logger: logger
|
|
13526
14508
|
})
|
|
13527
14509
|
};
|
|
@@ -14060,4 +15042,4 @@ function displayDescription(typeKey) {
|
|
|
14060
15042
|
if (typeKey) return DISPLAY[typeKey]?.description;
|
|
14061
15043
|
}
|
|
14062
15044
|
|
|
14063
|
-
export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MAX_READER, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DECISION_SEMANTICS, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstancePreviewSchema, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, actorFulfillsRole, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory,
|
|
15045
|
+
export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCascadeError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MAX_READER, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DECISION_SEMANTICS, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DOCUMENT_VALUE_PERMISSIONS, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstancePreviewSchema, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activeAssignmentMembers, activityAutonomyOf, actorFulfillsRole, actorMatchesAssignment, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, assignmentMatch, assignmentMembers, assignmentPrefilter, assignmentState, assignmentStateCounts, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientGuardDereference, clientProjectUserDirectory, compileGuards, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionRoleNames, definitionTagsGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deployedTagsGroq, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, documentStuckCause, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findActivityNode, findCurrentActivityEntry, findOpenStageEntry, findStageNode, formatRead2 as formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, identityMatchesAssignment, inFlightFilter, initialFieldIssues, instanceAssignmentStateCounts, instanceChangesQuery, instanceDocId, instanceGuardQuery, instancePreviewsQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isRevisionConflict, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, openActivityAssignments, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseInstancePreviewDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readInstancePreviewDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredDefinitionReaderModel, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resolveUserAttributes, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, snapshotGuardDereference, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, userLoginProvider, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
|