@sanity/workflow-engine 0.20.0 → 0.21.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 +93 -0
- package/DATAMODEL.md +168 -0
- package/dist/_chunks-cjs/invariants.cjs +223 -82
- package/dist/_chunks-es/invariants.js +213 -78
- package/dist/define.d.cts +38 -14
- package/dist/define.d.ts +38 -14
- package/dist/index.cjs +1717 -864
- package/dist/index.d.cts +434 -170
- package/dist/index.d.ts +434 -170
- package/dist/index.js +1698 -863
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { terminalState, andConditions, deriveActivityKind, parseDefinitionSnapshot, CALLER_BOUND_VARS,
|
|
1
|
+
import { terminalState, andConditions, deriveActivityKind, parseDefinitionSnapshot, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, rethrowWithContext, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, parentRef, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, evaluateCondition, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, WORKFLOW_INSTANCE_TYPE, parseGdr, isGdrUri, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, classifyPrincipalId, assertReadableModel, InstanceNotFoundError, modelStampFor, evaluateConditionOutcome, runGroq, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, minReaderModelOf, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, lakePrincipalId, driverKind, EffectNotFoundError, deriveExecutorClassification, validateTag, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, isUnprimed, DefinitionInUseError, assertReaderModelAcknowledgement, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
|
|
2
2
|
|
|
3
|
-
import { ACTION_SEMANTICS, ACTIVITY_KINDS,
|
|
3
|
+
import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, ModelVersionAheadError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, SYSTEM_IDENTITY, clientConfigFromResource, fieldTreeShape, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, modelVersionOf, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, requiredModelFeatures, requiredReaderModel, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
|
|
4
4
|
|
|
5
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, dedupeReads, whatIfCondition, MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
|
|
6
6
|
|
|
@@ -265,6 +265,10 @@ const HIGH_FREQUENCY_SAMPLE_MS = 6e4, WorkflowDefinitionDeployed = defineWorkflo
|
|
|
265
265
|
name: "Editorial Workflows Stage Set",
|
|
266
266
|
version: 1,
|
|
267
267
|
description: "The set-stage admin override was invoked (changed: false = already at the target stage)"
|
|
268
|
+
}), WorkflowActivityReset = defineWorkflowEvent({
|
|
269
|
+
name: "Editorial Workflows Activity Reset",
|
|
270
|
+
version: 1,
|
|
271
|
+
description: "The reset-activity admin override was invoked (changed: false = already at the target status, or the instance was terminal)"
|
|
268
272
|
}), WorkflowDefinitionDeleted = defineWorkflowEvent({
|
|
269
273
|
name: "Editorial Workflows Definition Deleted",
|
|
270
274
|
version: 1,
|
|
@@ -845,7 +849,7 @@ function toGroqDescribeContext(ctx) {
|
|
|
845
849
|
};
|
|
846
850
|
}
|
|
847
851
|
|
|
848
|
-
const VAR_LABELS = new Map([ ...
|
|
852
|
+
const VAR_LABELS = new Map([ ...START_REQUIREMENT_VARS, ...CONDITION_VARS ].map(entry => [ entry.name, entry.label ]));
|
|
849
853
|
|
|
850
854
|
function renderWorkflowRead(read, ctx) {
|
|
851
855
|
if (read.variable === "fields" && typeof read.path[0] == "string") {
|
|
@@ -918,13 +922,6 @@ function clauseVarRequirement(requirement) {
|
|
|
918
922
|
params: {},
|
|
919
923
|
text: "no activity in this stage may have failed"
|
|
920
924
|
});
|
|
921
|
-
if (target.variable === SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR) return kind === "truthy" ? phrase("requirement.subject-has-in-flight-instance", {
|
|
922
|
-
params: {},
|
|
923
|
-
text: "the subject must already have an in-flight workflow"
|
|
924
|
-
}) : phrase("requirement.subject-has-no-in-flight-instance", {
|
|
925
|
-
params: {},
|
|
926
|
-
text: "the subject must not already have an in-flight workflow"
|
|
927
|
-
});
|
|
928
925
|
}
|
|
929
926
|
}
|
|
930
927
|
|
|
@@ -1420,14 +1417,14 @@ function activitySites(activity, stage) {
|
|
|
1420
1417
|
activity: activity.name
|
|
1421
1418
|
},
|
|
1422
1419
|
condition: activity.filter
|
|
1423
|
-
} ] : [], ...
|
|
1420
|
+
} ] : [], ...(activity.requirements ?? []).map(requirement => ({
|
|
1424
1421
|
stage: stage,
|
|
1425
1422
|
address: {
|
|
1426
1423
|
kind: "requirement",
|
|
1427
1424
|
activity: activity.name,
|
|
1428
|
-
requirement: requirement
|
|
1425
|
+
requirement: requirement.name
|
|
1429
1426
|
},
|
|
1430
|
-
condition:
|
|
1427
|
+
condition: requirement.query
|
|
1431
1428
|
})), ...(activity.actions ?? []).flatMap(action => [ ...action.filter !== void 0 ? [ {
|
|
1432
1429
|
stage: stage,
|
|
1433
1430
|
address: {
|
|
@@ -1495,13 +1492,7 @@ async function evaluateStartFilter(args) {
|
|
|
1495
1492
|
const {filter: filter, definition: definition, document: document, scope: scope} = args, parsed = parseStartFilter({
|
|
1496
1493
|
filter: filter,
|
|
1497
1494
|
definition: definition
|
|
1498
|
-
});
|
|
1499
|
-
assertFilterSubject({
|
|
1500
|
-
readsSubject: parsed.readsSubject,
|
|
1501
|
-
definition: definition,
|
|
1502
|
-
scope: scope
|
|
1503
|
-
});
|
|
1504
|
-
const dataset = await filterDataset(parsed.needsDataset, scope);
|
|
1495
|
+
}), dataset = await filterDataset(parsed.needsDataset, scope);
|
|
1505
1496
|
if (dataset === void 0) return !1;
|
|
1506
1497
|
try {
|
|
1507
1498
|
const result = await (await evaluate(parsed.tree, {
|
|
@@ -1511,8 +1502,7 @@ async function evaluateStartFilter(args) {
|
|
|
1511
1502
|
dataset: dataset,
|
|
1512
1503
|
params: startContextParams({
|
|
1513
1504
|
definition: definition,
|
|
1514
|
-
scope: scope
|
|
1515
|
-
dataset: dataset
|
|
1505
|
+
scope: scope
|
|
1516
1506
|
})
|
|
1517
1507
|
})).get();
|
|
1518
1508
|
return isUnevaluable(result) ? !1 : !!result;
|
|
@@ -1528,11 +1518,9 @@ async function evaluateStartFilter(args) {
|
|
|
1528
1518
|
function parseStartFilter(args) {
|
|
1529
1519
|
const {filter: filter, definition: definition} = args;
|
|
1530
1520
|
try {
|
|
1531
|
-
const readsSubject = readsSubjectHasInFlightInstance(filter);
|
|
1532
1521
|
return {
|
|
1533
1522
|
tree: parse(filter),
|
|
1534
|
-
needsDataset: analyzeCondition(filter).readsDataset
|
|
1535
|
-
readsSubject: readsSubject
|
|
1523
|
+
needsDataset: analyzeCondition(filter).readsDataset
|
|
1536
1524
|
};
|
|
1537
1525
|
} catch (err) {
|
|
1538
1526
|
rethrowNamingDefinition({
|
|
@@ -1543,70 +1531,81 @@ function parseStartFilter(args) {
|
|
|
1543
1531
|
}
|
|
1544
1532
|
}
|
|
1545
1533
|
|
|
1546
|
-
function assertFilterSubject(args) {
|
|
1547
|
-
if (!(!args.readsSubject || args.scope?.subject !== void 0)) throw new ContractViolationError(`start.filter on definition "${args.definition.name ?? "<unnamed>"}" reads $${SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR}, but the caller supplied no resource-qualified \`scope.subject\` — a loaded document alone cannot identify its project and dataset.`);
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
1534
|
async function filterDataset(needsDataset, scope) {
|
|
1551
1535
|
if (!needsDataset) return [];
|
|
1552
1536
|
if (scope?.fetchDataset !== void 0) return scope.fetchDataset();
|
|
1553
1537
|
}
|
|
1554
1538
|
|
|
1555
|
-
async function
|
|
1556
|
-
const {
|
|
1539
|
+
async function explainStartRequirement(args) {
|
|
1540
|
+
const {query: query, definition: definition, fields: fields, scope: scope} = args;
|
|
1557
1541
|
let needsDataset;
|
|
1558
1542
|
try {
|
|
1559
|
-
needsDataset = analyzeCondition(
|
|
1543
|
+
needsDataset = analyzeCondition(query).readsDataset;
|
|
1560
1544
|
} catch (err) {
|
|
1561
1545
|
rethrowNamingDefinition({
|
|
1562
1546
|
err: err,
|
|
1563
1547
|
definition: definition,
|
|
1564
|
-
key: "
|
|
1548
|
+
key: "requirement"
|
|
1565
1549
|
});
|
|
1566
1550
|
}
|
|
1567
1551
|
let dataset = [];
|
|
1568
1552
|
if (needsDataset) {
|
|
1569
|
-
if (scope?.fetchDataset === void 0) throw new ContractViolationError(`start
|
|
1553
|
+
if (scope?.fetchDataset === void 0) throw new ContractViolationError(`start requirement on definition "${definition.name ?? "<unnamed>"}" reads the dataset (\`*[...]\`), but the caller supplied no \`scope.fetchDataset\` — evaluating over an empty slice would let a count()-style rule pass vacuously. Supply the instance slice.`);
|
|
1570
1554
|
dataset = await scope.fetchDataset();
|
|
1571
1555
|
}
|
|
1572
1556
|
try {
|
|
1573
1557
|
return await explainCondition({
|
|
1574
|
-
condition:
|
|
1558
|
+
condition: query,
|
|
1575
1559
|
dataset: dataset,
|
|
1576
1560
|
params: startContextParams({
|
|
1577
1561
|
definition: definition,
|
|
1578
1562
|
scope: scope,
|
|
1579
|
-
fields: fields
|
|
1580
|
-
dataset: dataset
|
|
1563
|
+
fields: fields
|
|
1581
1564
|
})
|
|
1582
1565
|
});
|
|
1583
1566
|
} catch (err) {
|
|
1584
1567
|
rethrowNamingDefinition({
|
|
1585
1568
|
err: err,
|
|
1586
1569
|
definition: definition,
|
|
1587
|
-
key: "
|
|
1570
|
+
key: "requirement"
|
|
1588
1571
|
});
|
|
1589
1572
|
}
|
|
1590
1573
|
}
|
|
1591
1574
|
|
|
1592
|
-
function
|
|
1593
|
-
return [ ...conditionFieldReadNames(
|
|
1575
|
+
function unboundRequirementReads(query, fields) {
|
|
1576
|
+
return [ ...conditionFieldReadNames(query) ].filter(name => !Object.hasOwn(fields, name));
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
function hasSingleSubjectRequirement(definition) {
|
|
1580
|
+
return definition.start?.requirements?.some(requirement => requirement.type === "singleSubject") ?? !1;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
async function singleSubjectRequirementRefused(args) {
|
|
1584
|
+
const {definition: definition, fields: fields, scope: scope} = args, name = singleSubjectDefinitionName(definition), subject = (fields !== void 0 ? startSubject(definition, fields) : void 0) ?? scope?.subject;
|
|
1585
|
+
if (subject === void 0) return !1;
|
|
1586
|
+
if (scope?.fetchDataset === void 0) throw new ContractViolationError(`singleSubject requirement on definition "${name}" scans the tag's instance slice, but the caller supplied no \`scope.fetchDataset\` — evaluating over an empty slice would let the rule pass vacuously. Supply the projected start slice.`);
|
|
1587
|
+
const dataset = await scope.fetchDataset();
|
|
1588
|
+
return sliceHasInFlightSubject({
|
|
1589
|
+
dataset: dataset,
|
|
1590
|
+
subject: subject,
|
|
1591
|
+
definition: name
|
|
1592
|
+
});
|
|
1594
1593
|
}
|
|
1595
1594
|
|
|
1596
|
-
function
|
|
1597
|
-
const
|
|
1598
|
-
|
|
1599
|
-
|
|
1595
|
+
function singleSubjectDefinitionName(definition) {
|
|
1596
|
+
const label = definition.name ?? "<unnamed>";
|
|
1597
|
+
if (definition.start?.requirements?.find(requirement => requirement.type === "singleSubject") === void 0) throw new ContractViolationError(`singleSubjectRequirementRefused called for definition "${label}", which declares no \`singleSubject\` requirement — evaluate only what the definition declares.`);
|
|
1598
|
+
if (definition.name === void 0) throw new ContractViolationError("singleSubjectRequirementRefused needs the definition `name` — the rule scopes its in-flight scan to instances of the definition, which a nameless source cannot identify.");
|
|
1599
|
+
return definition.name;
|
|
1600
1600
|
}
|
|
1601
1601
|
|
|
1602
1602
|
function rethrowNamingDefinition({err: err, definition: definition, key: key}) {
|
|
1603
|
-
rethrowWithContext(err,
|
|
1603
|
+
rethrowWithContext(err, `${key === "filter" ? "start.filter" : "start requirement"} on definition "${definition.name ?? "<unnamed>"}" failed to evaluate (check the predicate and its evaluation inputs)`);
|
|
1604
1604
|
}
|
|
1605
1605
|
|
|
1606
|
-
function startContextParams({definition: definition, scope: scope, fields: fields
|
|
1607
|
-
const
|
|
1608
|
-
return fields !== void 0 && (params.fields = fields),
|
|
1609
|
-
params;
|
|
1606
|
+
function startContextParams({definition: definition, scope: scope, fields: fields}) {
|
|
1607
|
+
const params = baseStartParams(definition, scope);
|
|
1608
|
+
return fields !== void 0 && (params.fields = fields), params;
|
|
1610
1609
|
}
|
|
1611
1610
|
|
|
1612
1611
|
function baseStartParams(definition, scope) {
|
|
@@ -1623,10 +1622,6 @@ function baseStartParams(definition, scope) {
|
|
|
1623
1622
|
};
|
|
1624
1623
|
}
|
|
1625
1624
|
|
|
1626
|
-
function readsSubjectHasInFlightInstance(groq) {
|
|
1627
|
-
return conditionParameterNames(groq).has(SUBJECT_HAS_IN_FLIGHT_INSTANCE_VAR);
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
1625
|
function startSubject(definition, fields) {
|
|
1631
1626
|
const subjectEntry = (definition.fields ?? []).find(isSubjectEntry);
|
|
1632
1627
|
if (subjectEntry === void 0) return;
|
|
@@ -1634,15 +1629,12 @@ function startSubject(definition, fields) {
|
|
|
1634
1629
|
return isGdr(value) ? value.id : void 0;
|
|
1635
1630
|
}
|
|
1636
1631
|
|
|
1637
|
-
function
|
|
1632
|
+
function sliceHasInFlightSubject(args) {
|
|
1633
|
+
const {dataset: dataset, subject: subject, definition: definition} = args;
|
|
1638
1634
|
return dataset.some(row => {
|
|
1639
1635
|
if (typeof row != "object" || row === null) return !1;
|
|
1640
1636
|
const instance = row;
|
|
1641
|
-
return instance.
|
|
1642
|
-
if (typeof entry != "object" || entry === null) return !1;
|
|
1643
|
-
const field = entry;
|
|
1644
|
-
return field._type === "subject" && isGdr(field.value) && field.value.id === subject;
|
|
1645
|
-
});
|
|
1637
|
+
return instance.completedAt != null || instance.definition !== definition ? !1 : instance.subject === subject;
|
|
1646
1638
|
});
|
|
1647
1639
|
}
|
|
1648
1640
|
|
|
@@ -1672,11 +1664,11 @@ function startFilterSyntaxIssues(groq) {
|
|
|
1672
1664
|
});
|
|
1673
1665
|
}
|
|
1674
1666
|
|
|
1675
|
-
function
|
|
1667
|
+
function startRequirementSyntaxIssues(groq) {
|
|
1676
1668
|
return startContextSyntaxIssues({
|
|
1677
1669
|
groq: groq,
|
|
1678
|
-
vars:
|
|
1679
|
-
context: "start-
|
|
1670
|
+
vars: START_REQUIREMENT_VARS,
|
|
1671
|
+
context: "start-requirement"
|
|
1680
1672
|
});
|
|
1681
1673
|
}
|
|
1682
1674
|
|
|
@@ -1684,7 +1676,7 @@ function startContextSyntaxIssues({groq: groq, vars: vars, context: context, ski
|
|
|
1684
1676
|
try {
|
|
1685
1677
|
parse(groq);
|
|
1686
1678
|
} catch (err) {
|
|
1687
|
-
return [
|
|
1679
|
+
return [ errorMessage(err) ];
|
|
1688
1680
|
}
|
|
1689
1681
|
const bound = new Set(vars.map(v2 => v2.name));
|
|
1690
1682
|
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(", "));
|
|
@@ -2523,24 +2515,24 @@ function applyFieldSet(op, ctx) {
|
|
|
2523
2515
|
src: op.value,
|
|
2524
2516
|
ctx: ctx,
|
|
2525
2517
|
target: entrySlot(entry)
|
|
2526
|
-
})
|
|
2527
|
-
return validateFieldValue({
|
|
2518
|
+
}), validated = validateFieldValue({
|
|
2528
2519
|
entryType: entry._type,
|
|
2529
2520
|
entryName: entry.name,
|
|
2530
2521
|
value: value,
|
|
2531
2522
|
...entryShape(entry)
|
|
2532
|
-
})
|
|
2523
|
+
});
|
|
2524
|
+
return assertRuntimeRefsWithinSurface({
|
|
2533
2525
|
entryType: entry._type,
|
|
2534
2526
|
entryName: entry.name,
|
|
2535
|
-
value:
|
|
2527
|
+
value: validated,
|
|
2536
2528
|
...entryShape(entry),
|
|
2537
2529
|
ctx: ctx,
|
|
2538
2530
|
src: op.value
|
|
2539
|
-
}), setEntryValue(entry,
|
|
2531
|
+
}), setEntryValue(entry, validated), {
|
|
2540
2532
|
opType: op.type,
|
|
2541
2533
|
target: op.target,
|
|
2542
2534
|
resolved: {
|
|
2543
|
-
value:
|
|
2535
|
+
value: validated
|
|
2544
2536
|
}
|
|
2545
2537
|
};
|
|
2546
2538
|
}
|
|
@@ -2601,27 +2593,27 @@ function applyFieldAppend(op, ctx) {
|
|
|
2601
2593
|
...slot !== void 0 ? {
|
|
2602
2594
|
target: slot
|
|
2603
2595
|
} : {}
|
|
2604
|
-
})
|
|
2605
|
-
validateFieldAppendItem({
|
|
2596
|
+
}), validated = validateFieldAppendItem({
|
|
2606
2597
|
entryType: entry._type,
|
|
2607
2598
|
entryName: entry.name,
|
|
2608
2599
|
item: item,
|
|
2609
2600
|
types: entry._type === "doc.refs" ? entry.types : void 0,
|
|
2610
2601
|
of: entry._type === "array" ? entry.of : void 0
|
|
2611
|
-
})
|
|
2602
|
+
});
|
|
2603
|
+
assertRuntimeRefsWithinSurface({
|
|
2612
2604
|
entryType: entry._type === "doc.refs" ? "doc.ref" : "object",
|
|
2613
2605
|
entryName: entry.name,
|
|
2614
|
-
value:
|
|
2606
|
+
value: validated,
|
|
2615
2607
|
fields: entry._type === "array" ? entry.of : void 0,
|
|
2616
2608
|
ctx: ctx,
|
|
2617
2609
|
src: op.value
|
|
2618
2610
|
});
|
|
2619
2611
|
const current = Array.isArray(entry.value) ? entry.value : [];
|
|
2620
|
-
return setEntryValue(entry, [ ...current, withRowKey(
|
|
2612
|
+
return setEntryValue(entry, [ ...current, withRowKey(validated) ]), {
|
|
2621
2613
|
opType: op.type,
|
|
2622
2614
|
target: op.target,
|
|
2623
2615
|
resolved: {
|
|
2624
|
-
item:
|
|
2616
|
+
item: validated
|
|
2625
2617
|
}
|
|
2626
2618
|
};
|
|
2627
2619
|
}
|
|
@@ -2649,8 +2641,9 @@ async function applyFieldUpdateWhere(op, ctx) {
|
|
|
2649
2641
|
mode: "value",
|
|
2650
2642
|
issues: [ `field.updateWhere value must resolve to an object of fields to merge (target "${op.target.field}")` ]
|
|
2651
2643
|
});
|
|
2644
|
+
const mergeRecord = merge;
|
|
2652
2645
|
requireNoReservedMergeKeys({
|
|
2653
|
-
merge:
|
|
2646
|
+
merge: mergeRecord,
|
|
2654
2647
|
entry: entry,
|
|
2655
2648
|
op: op
|
|
2656
2649
|
});
|
|
@@ -2660,25 +2653,27 @@ async function applyFieldUpdateWhere(op, ctx) {
|
|
|
2660
2653
|
ctx: ctx
|
|
2661
2654
|
}), next = rows.map((row, index) => matches[index] ? {
|
|
2662
2655
|
...row,
|
|
2663
|
-
...
|
|
2664
|
-
} : row)
|
|
2665
|
-
return validateFieldValue({
|
|
2656
|
+
...mergeRecord
|
|
2657
|
+
} : row), validated = validateFieldValue({
|
|
2666
2658
|
entryType: entry._type,
|
|
2667
2659
|
entryName: entry.name,
|
|
2668
2660
|
value: next,
|
|
2669
2661
|
of: entry.of
|
|
2670
|
-
})
|
|
2662
|
+
});
|
|
2663
|
+
assertRuntimeRefsWithinSurface({
|
|
2671
2664
|
entryType: "object",
|
|
2672
2665
|
entryName: entry.name,
|
|
2673
2666
|
value: merge,
|
|
2674
2667
|
fields: entry.of,
|
|
2675
2668
|
ctx: ctx,
|
|
2676
2669
|
src: op.value
|
|
2677
|
-
}), setEntryValue(entry,
|
|
2670
|
+
}), setEntryValue(entry, validated);
|
|
2671
|
+
const firstMatch = matches.indexOf(!0), persistedRows = validated, persistedMerge = firstMatch === -1 ? merge : Object.fromEntries(Object.keys(mergeRecord).map(key => [ key, persistedRows[firstMatch]?.[key] ]));
|
|
2672
|
+
return {
|
|
2678
2673
|
opType: op.type,
|
|
2679
2674
|
target: op.target,
|
|
2680
2675
|
resolved: {
|
|
2681
|
-
merge:
|
|
2676
|
+
merge: persistedMerge
|
|
2682
2677
|
}
|
|
2683
2678
|
};
|
|
2684
2679
|
}
|
|
@@ -2870,8 +2865,8 @@ function validateDefinition(definition) {
|
|
|
2870
2865
|
address: address
|
|
2871
2866
|
}));
|
|
2872
2867
|
}
|
|
2873
|
-
definition.start?.filter !== void 0 && v2.report("start.filter", startFilterSyntaxIssues(definition.start.filter))
|
|
2874
|
-
definition.start?.
|
|
2868
|
+
definition.start?.filter !== void 0 && v2.report("start.filter", startFilterSyntaxIssues(definition.start.filter));
|
|
2869
|
+
for (const [index, requirement] of (definition.start?.requirements ?? []).entries()) requirement.type === "groq" && v2.report(`start.requirements[${index}].query`, startRequirementSyntaxIssues(requirement.query));
|
|
2875
2870
|
for (const entry of definition.fields ?? []) v2.checkEntry(entry, `workflow.fields "${entry.name}"`);
|
|
2876
2871
|
for (const stage of definition.stages) validateStage(v2, stage);
|
|
2877
2872
|
for (const issue of checkWorkflowInvariants(definition)) v2.errors.push(` · ${formatIssuePath(issue.path)}: ${issue.message}`);
|
|
@@ -3301,6 +3296,11 @@ function definitionsListGroq(versionOrder) {
|
|
|
3301
3296
|
return `*[_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}] | order(name asc, version ${versionOrder})`;
|
|
3302
3297
|
}
|
|
3303
3298
|
|
|
3299
|
+
function latestDefinitionsGroq() {
|
|
3300
|
+
const scoped = `_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}`;
|
|
3301
|
+
return `*[${scoped} && version == math::max(*[${scoped} && name == ^.name].version)] | order(name asc)`;
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
3304
|
function latestDeployedDefinitions(rows) {
|
|
3305
3305
|
const byName = /* @__PURE__ */ new Map;
|
|
3306
3306
|
for (const row of rows) {
|
|
@@ -3382,7 +3382,7 @@ function blockedState(input) {
|
|
|
3382
3382
|
if (blocked !== void 0) return {
|
|
3383
3383
|
state: "blocked",
|
|
3384
3384
|
activity: blocked.activity.name,
|
|
3385
|
-
requirements: blocked.unmetRequirements ?? [],
|
|
3385
|
+
requirements: (blocked.unmetRequirements ?? []).map(requirement => requirement.name),
|
|
3386
3386
|
assignees: input.assignees[blocked.activity.name] ?? []
|
|
3387
3387
|
};
|
|
3388
3388
|
}
|
|
@@ -3425,7 +3425,7 @@ function diagnoseInstance(input) {
|
|
|
3425
3425
|
};
|
|
3426
3426
|
}
|
|
3427
3427
|
|
|
3428
|
-
const RUNNABLE_VERBS = /* @__PURE__ */ new Set([ "set-stage", "abort", "drain-effects" ]);
|
|
3428
|
+
const RUNNABLE_VERBS = /* @__PURE__ */ new Set([ "set-stage", "abort", "drain-effects", "reset-activity" ]);
|
|
3429
3429
|
|
|
3430
3430
|
function remediationsForCause(cause) {
|
|
3431
3431
|
switch (cause.kind) {
|
|
@@ -3927,7 +3927,7 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
|
|
|
3927
3927
|
defaultValue: defaultValue
|
|
3928
3928
|
});
|
|
3929
3929
|
if (entry.initialValue?.type === "query") {
|
|
3930
|
-
const
|
|
3930
|
+
const check = parseFieldValue({
|
|
3931
3931
|
entryType: entry.type,
|
|
3932
3932
|
value: value,
|
|
3933
3933
|
types: entry.types,
|
|
@@ -3936,9 +3936,9 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
|
|
|
3936
3936
|
options: entry.options,
|
|
3937
3937
|
validation: entry.validation
|
|
3938
3938
|
});
|
|
3939
|
-
return issues
|
|
3939
|
+
return "issues" in check ? (ctx.recordDiscard?.({
|
|
3940
3940
|
field: entry.name,
|
|
3941
|
-
detail: issues.join("; ")
|
|
3941
|
+
detail: check.issues.join("; ")
|
|
3942
3942
|
}), buildResolvedEntry({
|
|
3943
3943
|
entry: entry,
|
|
3944
3944
|
value: defaultValue,
|
|
@@ -3946,12 +3946,12 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
|
|
|
3946
3946
|
now: ctx.now
|
|
3947
3947
|
})) : buildResolvedEntry({
|
|
3948
3948
|
entry: entry,
|
|
3949
|
-
value:
|
|
3949
|
+
value: check.output,
|
|
3950
3950
|
_key: randomKey2(),
|
|
3951
3951
|
now: ctx.now
|
|
3952
3952
|
});
|
|
3953
3953
|
}
|
|
3954
|
-
|
|
3954
|
+
const validated = validateFieldValue({
|
|
3955
3955
|
entryType: entry.type,
|
|
3956
3956
|
entryName: entry.name,
|
|
3957
3957
|
value: value,
|
|
@@ -3960,16 +3960,17 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
|
|
|
3960
3960
|
of: entry.of,
|
|
3961
3961
|
options: entry.options,
|
|
3962
3962
|
validation: entry.validation
|
|
3963
|
-
})
|
|
3963
|
+
});
|
|
3964
|
+
return entry.initialValue?.type === "input" && ctx.inputProvenance !== "definition" && assertRefsWithinSurface({
|
|
3964
3965
|
entryType: entry.type,
|
|
3965
3966
|
entryName: entry.name,
|
|
3966
|
-
value:
|
|
3967
|
+
value: validated,
|
|
3967
3968
|
fields: entry.fields,
|
|
3968
3969
|
of: entry.of,
|
|
3969
3970
|
surface: ctx.refSurface
|
|
3970
3971
|
}), buildResolvedEntry({
|
|
3971
3972
|
entry: entry,
|
|
3972
|
-
value:
|
|
3973
|
+
value: validated,
|
|
3973
3974
|
_key: randomKey2(),
|
|
3974
3975
|
now: ctx.now
|
|
3975
3976
|
});
|
|
@@ -4363,172 +4364,605 @@ function parseInstanceDocument(doc) {
|
|
|
4363
4364
|
});
|
|
4364
4365
|
}
|
|
4365
4366
|
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4367
|
+
const SYNC_COMMIT = {
|
|
4368
|
+
visibility: "sync"
|
|
4369
|
+
}, ENGINE_API_VERSION = "2026-04-29", REQUEST_TAG = {
|
|
4370
|
+
engine: "workflow",
|
|
4371
|
+
deploy: "workflow.deploy",
|
|
4372
|
+
deleteDefinition: "workflow.delete-definition",
|
|
4373
|
+
start: "workflow.start",
|
|
4374
|
+
fireAction: "workflow.fire-action",
|
|
4375
|
+
editField: "workflow.edit-field",
|
|
4376
|
+
completeEffect: "workflow.complete-effect",
|
|
4377
|
+
commitEffectOps: "workflow.commit-effect-ops",
|
|
4378
|
+
tick: "workflow.tick",
|
|
4379
|
+
evaluate: "workflow.evaluate",
|
|
4380
|
+
evaluateStart: "workflow.evaluate-start",
|
|
4381
|
+
diagnose: "workflow.diagnose",
|
|
4382
|
+
availableActions: "workflow.available-actions",
|
|
4383
|
+
setStage: "workflow.set-stage",
|
|
4384
|
+
abort: "workflow.abort",
|
|
4385
|
+
resetActivity: "workflow.reset-activity",
|
|
4386
|
+
getInstance: "workflow.get-instance",
|
|
4387
|
+
children: "workflow.children",
|
|
4388
|
+
instancesForDocument: "workflow.instances-for-document",
|
|
4389
|
+
definitionsForDocument: "workflow.definitions-for-document",
|
|
4390
|
+
query: "workflow.query",
|
|
4391
|
+
discover: "workflow.discover",
|
|
4392
|
+
guardQuery: "workflow.guard.query",
|
|
4393
|
+
guardDeploy: "workflow.guard.deploy",
|
|
4394
|
+
guardRefresh: "workflow.guard.refresh",
|
|
4395
|
+
guardRetract: "workflow.guard.retract",
|
|
4396
|
+
effectList: "workflow.effect.list",
|
|
4397
|
+
effectFind: "workflow.effect.find",
|
|
4398
|
+
drain: "workflow.drain",
|
|
4399
|
+
effect: "workflow.effect",
|
|
4400
|
+
verifyDefinitions: "workflow.verify-definitions",
|
|
4401
|
+
accessResolveActor: "workflow.access.resolve-actor",
|
|
4402
|
+
accessGrants: "workflow.access.grants"
|
|
4403
|
+
}, RAW_PATCH = /* @__PURE__ */ Symbol("workflow-engine.raw-patch");
|
|
4370
4404
|
|
|
4371
|
-
function
|
|
4372
|
-
return
|
|
4405
|
+
function unwrapPatch(patch) {
|
|
4406
|
+
return typeof patch == "object" && patch !== null && RAW_PATCH in patch ? patch[RAW_PATCH] : patch;
|
|
4373
4407
|
}
|
|
4374
4408
|
|
|
4375
|
-
|
|
4376
|
-
const doc = await getInstanceDocument(client, instanceId);
|
|
4377
|
-
if (!doc) throw new InstanceNotFoundError({
|
|
4378
|
-
instanceId: instanceId
|
|
4379
|
-
});
|
|
4380
|
-
if (doc.tag !== tag) throw new InstanceNotFoundError({
|
|
4381
|
-
instanceId: instanceId,
|
|
4382
|
-
detail: "not visible to this engine: tag mismatch"
|
|
4383
|
-
});
|
|
4384
|
-
return doc;
|
|
4385
|
-
}
|
|
4409
|
+
const wrapperCache = /* @__PURE__ */ new WeakMap, effectHandlerClientCache = /* @__PURE__ */ new WeakMap, RAW_CLIENT = /* @__PURE__ */ Symbol("workflow-engine.raw-client");
|
|
4386
4410
|
|
|
4387
|
-
function
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
_type: "context.string",
|
|
4392
|
-
name: name,
|
|
4393
|
-
value: value
|
|
4394
|
-
} : typeof value == "number" ? {
|
|
4395
|
-
_key: _key,
|
|
4396
|
-
_type: "context.number",
|
|
4397
|
-
name: name,
|
|
4398
|
-
value: value
|
|
4399
|
-
} : typeof value == "boolean" ? {
|
|
4400
|
-
_key: _key,
|
|
4401
|
-
_type: "context.boolean",
|
|
4402
|
-
name: name,
|
|
4403
|
-
value: value
|
|
4404
|
-
} : {
|
|
4405
|
-
_key: _key,
|
|
4406
|
-
_type: "context.ref",
|
|
4407
|
-
name: name,
|
|
4408
|
-
value: value
|
|
4409
|
-
};
|
|
4411
|
+
function unwrapRequestTag(client) {
|
|
4412
|
+
let current = client;
|
|
4413
|
+
for (;RAW_CLIENT in current; ) current = current[RAW_CLIENT];
|
|
4414
|
+
return current;
|
|
4410
4415
|
}
|
|
4411
4416
|
|
|
4412
|
-
function
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4417
|
+
function withRequestTag(client, fallback) {
|
|
4418
|
+
let byTag = wrapperCache.get(client);
|
|
4419
|
+
byTag === void 0 && (byTag = /* @__PURE__ */ new Map, wrapperCache.set(client, byTag));
|
|
4420
|
+
const cached = byTag.get(fallback);
|
|
4421
|
+
if (cached !== void 0) return cached;
|
|
4422
|
+
const wrapped = buildTaggedClient(client, fallback);
|
|
4423
|
+
return byTag.set(fallback, wrapped), wrapped;
|
|
4419
4424
|
}
|
|
4420
4425
|
|
|
4421
|
-
function
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4426
|
+
function effectHandlerClient(client) {
|
|
4427
|
+
const cached = effectHandlerClientCache.get(client);
|
|
4428
|
+
if (cached !== void 0) return cached;
|
|
4429
|
+
let tagged;
|
|
4430
|
+
if (client.withConfig === void 0) tagged = withRequestTag(client, REQUEST_TAG.effect); else {
|
|
4431
|
+
const prefix = clientRequestTagPrefix(client), effectTag = composeRequestTag(prefix, REQUEST_TAG.effect);
|
|
4432
|
+
tagged = client.withConfig({
|
|
4433
|
+
requestTagPrefix: effectTag
|
|
4434
|
+
});
|
|
4427
4435
|
}
|
|
4428
|
-
|
|
4429
|
-
return json;
|
|
4436
|
+
return effectHandlerClientCache.set(client, tagged), tagged;
|
|
4430
4437
|
}
|
|
4431
4438
|
|
|
4432
|
-
function
|
|
4433
|
-
|
|
4434
|
-
_key: randomKey(),
|
|
4435
|
-
_type: "stageEntered",
|
|
4436
|
-
at: now,
|
|
4437
|
-
stage: args.initialStage,
|
|
4438
|
-
...actor !== void 0 ? {
|
|
4439
|
-
actor: actor
|
|
4440
|
-
} : {}
|
|
4441
|
-
}, ...args.extraHistory ?? [] ], history = executionContext !== void 0 ? stampHistoryEntries(entries, executionContext) : entries, body = {
|
|
4442
|
-
_id: id,
|
|
4443
|
-
_type: WORKFLOW_INSTANCE_TYPE,
|
|
4444
|
-
_rev: "",
|
|
4445
|
-
_createdAt: now,
|
|
4446
|
-
_updatedAt: now,
|
|
4447
|
-
tag: args.tag,
|
|
4448
|
-
workflowResource: args.workflowResource,
|
|
4449
|
-
definition: args.definitionName,
|
|
4450
|
-
pinnedVersion: args.pinnedVersion,
|
|
4451
|
-
...args.pinnedContentHash !== void 0 ? {
|
|
4452
|
-
pinnedContentHash: args.pinnedContentHash
|
|
4453
|
-
} : {},
|
|
4454
|
-
definitionSnapshot: JSON.stringify(args.definition),
|
|
4455
|
-
fields: args.fields,
|
|
4456
|
-
context: args.context,
|
|
4457
|
-
ancestors: args.ancestors,
|
|
4458
|
-
...perspective !== void 0 ? {
|
|
4459
|
-
perspective: perspective
|
|
4460
|
-
} : {},
|
|
4461
|
-
currentStage: args.initialStage,
|
|
4462
|
-
stages: [],
|
|
4463
|
-
subworkflows: [],
|
|
4464
|
-
pendingEffects: [],
|
|
4465
|
-
effectHistory: [],
|
|
4466
|
-
history: history,
|
|
4467
|
-
startedAt: now,
|
|
4468
|
-
lastChangedAt: now
|
|
4469
|
-
};
|
|
4470
|
-
return {
|
|
4471
|
-
...body,
|
|
4472
|
-
...modelStampFor({
|
|
4473
|
-
documentType: "instance",
|
|
4474
|
-
document: body
|
|
4475
|
-
})
|
|
4476
|
-
};
|
|
4439
|
+
function effectHandlerResolver(resolver) {
|
|
4440
|
+
return mapResourceClientResolver(resolver, effectHandlerClient);
|
|
4477
4441
|
}
|
|
4478
4442
|
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
}), visited.add(selfGdr(instance));
|
|
4485
|
-
const {pending: pending, ordered: ordered} = planReads({
|
|
4486
|
-
client: client,
|
|
4487
|
-
clientForGdr: clientForGdr,
|
|
4488
|
-
instance: instance,
|
|
4489
|
-
overlay: overlay,
|
|
4490
|
-
visited: visited
|
|
4491
|
-
}), fetched = await readPending(pending);
|
|
4492
|
-
for (const entry of ordered) if (!isPendingRead(entry)) loaded.push(entry); else {
|
|
4493
|
-
const doc = fetched.get(entry);
|
|
4494
|
-
doc !== void 0 && loaded.push({
|
|
4495
|
-
doc: doc,
|
|
4496
|
-
resource: entry.resource
|
|
4497
|
-
});
|
|
4498
|
-
}
|
|
4499
|
-
return buildSnapshot({
|
|
4500
|
-
docs: loaded
|
|
4501
|
-
});
|
|
4443
|
+
function mapResourceClientResolver(resolver, mapClient) {
|
|
4444
|
+
if (resolver !== void 0) return parsed => {
|
|
4445
|
+
const client = resolver(parsed);
|
|
4446
|
+
return client === void 0 ? void 0 : mapClient(client);
|
|
4447
|
+
};
|
|
4502
4448
|
}
|
|
4503
4449
|
|
|
4504
|
-
function
|
|
4505
|
-
|
|
4506
|
-
for (const ref of collectWatchRefs(instance)) {
|
|
4507
|
-
if (visited.has(ref.id)) continue;
|
|
4508
|
-
visited.add(ref.id);
|
|
4509
|
-
const held = overlay?.get(ref.id);
|
|
4510
|
-
if (held !== void 0) ordered.push(held); else {
|
|
4511
|
-
const read = routeRead({
|
|
4512
|
-
defaultClient: client,
|
|
4513
|
-
clientForGdr: clientForGdr,
|
|
4514
|
-
defaultResource: instance.workflowResource,
|
|
4515
|
-
uri: ref.id,
|
|
4516
|
-
perspective: readsRaw(ref) ? "raw" : instance.perspective ?? DEFAULT_CONTENT_PERSPECTIVE
|
|
4517
|
-
});
|
|
4518
|
-
pending.push(read), ordered.push(read);
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
return {
|
|
4522
|
-
pending: pending,
|
|
4523
|
-
ordered: ordered
|
|
4524
|
-
};
|
|
4450
|
+
function isWorkflowsFamilyPrefix(prefix) {
|
|
4451
|
+
return prefix === void 0 ? !1 : prefix === "sanity.workflows" || prefix.startsWith("sanity.workflows.") || prefix === "sanity.workflows-mcp";
|
|
4525
4452
|
}
|
|
4526
4453
|
|
|
4527
|
-
function
|
|
4528
|
-
|
|
4454
|
+
function clientRequestTagPrefix(client) {
|
|
4455
|
+
const probe = client;
|
|
4456
|
+
return typeof probe.config == "function" ? probe.config().requestTagPrefix : void 0;
|
|
4529
4457
|
}
|
|
4530
4458
|
|
|
4531
|
-
|
|
4459
|
+
function composeRequestTag(prefix, tag) {
|
|
4460
|
+
if (prefix === void 0) return tag;
|
|
4461
|
+
const relative = isWorkflowsFamilyPrefix(prefix) ? stripWorkflowRoot(tag) : tag;
|
|
4462
|
+
return `${prefix}.${relative}`;
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
function stripWorkflowRoot(tag) {
|
|
4466
|
+
return tag.startsWith("workflow.") ? tag.slice(9) : tag;
|
|
4467
|
+
}
|
|
4468
|
+
|
|
4469
|
+
function buildTaggedClient(client, fallback) {
|
|
4470
|
+
const strip = isWorkflowsFamilyPrefix(clientRequestTagPrefix(unwrapRequestTag(client))), normalize = tag => strip ? stripWorkflowRoot(tag) : tag, stamp = options => options === void 0 ? {
|
|
4471
|
+
tag: normalize(fallback)
|
|
4472
|
+
} : options.tag === void 0 ? {
|
|
4473
|
+
...options,
|
|
4474
|
+
tag: normalize(fallback)
|
|
4475
|
+
} : typeof options.tag == "string" && options.tag !== normalize(options.tag) ? {
|
|
4476
|
+
...options,
|
|
4477
|
+
tag: normalize(options.tag)
|
|
4478
|
+
} : options, wrapPatch = patch => {
|
|
4479
|
+
let target = patch;
|
|
4480
|
+
const wrapped = {
|
|
4481
|
+
get [RAW_PATCH]() {
|
|
4482
|
+
return target;
|
|
4483
|
+
},
|
|
4484
|
+
set: props => (target = target.set(props), wrapped),
|
|
4485
|
+
setIfMissing: props => (target = target.setIfMissing(props), wrapped),
|
|
4486
|
+
unset: paths => (target = target.unset(paths), wrapped),
|
|
4487
|
+
ifRevisionId: rev => (target = target.ifRevisionId(rev), wrapped),
|
|
4488
|
+
commit: options => target.commit(stamp(options))
|
|
4489
|
+
};
|
|
4490
|
+
return wrapped;
|
|
4491
|
+
}, wrapTransaction = tx => {
|
|
4492
|
+
let target = tx;
|
|
4493
|
+
const wrapped = {
|
|
4494
|
+
create: doc => (target = target.create(doc), wrapped),
|
|
4495
|
+
patch: patch => (target = target.patch(unwrapPatch(patch)), wrapped),
|
|
4496
|
+
delete: id => (target = target.delete(id), wrapped),
|
|
4497
|
+
commit: options => target.commit(stamp(options))
|
|
4498
|
+
};
|
|
4499
|
+
return wrapped;
|
|
4500
|
+
}, overrides = {
|
|
4501
|
+
[RAW_CLIENT]: unwrapRequestTag(client),
|
|
4502
|
+
fetch: (query, params, options) => client.fetch(query, params, stamp(options)),
|
|
4503
|
+
getDocument: (id, options) => client.getDocument(id, stamp(options)),
|
|
4504
|
+
patch: documentId => wrapPatch(client.patch(documentId)),
|
|
4505
|
+
create: (doc, options) => client.create(doc, stamp(options)),
|
|
4506
|
+
transaction: () => wrapTransaction(client.transaction()),
|
|
4507
|
+
...client.withConfig !== void 0 ? {
|
|
4508
|
+
withConfig: config => withRequestTag(client.withConfig(config), fallback)
|
|
4509
|
+
} : {},
|
|
4510
|
+
...client.action !== void 0 ? {
|
|
4511
|
+
action: (action, options) => client.action(action, stamp(options))
|
|
4512
|
+
} : {},
|
|
4513
|
+
...client.request !== void 0 ? {
|
|
4514
|
+
request: opts => client.request(stamp(opts))
|
|
4515
|
+
} : {}
|
|
4516
|
+
};
|
|
4517
|
+
return new Proxy(client, {
|
|
4518
|
+
has: (target, property) => Object.hasOwn(overrides, property) || property in target,
|
|
4519
|
+
get: (target, property) => {
|
|
4520
|
+
if (Object.hasOwn(overrides, property)) return Reflect.get(overrides, property, overrides);
|
|
4521
|
+
const value = Reflect.get(target, property, target);
|
|
4522
|
+
return typeof value == "function" ? value.bind(target) : value;
|
|
4523
|
+
}
|
|
4524
|
+
});
|
|
4525
|
+
}
|
|
4526
|
+
|
|
4527
|
+
const pinCache = /* @__PURE__ */ new WeakMap, enginePinned = /* @__PURE__ */ new WeakSet;
|
|
4528
|
+
|
|
4529
|
+
function pinApiVersion(client) {
|
|
4530
|
+
const raw = unwrapRequestTag(client);
|
|
4531
|
+
if (enginePinned.has(raw) || raw.withConfig === void 0) return client;
|
|
4532
|
+
let sibling = pinCache.get(raw);
|
|
4533
|
+
return sibling === void 0 && (sibling = raw.withConfig({
|
|
4534
|
+
apiVersion: ENGINE_API_VERSION
|
|
4535
|
+
}), pinCache.set(raw, sibling), enginePinned.add(unwrapRequestTag(sibling))), sibling;
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4538
|
+
function taggedResolver(resolver, fallback) {
|
|
4539
|
+
return mapResourceClientResolver(resolver, client => withRequestTag(pinApiVersion(client), fallback));
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
function taggedScope(args, tag) {
|
|
4543
|
+
const resourceClients = taggedResolver(args.resourceClients, tag);
|
|
4544
|
+
return {
|
|
4545
|
+
...args,
|
|
4546
|
+
client: withRequestTag(pinApiVersion(args.client), tag),
|
|
4547
|
+
...resourceClients !== void 0 ? {
|
|
4548
|
+
resourceClients: resourceClients
|
|
4549
|
+
} : {}
|
|
4550
|
+
};
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
const ACTOR_KIND_SET = new Set(ACTOR_KINDS), resolutionCache = /* @__PURE__ */ new WeakMap, warnedInstances = /* @__PURE__ */ new WeakMap;
|
|
4554
|
+
|
|
4555
|
+
async function normalizeInstanceIdentities(args) {
|
|
4556
|
+
const {client: client, instance: instance} = args, pending = collectLegacyIds(instance);
|
|
4557
|
+
if (pending.size === 0) return instance;
|
|
4558
|
+
const resolved = await resolveLegacyIds({
|
|
4559
|
+
client: client,
|
|
4560
|
+
instance: instance,
|
|
4561
|
+
pending: pending
|
|
4562
|
+
}), unresolved = [ ...pending ].filter(id => !resolved.has(id));
|
|
4563
|
+
return unresolved.length > 0 ? (warnUnresolvedOnce({
|
|
4564
|
+
client: client,
|
|
4565
|
+
instance: instance,
|
|
4566
|
+
unresolved: unresolved
|
|
4567
|
+
}), instance) : rewriteIdentitySlots(instance, id => resolved.get(id));
|
|
4568
|
+
}
|
|
4569
|
+
|
|
4570
|
+
async function resolveLegacyIds(args) {
|
|
4571
|
+
const resolved = /* @__PURE__ */ new Map, directoryIds = [];
|
|
4572
|
+
for (const id of args.pending) {
|
|
4573
|
+
const {globalId: globalId} = classifyPrincipalId(id);
|
|
4574
|
+
globalId !== void 0 ? resolved.set(id, globalId) : directoryIds.push(id);
|
|
4575
|
+
}
|
|
4576
|
+
const projectId = anchorProjectId(args.instance.workflowResource);
|
|
4577
|
+
if (directoryIds.length === 0 || projectId === void 0) return resolved;
|
|
4578
|
+
const fromDirectory = await resolveThroughDirectory({
|
|
4579
|
+
client: args.client,
|
|
4580
|
+
projectId: projectId,
|
|
4581
|
+
ids: directoryIds
|
|
4582
|
+
});
|
|
4583
|
+
for (const [id, globalId] of fromDirectory) resolved.set(id, globalId);
|
|
4584
|
+
return resolved;
|
|
4585
|
+
}
|
|
4586
|
+
|
|
4587
|
+
function warnUnresolvedOnce(args) {
|
|
4588
|
+
const key = unwrapRequestTag(args.client);
|
|
4589
|
+
let warned = warnedInstances.get(key);
|
|
4590
|
+
warned === void 0 && (warned = /* @__PURE__ */ new Set, warnedInstances.set(key, warned)),
|
|
4591
|
+
!warned.has(args.instance._id) && (warned.add(args.instance._id), console.warn(`workflow: instance "${args.instance._id}" carries ${args.unresolved.length} legacy project-scoped principal id(s) the project-users directory could not resolve (${args.unresolved.join(", ")}). Its identity values are left as stored — comparisons against them fail closed — and the document does not self-heal until they resolve.`));
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4594
|
+
function anchorProjectId(resource) {
|
|
4595
|
+
if (resource.type === "dataset") return datasetResourceParts(resource.id).projectId;
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
function collectLegacyIds(instance) {
|
|
4599
|
+
const found = /* @__PURE__ */ new Set;
|
|
4600
|
+
return rewriteIdentitySlots(instance, id => {
|
|
4601
|
+
classifyPrincipalId(id).namespace === "project" && found.add(id);
|
|
4602
|
+
}), found;
|
|
4603
|
+
}
|
|
4604
|
+
|
|
4605
|
+
function rewriteIdentitySlots(instance, visit) {
|
|
4606
|
+
const record = instance, fields = walkEntries(record.fields, visit), stages = walkStages(record.stages, visit);
|
|
4607
|
+
return fields === record.fields && stages === record.stages ? instance : {
|
|
4608
|
+
...record,
|
|
4609
|
+
fields: fields,
|
|
4610
|
+
stages: stages
|
|
4611
|
+
};
|
|
4612
|
+
}
|
|
4613
|
+
|
|
4614
|
+
function walkStages(stages, visit) {
|
|
4615
|
+
return Array.isArray(stages) ? shareMap(stages, stage => {
|
|
4616
|
+
const walked = walkEntryRow({
|
|
4617
|
+
row: stage,
|
|
4618
|
+
visit: visit
|
|
4619
|
+
});
|
|
4620
|
+
if (walked === null || typeof walked != "object") return walked;
|
|
4621
|
+
const record = walked, activities = walkActivities(record.activities, visit);
|
|
4622
|
+
return activities === record.activities ? walked === stage ? stage : walked : {
|
|
4623
|
+
...record,
|
|
4624
|
+
activities: activities
|
|
4625
|
+
};
|
|
4626
|
+
}) : stages;
|
|
4627
|
+
}
|
|
4628
|
+
|
|
4629
|
+
function walkActivities(activities, visit) {
|
|
4630
|
+
return Array.isArray(activities) ? shareMap(activities, activity => walkEntryRow({
|
|
4631
|
+
row: activity,
|
|
4632
|
+
visit: visit
|
|
4633
|
+
})) : activities;
|
|
4634
|
+
}
|
|
4635
|
+
|
|
4636
|
+
function walkEntryRow(args) {
|
|
4637
|
+
const {row: row, visit: visit} = args;
|
|
4638
|
+
if (row === null || typeof row != "object") return row;
|
|
4639
|
+
const record = row, patch = {}, fields = walkEntries(record.fields, visit);
|
|
4640
|
+
if (fields !== record.fields && (patch.fields = fields), typeof record.completedBy == "string") {
|
|
4641
|
+
const stamped = visit(record.completedBy) ?? record.completedBy;
|
|
4642
|
+
stamped !== record.completedBy && (patch.completedBy = stamped);
|
|
4643
|
+
}
|
|
4644
|
+
return Object.keys(patch).length === 0 ? row : {
|
|
4645
|
+
...record,
|
|
4646
|
+
...patch
|
|
4647
|
+
};
|
|
4648
|
+
}
|
|
4649
|
+
|
|
4650
|
+
function walkEntries(entries, visit) {
|
|
4651
|
+
return Array.isArray(entries) ? shareMap(entries, entry => {
|
|
4652
|
+
if (entry === null || typeof entry != "object") return entry;
|
|
4653
|
+
const record = entry, value = walkDeclaredValue({
|
|
4654
|
+
type: record._type,
|
|
4655
|
+
fields: record.fields,
|
|
4656
|
+
of: record.of,
|
|
4657
|
+
value: record.value,
|
|
4658
|
+
visit: visit
|
|
4659
|
+
});
|
|
4660
|
+
return value === record.value ? entry : {
|
|
4661
|
+
...record,
|
|
4662
|
+
value: value
|
|
4663
|
+
};
|
|
4664
|
+
}) : entries;
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
function collectDeclaredGlobalIds(args) {
|
|
4668
|
+
const found = /* @__PURE__ */ new Set;
|
|
4669
|
+
return walkDeclaredValue({
|
|
4670
|
+
type: args.type,
|
|
4671
|
+
fields: args.fields,
|
|
4672
|
+
of: args.of,
|
|
4673
|
+
value: args.value,
|
|
4674
|
+
visit: id => {
|
|
4675
|
+
classifyPrincipalId(id).namespace === "global" && found.add(id);
|
|
4676
|
+
}
|
|
4677
|
+
}), found;
|
|
4678
|
+
}
|
|
4679
|
+
|
|
4680
|
+
function rewriteDeclaredPrincipalIds(args) {
|
|
4681
|
+
return walkDeclaredValue({
|
|
4682
|
+
type: args.type,
|
|
4683
|
+
fields: args.fields,
|
|
4684
|
+
of: args.of,
|
|
4685
|
+
value: args.value,
|
|
4686
|
+
visit: id => args.map.get(id)
|
|
4687
|
+
});
|
|
4688
|
+
}
|
|
4689
|
+
|
|
4690
|
+
function walkDeclaredValue(args) {
|
|
4691
|
+
const {type: type, value: value, visit: visit} = args;
|
|
4692
|
+
return type === "actor" || type === "assignee" ? visitPrincipalObject(value, visit) : type === "assignees" ? Array.isArray(value) ? shareMap(value, item => visitPrincipalObject(item, visit)) : value : type === "object" ? walkDeclaredObject({
|
|
4693
|
+
value: value,
|
|
4694
|
+
shapes: args.fields,
|
|
4695
|
+
visit: visit
|
|
4696
|
+
}) : type === "array" && Array.isArray(value) ? shareMap(value, row => walkDeclaredObject({
|
|
4697
|
+
value: row,
|
|
4698
|
+
shapes: args.of,
|
|
4699
|
+
visit: visit
|
|
4700
|
+
})) : value;
|
|
4701
|
+
}
|
|
4702
|
+
|
|
4703
|
+
function walkDeclaredObject(args) {
|
|
4704
|
+
const {value: value, shapes: shapes, visit: visit} = args;
|
|
4705
|
+
if (value === null || typeof value != "object" || Array.isArray(value) || !Array.isArray(shapes)) return value;
|
|
4706
|
+
const record = value, patch = {};
|
|
4707
|
+
for (const shape of shapes) {
|
|
4708
|
+
const step = walkDeclaredProperty({
|
|
4709
|
+
record: record,
|
|
4710
|
+
shape: shape,
|
|
4711
|
+
visit: visit
|
|
4712
|
+
});
|
|
4713
|
+
step !== void 0 && (patch[step.name] = step.value);
|
|
4714
|
+
}
|
|
4715
|
+
return Object.keys(patch).length === 0 ? value : {
|
|
4716
|
+
...record,
|
|
4717
|
+
...patch
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
|
|
4721
|
+
function walkDeclaredProperty(args) {
|
|
4722
|
+
const {record: record, shape: shape, visit: visit} = args;
|
|
4723
|
+
if (shape === null || typeof shape != "object") return;
|
|
4724
|
+
const name = shape.name;
|
|
4725
|
+
if (typeof name != "string" || !Object.hasOwn(record, name)) return;
|
|
4726
|
+
const walked = walkDeclaredValue({
|
|
4727
|
+
type: shape.type,
|
|
4728
|
+
fields: shape.fields,
|
|
4729
|
+
of: shape.of,
|
|
4730
|
+
value: record[name],
|
|
4731
|
+
visit: visit
|
|
4732
|
+
});
|
|
4733
|
+
return walked === record[name] ? void 0 : {
|
|
4734
|
+
name: name,
|
|
4735
|
+
value: walked
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
|
|
4739
|
+
function visitPrincipalObject(value, visit) {
|
|
4740
|
+
if (value === null || typeof value != "object" || Array.isArray(value)) return value;
|
|
4741
|
+
const record = value;
|
|
4742
|
+
if (typeof record.id != "string" || record.type !== "user" && !(typeof record.kind == "string" && ACTOR_KIND_SET.has(record.kind))) return value;
|
|
4743
|
+
const stamped = visit(record.id) ?? record.id;
|
|
4744
|
+
return stamped === record.id ? value : {
|
|
4745
|
+
...record,
|
|
4746
|
+
id: stamped
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4749
|
+
|
|
4750
|
+
function shareMap(items, fn) {
|
|
4751
|
+
let changed = !1;
|
|
4752
|
+
const next = items.map(item => {
|
|
4753
|
+
const out = fn(item);
|
|
4754
|
+
return out !== item && (changed = !0), out;
|
|
4755
|
+
});
|
|
4756
|
+
return changed ? next : items;
|
|
4757
|
+
}
|
|
4758
|
+
|
|
4759
|
+
const SAFE_ID = /^[A-Za-z0-9_-]+$/;
|
|
4760
|
+
|
|
4761
|
+
async function resolveThroughDirectory(args) {
|
|
4762
|
+
const {client: client, projectId: projectId, ids: ids} = args, cache = cacheFor(unwrapRequestTag(client)), out = /* @__PURE__ */ new Map, safeMisses = ids.filter(id => {
|
|
4763
|
+
const hit = cache.get(id);
|
|
4764
|
+
return typeof hit == "string" && out.set(id, hit), hit === void 0;
|
|
4765
|
+
}).filter(id => SAFE_ID.test(id) && SAFE_ID.test(projectId));
|
|
4766
|
+
if (safeMisses.length === 0 || client.request === void 0) return out;
|
|
4767
|
+
try {
|
|
4768
|
+
const response = await client.request({
|
|
4769
|
+
uri: `/projects/${encodeURIComponent(projectId)}/users/${safeMisses.map(encodeURIComponent).join(",")}`,
|
|
4770
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
4771
|
+
});
|
|
4772
|
+
ingestDirectoryRows({
|
|
4773
|
+
response: response,
|
|
4774
|
+
requested: new Set(safeMisses),
|
|
4775
|
+
cache: cache,
|
|
4776
|
+
out: out
|
|
4777
|
+
});
|
|
4778
|
+
for (const id of safeMisses) out.has(id) || cache.set(id, null);
|
|
4779
|
+
} catch (err) {
|
|
4780
|
+
console.warn(`workflow: project-users directory lookup failed for project "${projectId}" — legacy principal ids stay unresolved this pass. Original error: ${errorMessage(err)}`);
|
|
4781
|
+
}
|
|
4782
|
+
return out;
|
|
4783
|
+
}
|
|
4784
|
+
|
|
4785
|
+
function cacheFor(client) {
|
|
4786
|
+
let cache = resolutionCache.get(client);
|
|
4787
|
+
return cache === void 0 && (cache = /* @__PURE__ */ new Map, resolutionCache.set(client, cache)),
|
|
4788
|
+
cache;
|
|
4789
|
+
}
|
|
4790
|
+
|
|
4791
|
+
function ingestDirectoryRows(args) {
|
|
4792
|
+
const records = Array.isArray(args.response) ? args.response : [ args.response ];
|
|
4793
|
+
for (const row of records) typeof row?.id != "string" || typeof row.sanityUserId != "string" || args.requested.has(row.id) && classifyPrincipalId(row.sanityUserId).namespace === "global" && (args.cache.set(row.id, row.sanityUserId),
|
|
4794
|
+
args.out.set(row.id, row.sanityUserId));
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
async function getInstanceDocument(client, instanceId) {
|
|
4798
|
+
const doc = await client.getDocument(instanceId);
|
|
4799
|
+
if (doc) return normalizeInstanceIdentities({
|
|
4800
|
+
client: client,
|
|
4801
|
+
instance: readInstanceDoc(doc)
|
|
4802
|
+
});
|
|
4803
|
+
}
|
|
4804
|
+
|
|
4805
|
+
function readInstanceDoc(doc) {
|
|
4806
|
+
return parseInstanceDocument(assertReadableModel(doc));
|
|
4807
|
+
}
|
|
4808
|
+
|
|
4809
|
+
async function reload({client: client, instanceId: instanceId, tag: tag}) {
|
|
4810
|
+
const doc = await getInstanceDocument(client, instanceId);
|
|
4811
|
+
if (!doc) throw new InstanceNotFoundError({
|
|
4812
|
+
instanceId: instanceId
|
|
4813
|
+
});
|
|
4814
|
+
if (doc.tag !== tag) throw new InstanceNotFoundError({
|
|
4815
|
+
instanceId: instanceId,
|
|
4816
|
+
detail: "not visible to this engine: tag mismatch"
|
|
4817
|
+
});
|
|
4818
|
+
return doc;
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
function contextEntry(name, value) {
|
|
4822
|
+
const _key = randomKey();
|
|
4823
|
+
return typeof value == "string" ? {
|
|
4824
|
+
_key: _key,
|
|
4825
|
+
_type: "context.string",
|
|
4826
|
+
name: name,
|
|
4827
|
+
value: value
|
|
4828
|
+
} : typeof value == "number" ? {
|
|
4829
|
+
_key: _key,
|
|
4830
|
+
_type: "context.number",
|
|
4831
|
+
name: name,
|
|
4832
|
+
value: value
|
|
4833
|
+
} : typeof value == "boolean" ? {
|
|
4834
|
+
_key: _key,
|
|
4835
|
+
_type: "context.boolean",
|
|
4836
|
+
name: name,
|
|
4837
|
+
value: value
|
|
4838
|
+
} : {
|
|
4839
|
+
_key: _key,
|
|
4840
|
+
_type: "context.ref",
|
|
4841
|
+
name: name,
|
|
4842
|
+
value: value
|
|
4843
|
+
};
|
|
4844
|
+
}
|
|
4845
|
+
|
|
4846
|
+
function contextJsonEntry(name, value) {
|
|
4847
|
+
return {
|
|
4848
|
+
_key: randomKey(),
|
|
4849
|
+
_type: "context.json",
|
|
4850
|
+
name: name,
|
|
4851
|
+
value: serializeContextValue(name, value)
|
|
4852
|
+
};
|
|
4853
|
+
}
|
|
4854
|
+
|
|
4855
|
+
function serializeContextValue(name, value) {
|
|
4856
|
+
let json;
|
|
4857
|
+
try {
|
|
4858
|
+
json = JSON.stringify(value);
|
|
4859
|
+
} catch (err) {
|
|
4860
|
+
rethrowWithContext(err, `context entry "${name}" holds unserializable JSON`);
|
|
4861
|
+
}
|
|
4862
|
+
if (json === void 0) throw new Error(`context entry "${name}" holds a non-JSON value (undefined, a function, or a symbol)`);
|
|
4863
|
+
return json;
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4866
|
+
function buildInstanceBase(args) {
|
|
4867
|
+
const {id: id, now: now, actor: actor, perspective: perspective, executionContext: executionContext} = args, entries = [ {
|
|
4868
|
+
_key: randomKey(),
|
|
4869
|
+
_type: "stageEntered",
|
|
4870
|
+
at: now,
|
|
4871
|
+
stage: args.initialStage,
|
|
4872
|
+
...actor !== void 0 ? {
|
|
4873
|
+
actor: actor
|
|
4874
|
+
} : {}
|
|
4875
|
+
}, ...args.extraHistory ?? [] ], history = executionContext !== void 0 ? stampHistoryEntries(entries, executionContext) : entries, body = {
|
|
4876
|
+
_id: id,
|
|
4877
|
+
_type: WORKFLOW_INSTANCE_TYPE,
|
|
4878
|
+
_rev: "",
|
|
4879
|
+
_createdAt: now,
|
|
4880
|
+
_updatedAt: now,
|
|
4881
|
+
tag: args.tag,
|
|
4882
|
+
workflowResource: args.workflowResource,
|
|
4883
|
+
definition: args.definitionName,
|
|
4884
|
+
pinnedVersion: args.pinnedVersion,
|
|
4885
|
+
...args.pinnedContentHash !== void 0 ? {
|
|
4886
|
+
pinnedContentHash: args.pinnedContentHash
|
|
4887
|
+
} : {},
|
|
4888
|
+
definitionSnapshot: JSON.stringify(args.definition),
|
|
4889
|
+
fields: args.fields,
|
|
4890
|
+
context: args.context,
|
|
4891
|
+
ancestors: args.ancestors,
|
|
4892
|
+
...perspective !== void 0 ? {
|
|
4893
|
+
perspective: perspective
|
|
4894
|
+
} : {},
|
|
4895
|
+
currentStage: args.initialStage,
|
|
4896
|
+
stages: [],
|
|
4897
|
+
subworkflows: [],
|
|
4898
|
+
pendingEffects: [],
|
|
4899
|
+
effectHistory: [],
|
|
4900
|
+
history: history,
|
|
4901
|
+
startedAt: now,
|
|
4902
|
+
lastChangedAt: now
|
|
4903
|
+
};
|
|
4904
|
+
return {
|
|
4905
|
+
...body,
|
|
4906
|
+
...modelStampFor({
|
|
4907
|
+
documentType: "instance",
|
|
4908
|
+
document: body
|
|
4909
|
+
})
|
|
4910
|
+
};
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4913
|
+
async function hydrateSnapshot(args) {
|
|
4914
|
+
const {client: client, clientForGdr: clientForGdr, instance: instance, overlay: overlay} = args, loaded = [], visited = /* @__PURE__ */ new Set;
|
|
4915
|
+
loaded.push({
|
|
4916
|
+
doc: instance,
|
|
4917
|
+
resource: instance.workflowResource
|
|
4918
|
+
}), visited.add(selfGdr(instance));
|
|
4919
|
+
const {pending: pending, ordered: ordered} = planReads({
|
|
4920
|
+
client: client,
|
|
4921
|
+
clientForGdr: clientForGdr,
|
|
4922
|
+
instance: instance,
|
|
4923
|
+
overlay: overlay,
|
|
4924
|
+
visited: visited
|
|
4925
|
+
}), fetched = await readPending(pending);
|
|
4926
|
+
for (const entry of ordered) if (!isPendingRead(entry)) loaded.push(entry); else {
|
|
4927
|
+
const doc = fetched.get(entry);
|
|
4928
|
+
doc !== void 0 && loaded.push({
|
|
4929
|
+
doc: doc,
|
|
4930
|
+
resource: entry.resource
|
|
4931
|
+
});
|
|
4932
|
+
}
|
|
4933
|
+
return buildSnapshot({
|
|
4934
|
+
docs: loaded
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
|
|
4938
|
+
function planReads(args) {
|
|
4939
|
+
const {client: client, clientForGdr: clientForGdr, instance: instance, overlay: overlay, visited: visited} = args, pending = [], ordered = [];
|
|
4940
|
+
for (const ref of collectWatchRefs(instance)) {
|
|
4941
|
+
if (visited.has(ref.id)) continue;
|
|
4942
|
+
visited.add(ref.id);
|
|
4943
|
+
const held = overlay?.get(ref.id);
|
|
4944
|
+
if (held !== void 0) ordered.push(held); else {
|
|
4945
|
+
const read = routeRead({
|
|
4946
|
+
defaultClient: client,
|
|
4947
|
+
clientForGdr: clientForGdr,
|
|
4948
|
+
defaultResource: instance.workflowResource,
|
|
4949
|
+
uri: ref.id,
|
|
4950
|
+
perspective: readsRaw(ref) ? "raw" : instance.perspective ?? DEFAULT_CONTENT_PERSPECTIVE
|
|
4951
|
+
});
|
|
4952
|
+
pending.push(read), ordered.push(read);
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
return {
|
|
4956
|
+
pending: pending,
|
|
4957
|
+
ordered: ordered
|
|
4958
|
+
};
|
|
4959
|
+
}
|
|
4960
|
+
|
|
4961
|
+
function isPendingRead(entry) {
|
|
4962
|
+
return "client" in entry;
|
|
4963
|
+
}
|
|
4964
|
+
|
|
4965
|
+
const SNAPSHOT_READ_BATCH_SIZE = 100, SNAPSHOT_READ_CONCURRENCY = 4, snapshotDocsQuery = "*[_id in $ids]";
|
|
4532
4966
|
|
|
4533
4967
|
function routeRead({defaultClient: defaultClient, clientForGdr: clientForGdr, defaultResource: defaultResource, uri: uri, perspective: perspective}) {
|
|
4534
4968
|
const parsed = tryParseGdr(uri);
|
|
@@ -4645,29 +5079,31 @@ async function loadContext({client: client, instanceId: instanceId, options: opt
|
|
|
4645
5079
|
if (!instance) throw new InstanceNotFoundError({
|
|
4646
5080
|
instanceId: instanceId
|
|
4647
5081
|
});
|
|
4648
|
-
|
|
5082
|
+
return buildEngineContext({
|
|
4649
5083
|
client: client,
|
|
4650
|
-
clientForGdr: clientForGdr,
|
|
5084
|
+
clientForGdr: options.clientForGdr,
|
|
5085
|
+
refSurface: options.refSurface,
|
|
4651
5086
|
instance: instance,
|
|
5087
|
+
definition: parseDefinitionSnapshot(instance),
|
|
5088
|
+
...options.actor !== void 0 ? {
|
|
5089
|
+
actor: options.actor
|
|
5090
|
+
} : {},
|
|
5091
|
+
...options.clock !== void 0 ? {
|
|
5092
|
+
clock: options.clock
|
|
5093
|
+
} : {},
|
|
5094
|
+
...options.executionContext !== void 0 ? {
|
|
5095
|
+
executionContext: options.executionContext
|
|
5096
|
+
} : {},
|
|
5097
|
+
...options.telemetry !== void 0 ? {
|
|
5098
|
+
telemetry: options.telemetry
|
|
5099
|
+
} : {},
|
|
4652
5100
|
...options.overlay !== void 0 ? {
|
|
4653
5101
|
overlay: options.overlay
|
|
5102
|
+
} : {},
|
|
5103
|
+
...options.settlingCohorts !== void 0 ? {
|
|
5104
|
+
settlingCohorts: options.settlingCohorts
|
|
4654
5105
|
} : {}
|
|
4655
5106
|
});
|
|
4656
|
-
return {
|
|
4657
|
-
client: client,
|
|
4658
|
-
clientForGdr: clientForGdr,
|
|
4659
|
-
refSurface: refSurface,
|
|
4660
|
-
clock: clock,
|
|
4661
|
-
now: clock(),
|
|
4662
|
-
executionContext: resolveExecutionContext(options?.executionContext),
|
|
4663
|
-
telemetry: resolveTelemetry(options.telemetry),
|
|
4664
|
-
...options?.actor !== void 0 ? {
|
|
4665
|
-
actor: options.actor
|
|
4666
|
-
} : {},
|
|
4667
|
-
instance: instance,
|
|
4668
|
-
definition: definition,
|
|
4669
|
-
snapshot: snapshot
|
|
4670
|
-
};
|
|
4671
5107
|
}
|
|
4672
5108
|
|
|
4673
5109
|
async function ctxConditionParams(ctx, opts) {
|
|
@@ -4705,6 +5141,9 @@ async function buildEngineContext(args) {
|
|
|
4705
5141
|
now: clock(),
|
|
4706
5142
|
executionContext: resolveExecutionContext(args.executionContext),
|
|
4707
5143
|
telemetry: resolveTelemetry(args.telemetry),
|
|
5144
|
+
...args.settlingCohorts !== void 0 ? {
|
|
5145
|
+
settlingCohorts: args.settlingCohorts
|
|
5146
|
+
} : {},
|
|
4708
5147
|
...args.actor !== void 0 ? {
|
|
4709
5148
|
actor: args.actor
|
|
4710
5149
|
} : {},
|
|
@@ -4713,7 +5152,10 @@ async function buildEngineContext(args) {
|
|
|
4713
5152
|
snapshot: await hydrateSnapshot({
|
|
4714
5153
|
client: client,
|
|
4715
5154
|
clientForGdr: clientForGdr,
|
|
4716
|
-
instance: instance
|
|
5155
|
+
instance: instance,
|
|
5156
|
+
...args.overlay !== void 0 ? {
|
|
5157
|
+
overlay: args.overlay
|
|
5158
|
+
} : {}
|
|
4717
5159
|
})
|
|
4718
5160
|
};
|
|
4719
5161
|
}
|
|
@@ -4836,10 +5278,6 @@ function recordProcessedRequest({mutation: mutation, record: record, now: now})
|
|
|
4836
5278
|
} ];
|
|
4837
5279
|
}
|
|
4838
5280
|
|
|
4839
|
-
const SYNC_COMMIT = {
|
|
4840
|
-
visibility: "sync"
|
|
4841
|
-
}, ENGINE_API_VERSION = "2026-04-29";
|
|
4842
|
-
|
|
4843
5281
|
function resolveGuardRead(args) {
|
|
4844
5282
|
const {expr: expr, ctx: ctx, deref: deref} = args;
|
|
4845
5283
|
if (expr === "$self") return selfGdr(ctx.instance);
|
|
@@ -4859,66 +5297,345 @@ function resolveGuardRead(args) {
|
|
|
4859
5297
|
const outputs = effectOutputsMap(ctx.instance)[effectsRead[1]];
|
|
4860
5298
|
return effectsRead[2] !== void 0 ? getPath(outputs, effectsRead[2]) : outputs;
|
|
4861
5299
|
}
|
|
4862
|
-
throw new Error(`Guard read "${expr}" is not a supported deploy-time value — use "$self", "$now", "$fields.<name>[.path]", or "$effects['<name>'][.path]" (guards store resolved values; the lake cannot see $fields or $effects)`);
|
|
5300
|
+
throw new Error(`Guard read "${expr}" is not a supported deploy-time value — use "$self", "$now", "$fields.<name>[.path]", or "$effects['<name>'][.path]" (guards store resolved values; the lake cannot see $fields or $effects)`);
|
|
5301
|
+
}
|
|
5302
|
+
|
|
5303
|
+
function resolveIdRefTarget(expr, ctx) {
|
|
5304
|
+
const value = resolveGuardRead({
|
|
5305
|
+
expr: expr,
|
|
5306
|
+
ctx: ctx,
|
|
5307
|
+
deref: !1
|
|
5308
|
+
});
|
|
5309
|
+
if (typeof value == "string" && isGdrUri(value)) return {
|
|
5310
|
+
parsed: parseGdr(value)
|
|
5311
|
+
};
|
|
5312
|
+
if (value && typeof value == "object") {
|
|
5313
|
+
const v2 = value;
|
|
5314
|
+
if (typeof v2.id == "string" && isGdrUri(v2.id)) return typeof v2.type == "string" ? {
|
|
5315
|
+
parsed: parseGdr(v2.id),
|
|
5316
|
+
type: v2.type
|
|
5317
|
+
} : {
|
|
5318
|
+
parsed: parseGdr(v2.id)
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
return null;
|
|
5322
|
+
}
|
|
5323
|
+
|
|
5324
|
+
function resolveIdRefTargets(idRefs, ctx) {
|
|
5325
|
+
const targets = [];
|
|
5326
|
+
for (const expr of idRefs ?? []) {
|
|
5327
|
+
const target = resolveIdRefTarget(expr, ctx);
|
|
5328
|
+
if (target === null) return null;
|
|
5329
|
+
targets.push(target);
|
|
5330
|
+
}
|
|
5331
|
+
return targets.length === 0 ? null : targets;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
function assertSingleResource(targets) {
|
|
5335
|
+
const resource = resourceFromParsed(targets[0].parsed);
|
|
5336
|
+
for (const g of targets) {
|
|
5337
|
+
const r = resourceFromParsed(g.parsed);
|
|
5338
|
+
if (r.type !== resource.type || r.id !== resource.id) throw new Error(`Guard targets span multiple resources (${resource.type}:${resource.id} vs ${r.type}:${r.id}); a guard is single-resource.`);
|
|
5339
|
+
}
|
|
5340
|
+
return resource;
|
|
5341
|
+
}
|
|
5342
|
+
|
|
5343
|
+
function bareIdRefs(targets) {
|
|
5344
|
+
return targets.flatMap(g => [ g.parsed.documentId, `drafts.${g.parsed.documentId}` ]);
|
|
5345
|
+
}
|
|
5346
|
+
|
|
5347
|
+
function resolveMatchTypes(targets, authorTypes) {
|
|
5348
|
+
if (authorTypes !== void 0) return authorTypes;
|
|
5349
|
+
const inferred = [ ...new Set(targets.map(g => g.type).filter(t => !!t)) ];
|
|
5350
|
+
return inferred.length > 0 ? inferred : void 0;
|
|
5351
|
+
}
|
|
5352
|
+
|
|
5353
|
+
function resolveMetadata(metadata, ctx) {
|
|
5354
|
+
const out = {};
|
|
5355
|
+
for (const [k, expr] of Object.entries(metadata ?? {})) out[k] = resolveGuardRead({
|
|
5356
|
+
expr: expr,
|
|
5357
|
+
ctx: ctx,
|
|
5358
|
+
deref: !0
|
|
5359
|
+
});
|
|
5360
|
+
return out;
|
|
5361
|
+
}
|
|
5362
|
+
|
|
5363
|
+
function isRecord(value) {
|
|
5364
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
5365
|
+
}
|
|
5366
|
+
|
|
5367
|
+
function isClientProjectUser(value) {
|
|
5368
|
+
return isRecord(value) && typeof value.id == "string" && (value.sanityUserId === void 0 || typeof value.sanityUserId == "string") && (value.displayName === void 0 || typeof value.displayName == "string") && (value.email === void 0 || typeof value.email == "string") && (value.imageUrl === void 0 || value.imageUrl === null || typeof value.imageUrl == "string");
|
|
5369
|
+
}
|
|
5370
|
+
|
|
5371
|
+
function objectProperty(value, property) {
|
|
5372
|
+
if (!isRecord(value)) return;
|
|
5373
|
+
const propertyValue = value[property];
|
|
5374
|
+
return typeof propertyValue == "object" && propertyValue !== null ? propertyValue : void 0;
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
function stringProperty(value, property) {
|
|
5378
|
+
const propertyValue = Reflect.get(value, property);
|
|
5379
|
+
return typeof propertyValue == "string" ? propertyValue : void 0;
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
function apiErrorType(error) {
|
|
5383
|
+
const response = objectProperty(error, "response"), body = objectProperty(response, "body");
|
|
5384
|
+
if (!body) return;
|
|
5385
|
+
const nestedError = objectProperty(body, "error");
|
|
5386
|
+
return (nestedError ? stringProperty(nestedError, "type") : void 0) ?? stringProperty(body, "type");
|
|
5387
|
+
}
|
|
5388
|
+
|
|
5389
|
+
function isProjectUserNotFoundError(error) {
|
|
5390
|
+
return apiErrorType(error) === "projectUserNotFoundError";
|
|
5391
|
+
}
|
|
5392
|
+
|
|
5393
|
+
const memberJoinCache = /* @__PURE__ */ new WeakMap;
|
|
5394
|
+
|
|
5395
|
+
function joinCacheFor(client) {
|
|
5396
|
+
let cache = memberJoinCache.get(client);
|
|
5397
|
+
return cache === void 0 && (cache = /* @__PURE__ */ new Map, memberJoinCache.set(client, cache)),
|
|
5398
|
+
cache;
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
async function projectMemberIds(request, projectId) {
|
|
5402
|
+
const project = await request({
|
|
5403
|
+
uri: `/projects/${encodeURIComponent(projectId)}`
|
|
5404
|
+
}), members = isRecord(project) ? project.members : void 0;
|
|
5405
|
+
return Array.isArray(members) ? members.map(member => isRecord(member) ? member.id : void 0).filter(id => typeof id == "string") : [];
|
|
5406
|
+
}
|
|
5407
|
+
|
|
5408
|
+
async function resolveGlobalProjectUser(args) {
|
|
5409
|
+
const {client: client, request: request, projectId: projectId, id: id} = args, cache = joinCacheFor(client), key = `${projectId}:${id}`, hit = cache.get(key);
|
|
5410
|
+
if (hit !== void 0) return hit === null ? {
|
|
5411
|
+
status: "missing"
|
|
5412
|
+
} : {
|
|
5413
|
+
status: "resolved",
|
|
5414
|
+
user: hit
|
|
5415
|
+
};
|
|
5416
|
+
try {
|
|
5417
|
+
await ingestMemberJoin({
|
|
5418
|
+
request: request,
|
|
5419
|
+
projectId: projectId,
|
|
5420
|
+
cache: cache
|
|
5421
|
+
});
|
|
5422
|
+
const found = cache.get(key);
|
|
5423
|
+
return found != null ? {
|
|
5424
|
+
status: "resolved",
|
|
5425
|
+
user: found
|
|
5426
|
+
} : (cache.set(key, null), {
|
|
5427
|
+
status: "missing"
|
|
5428
|
+
});
|
|
5429
|
+
} catch (cause) {
|
|
5430
|
+
return {
|
|
5431
|
+
status: "inaccessible",
|
|
5432
|
+
cause: cause
|
|
5433
|
+
};
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
|
|
5437
|
+
async function ingestMemberJoin(args) {
|
|
5438
|
+
const {request: request, projectId: projectId, cache: cache} = args, memberIds = await projectMemberIds(request, projectId);
|
|
5439
|
+
if (memberIds.length === 0) return;
|
|
5440
|
+
const response = await request({
|
|
5441
|
+
uri: `/projects/${encodeURIComponent(projectId)}/users/${memberIds.map(encodeURIComponent).join(",")}`
|
|
5442
|
+
});
|
|
5443
|
+
for (const row of Array.isArray(response) ? response : [ response ]) isClientProjectUser(row) && typeof row.sanityUserId == "string" && cache.set(`${projectId}:${row.sanityUserId}`, row);
|
|
5444
|
+
}
|
|
5445
|
+
|
|
5446
|
+
function clientProjectUserDirectory(client, projectId) {
|
|
5447
|
+
return {
|
|
5448
|
+
findById: async id => {
|
|
5449
|
+
if (!client.request) return {
|
|
5450
|
+
status: "inaccessible",
|
|
5451
|
+
cause: new Error("Project-user resolution requires WorkflowClient.request")
|
|
5452
|
+
};
|
|
5453
|
+
if (classifyPrincipalId(id).namespace === "global") return resolveGlobalProjectUser({
|
|
5454
|
+
client: client,
|
|
5455
|
+
request: client.request,
|
|
5456
|
+
projectId: projectId,
|
|
5457
|
+
id: id
|
|
5458
|
+
});
|
|
5459
|
+
try {
|
|
5460
|
+
const response = await client.request({
|
|
5461
|
+
uri: `/projects/${encodeURIComponent(projectId)}/users/${encodeURIComponent(id)}`
|
|
5462
|
+
}), candidate = Array.isArray(response) ? response[0] : response;
|
|
5463
|
+
return candidate == null ? {
|
|
5464
|
+
status: "missing"
|
|
5465
|
+
} : isClientProjectUser(candidate) ? {
|
|
5466
|
+
status: "resolved",
|
|
5467
|
+
user: candidate
|
|
5468
|
+
} : {
|
|
5469
|
+
status: "inaccessible",
|
|
5470
|
+
cause: new Error("Project-user response had an invalid shape")
|
|
5471
|
+
};
|
|
5472
|
+
} catch (cause) {
|
|
5473
|
+
return isProjectUserNotFoundError(cause) ? {
|
|
5474
|
+
status: "missing"
|
|
5475
|
+
} : {
|
|
5476
|
+
status: "inaccessible",
|
|
5477
|
+
cause: cause
|
|
5478
|
+
};
|
|
5479
|
+
}
|
|
5480
|
+
}
|
|
5481
|
+
};
|
|
5482
|
+
}
|
|
5483
|
+
|
|
5484
|
+
function resolveClientActor(client, args) {
|
|
5485
|
+
return resolveActor(clientProjectUserDirectory(client, args.projectId), args.actor);
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
async function resolveActor(directory, actor) {
|
|
5489
|
+
if (actor.kind !== "person") return {
|
|
5490
|
+
status: "not-person",
|
|
5491
|
+
actor: actor
|
|
5492
|
+
};
|
|
5493
|
+
const personActor = {
|
|
5494
|
+
...actor,
|
|
5495
|
+
kind: "person"
|
|
5496
|
+
}, lookup = await directory.findById(personActor.id);
|
|
5497
|
+
return lookup.status === "resolved" ? {
|
|
5498
|
+
status: "resolved",
|
|
5499
|
+
actor: personActor,
|
|
5500
|
+
user: lookup.user
|
|
5501
|
+
} : lookup.status === "inaccessible" ? {
|
|
5502
|
+
status: "inaccessible",
|
|
5503
|
+
actor: personActor,
|
|
5504
|
+
...lookup.cause === void 0 ? {} : {
|
|
5505
|
+
cause: lookup.cause
|
|
5506
|
+
}
|
|
5507
|
+
} : {
|
|
5508
|
+
status: "missing",
|
|
5509
|
+
actor: personActor
|
|
5510
|
+
};
|
|
5511
|
+
}
|
|
5512
|
+
|
|
5513
|
+
const IDENTITY_KINDS = /* @__PURE__ */ new Set([ "actor", "assignee", "assignees" ]);
|
|
5514
|
+
|
|
5515
|
+
async function localizeGuardMetadata(args) {
|
|
5516
|
+
const {doc: doc, guard: guard, client: client, instance: instance, definition: definition} = args;
|
|
5517
|
+
if (doc.resourceType !== "dataset" || client.request === void 0) return doc;
|
|
5518
|
+
const request = client.request, {projectId: projectId} = datasetResourceParts(doc.resourceId), shapes = metadataShapes({
|
|
5519
|
+
guard: guard,
|
|
5520
|
+
instance: instance,
|
|
5521
|
+
definition: definition
|
|
5522
|
+
}), globals = collectMetadataGlobals({
|
|
5523
|
+
metadata: doc.metadata,
|
|
5524
|
+
shapes: shapes
|
|
5525
|
+
});
|
|
5526
|
+
if (globals.size === 0) return doc;
|
|
5527
|
+
const map = /* @__PURE__ */ new Map;
|
|
5528
|
+
for (const id of globals) {
|
|
5529
|
+
const lookup = await resolveGlobalProjectUser({
|
|
5530
|
+
client: client,
|
|
5531
|
+
request: request,
|
|
5532
|
+
projectId: projectId,
|
|
5533
|
+
id: id
|
|
5534
|
+
});
|
|
5535
|
+
lookup.status === "resolved" && map.set(id, lookup.user.id);
|
|
5536
|
+
}
|
|
5537
|
+
return map.size === 0 ? doc : {
|
|
5538
|
+
...doc,
|
|
5539
|
+
metadata: rewriteMetadata({
|
|
5540
|
+
metadata: doc.metadata,
|
|
5541
|
+
shapes: shapes,
|
|
5542
|
+
map: map
|
|
5543
|
+
})
|
|
5544
|
+
};
|
|
4863
5545
|
}
|
|
4864
5546
|
|
|
4865
|
-
function
|
|
4866
|
-
const
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
if (value && typeof value == "object") {
|
|
4875
|
-
const v2 = value;
|
|
4876
|
-
if (typeof v2.id == "string" && isGdrUri(v2.id)) return typeof v2.type == "string" ? {
|
|
4877
|
-
parsed: parseGdr(v2.id),
|
|
4878
|
-
type: v2.type
|
|
4879
|
-
} : {
|
|
4880
|
-
parsed: parseGdr(v2.id)
|
|
4881
|
-
};
|
|
5547
|
+
function metadataShapes(args) {
|
|
5548
|
+
const out = /* @__PURE__ */ new Map;
|
|
5549
|
+
for (const [key, expr] of Object.entries(args.guard.metadata ?? {})) {
|
|
5550
|
+
const shape = shapeOfRead({
|
|
5551
|
+
expr: expr,
|
|
5552
|
+
instance: args.instance,
|
|
5553
|
+
definition: args.definition
|
|
5554
|
+
});
|
|
5555
|
+
shape !== void 0 && out.set(key, shape);
|
|
4882
5556
|
}
|
|
4883
|
-
return
|
|
5557
|
+
return out;
|
|
4884
5558
|
}
|
|
4885
5559
|
|
|
4886
|
-
function
|
|
4887
|
-
const
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
targets.push(target);
|
|
4892
|
-
}
|
|
4893
|
-
return targets.length === 0 ? null : targets;
|
|
5560
|
+
function shapeOfRead(args) {
|
|
5561
|
+
const fieldRead = FIELD_READ.exec(args.expr);
|
|
5562
|
+
if (fieldRead !== null) return shapeOfFieldRead(args.instance, fieldRead);
|
|
5563
|
+
const effectsRead = EFFECTS_READ.exec(args.expr);
|
|
5564
|
+
if (effectsRead !== null) return shapeOfEffectsRead(args.definition, effectsRead);
|
|
4894
5565
|
}
|
|
4895
5566
|
|
|
4896
|
-
function
|
|
4897
|
-
const
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
5567
|
+
function shapeOfFieldRead(instance, fieldRead) {
|
|
5568
|
+
const entry = (instance.fields ?? []).find(s => s.name === fieldRead[1]);
|
|
5569
|
+
if (entry !== void 0) return narrowByPath({
|
|
5570
|
+
type: entry._type,
|
|
5571
|
+
fields: Reflect.get(entry, "fields"),
|
|
5572
|
+
of: Reflect.get(entry, "of")
|
|
5573
|
+
}, fieldRead[2]);
|
|
4903
5574
|
}
|
|
4904
5575
|
|
|
4905
|
-
function
|
|
4906
|
-
|
|
5576
|
+
function shapeOfEffectsRead(definition, effectsRead) {
|
|
5577
|
+
const outputs = findEffect(definition, effectsRead[1])?.outputs ?? [], path = effectsRead[2];
|
|
5578
|
+
if (path === void 0) return;
|
|
5579
|
+
const [head, ...rest] = path.split("."), output = outputs.find(shape => shape.name === head);
|
|
5580
|
+
if (output !== void 0) return narrowByPath({
|
|
5581
|
+
type: output.type,
|
|
5582
|
+
fields: output.fields,
|
|
5583
|
+
of: output.of
|
|
5584
|
+
}, rest.length > 0 ? rest.join(".") : void 0);
|
|
4907
5585
|
}
|
|
4908
5586
|
|
|
4909
|
-
function
|
|
4910
|
-
if (
|
|
4911
|
-
|
|
4912
|
-
|
|
5587
|
+
function narrowByPath(shape, path) {
|
|
5588
|
+
if (path === void 0) return shape;
|
|
5589
|
+
if (typeof shape.type != "string" || !IDENTITY_KINDS.has(shape.type)) return;
|
|
5590
|
+
const steps = identityPathSteps(shape.type, path);
|
|
5591
|
+
if (steps === void 0) return;
|
|
5592
|
+
const itemType = shape.type === "assignees" ? "assignee" : shape.type;
|
|
5593
|
+
if (steps.length === 0) return {
|
|
5594
|
+
type: itemType
|
|
5595
|
+
};
|
|
5596
|
+
if (steps.length === 1 && steps[0] === "id") return {
|
|
5597
|
+
type: itemType,
|
|
5598
|
+
idLeaf: !0
|
|
5599
|
+
};
|
|
4913
5600
|
}
|
|
4914
5601
|
|
|
4915
|
-
function
|
|
4916
|
-
const
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
5602
|
+
function identityPathSteps(kind, path) {
|
|
5603
|
+
const segments = path.split(".");
|
|
5604
|
+
return kind !== "assignees" ? segments : /^\d+$/.test(segments[0] ?? "") ? segments.slice(1) : void 0;
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5607
|
+
function collectMetadataGlobals(args) {
|
|
5608
|
+
const found = /* @__PURE__ */ new Set;
|
|
5609
|
+
for (const [key, shape] of args.shapes) {
|
|
5610
|
+
const value = args.metadata[key];
|
|
5611
|
+
if (shape.idLeaf === !0) {
|
|
5612
|
+
typeof value == "string" && classifyPrincipalId(value).namespace === "global" && found.add(value);
|
|
5613
|
+
continue;
|
|
5614
|
+
}
|
|
5615
|
+
for (const id of collectDeclaredGlobalIds({
|
|
5616
|
+
...shape,
|
|
5617
|
+
value: value
|
|
5618
|
+
})) found.add(id);
|
|
5619
|
+
}
|
|
5620
|
+
return found;
|
|
5621
|
+
}
|
|
5622
|
+
|
|
5623
|
+
function rewriteMetadata(args) {
|
|
5624
|
+
const out = {
|
|
5625
|
+
...args.metadata
|
|
5626
|
+
};
|
|
5627
|
+
for (const [key, shape] of args.shapes) {
|
|
5628
|
+
const value = out[key];
|
|
5629
|
+
if (shape.idLeaf === !0) {
|
|
5630
|
+
typeof value == "string" && (out[key] = args.map.get(value) ?? value);
|
|
5631
|
+
continue;
|
|
5632
|
+
}
|
|
5633
|
+
out[key] = rewriteDeclaredPrincipalIds({
|
|
5634
|
+
...shape,
|
|
5635
|
+
value: value,
|
|
5636
|
+
map: args.map
|
|
5637
|
+
});
|
|
5638
|
+
}
|
|
4922
5639
|
return out;
|
|
4923
5640
|
}
|
|
4924
5641
|
|
|
@@ -4951,190 +5668,7 @@ function parseGuardDocument(doc) {
|
|
|
4951
5668
|
schema: MutationGuardDocSchema,
|
|
4952
5669
|
doc: doc,
|
|
4953
5670
|
docType: GUARD_DOC_TYPE
|
|
4954
|
-
});
|
|
4955
|
-
}
|
|
4956
|
-
|
|
4957
|
-
const REQUEST_TAG = {
|
|
4958
|
-
engine: "workflow",
|
|
4959
|
-
deploy: "workflow.deploy",
|
|
4960
|
-
deleteDefinition: "workflow.delete-definition",
|
|
4961
|
-
start: "workflow.start",
|
|
4962
|
-
fireAction: "workflow.fire-action",
|
|
4963
|
-
editField: "workflow.edit-field",
|
|
4964
|
-
completeEffect: "workflow.complete-effect",
|
|
4965
|
-
commitEffectOps: "workflow.commit-effect-ops",
|
|
4966
|
-
tick: "workflow.tick",
|
|
4967
|
-
evaluate: "workflow.evaluate",
|
|
4968
|
-
evaluateStart: "workflow.evaluate-start",
|
|
4969
|
-
diagnose: "workflow.diagnose",
|
|
4970
|
-
availableActions: "workflow.available-actions",
|
|
4971
|
-
setStage: "workflow.set-stage",
|
|
4972
|
-
abort: "workflow.abort",
|
|
4973
|
-
getInstance: "workflow.get-instance",
|
|
4974
|
-
children: "workflow.children",
|
|
4975
|
-
instancesForDocument: "workflow.instances-for-document",
|
|
4976
|
-
definitionsForDocument: "workflow.definitions-for-document",
|
|
4977
|
-
query: "workflow.query",
|
|
4978
|
-
discover: "workflow.discover",
|
|
4979
|
-
guardQuery: "workflow.guard.query",
|
|
4980
|
-
guardDeploy: "workflow.guard.deploy",
|
|
4981
|
-
guardRefresh: "workflow.guard.refresh",
|
|
4982
|
-
guardRetract: "workflow.guard.retract",
|
|
4983
|
-
effectList: "workflow.effect.list",
|
|
4984
|
-
effectFind: "workflow.effect.find",
|
|
4985
|
-
drain: "workflow.drain",
|
|
4986
|
-
effect: "workflow.effect",
|
|
4987
|
-
verifyDefinitions: "workflow.verify-definitions",
|
|
4988
|
-
accessResolveActor: "workflow.access.resolve-actor",
|
|
4989
|
-
accessGrants: "workflow.access.grants"
|
|
4990
|
-
}, RAW_PATCH = /* @__PURE__ */ Symbol("workflow-engine.raw-patch");
|
|
4991
|
-
|
|
4992
|
-
function unwrapPatch(patch) {
|
|
4993
|
-
return typeof patch == "object" && patch !== null && RAW_PATCH in patch ? patch[RAW_PATCH] : patch;
|
|
4994
|
-
}
|
|
4995
|
-
|
|
4996
|
-
const wrapperCache = /* @__PURE__ */ new WeakMap, effectHandlerClientCache = /* @__PURE__ */ new WeakMap, RAW_CLIENT = /* @__PURE__ */ Symbol("workflow-engine.raw-client");
|
|
4997
|
-
|
|
4998
|
-
function unwrapRequestTag(client) {
|
|
4999
|
-
let current = client;
|
|
5000
|
-
for (;RAW_CLIENT in current; ) current = current[RAW_CLIENT];
|
|
5001
|
-
return current;
|
|
5002
|
-
}
|
|
5003
|
-
|
|
5004
|
-
function withRequestTag(client, fallback) {
|
|
5005
|
-
let byTag = wrapperCache.get(client);
|
|
5006
|
-
byTag === void 0 && (byTag = /* @__PURE__ */ new Map, wrapperCache.set(client, byTag));
|
|
5007
|
-
const cached = byTag.get(fallback);
|
|
5008
|
-
if (cached !== void 0) return cached;
|
|
5009
|
-
const wrapped = buildTaggedClient(client, fallback);
|
|
5010
|
-
return byTag.set(fallback, wrapped), wrapped;
|
|
5011
|
-
}
|
|
5012
|
-
|
|
5013
|
-
function effectHandlerClient(client) {
|
|
5014
|
-
const cached = effectHandlerClientCache.get(client);
|
|
5015
|
-
if (cached !== void 0) return cached;
|
|
5016
|
-
let tagged;
|
|
5017
|
-
if (client.withConfig === void 0) tagged = withRequestTag(client, REQUEST_TAG.effect); else {
|
|
5018
|
-
const prefix = clientRequestTagPrefix(client), effectTag = composeRequestTag(prefix, REQUEST_TAG.effect);
|
|
5019
|
-
tagged = client.withConfig({
|
|
5020
|
-
requestTagPrefix: effectTag
|
|
5021
|
-
});
|
|
5022
|
-
}
|
|
5023
|
-
return effectHandlerClientCache.set(client, tagged), tagged;
|
|
5024
|
-
}
|
|
5025
|
-
|
|
5026
|
-
function effectHandlerResolver(resolver) {
|
|
5027
|
-
return mapResourceClientResolver(resolver, effectHandlerClient);
|
|
5028
|
-
}
|
|
5029
|
-
|
|
5030
|
-
function mapResourceClientResolver(resolver, mapClient) {
|
|
5031
|
-
if (resolver !== void 0) return parsed => {
|
|
5032
|
-
const client = resolver(parsed);
|
|
5033
|
-
return client === void 0 ? void 0 : mapClient(client);
|
|
5034
|
-
};
|
|
5035
|
-
}
|
|
5036
|
-
|
|
5037
|
-
function isWorkflowsFamilyPrefix(prefix) {
|
|
5038
|
-
return prefix === void 0 ? !1 : prefix === "sanity.workflows" || prefix.startsWith("sanity.workflows.") || prefix === "sanity.workflows-mcp";
|
|
5039
|
-
}
|
|
5040
|
-
|
|
5041
|
-
function clientRequestTagPrefix(client) {
|
|
5042
|
-
const probe = client;
|
|
5043
|
-
return typeof probe.config == "function" ? probe.config().requestTagPrefix : void 0;
|
|
5044
|
-
}
|
|
5045
|
-
|
|
5046
|
-
function composeRequestTag(prefix, tag) {
|
|
5047
|
-
if (prefix === void 0) return tag;
|
|
5048
|
-
const relative = isWorkflowsFamilyPrefix(prefix) ? stripWorkflowRoot(tag) : tag;
|
|
5049
|
-
return `${prefix}.${relative}`;
|
|
5050
|
-
}
|
|
5051
|
-
|
|
5052
|
-
function stripWorkflowRoot(tag) {
|
|
5053
|
-
return tag.startsWith("workflow.") ? tag.slice(9) : tag;
|
|
5054
|
-
}
|
|
5055
|
-
|
|
5056
|
-
function buildTaggedClient(client, fallback) {
|
|
5057
|
-
const strip = isWorkflowsFamilyPrefix(clientRequestTagPrefix(unwrapRequestTag(client))), normalize = tag => strip ? stripWorkflowRoot(tag) : tag, stamp = options => options === void 0 ? {
|
|
5058
|
-
tag: normalize(fallback)
|
|
5059
|
-
} : options.tag === void 0 ? {
|
|
5060
|
-
...options,
|
|
5061
|
-
tag: normalize(fallback)
|
|
5062
|
-
} : typeof options.tag == "string" && options.tag !== normalize(options.tag) ? {
|
|
5063
|
-
...options,
|
|
5064
|
-
tag: normalize(options.tag)
|
|
5065
|
-
} : options, wrapPatch = patch => {
|
|
5066
|
-
let target = patch;
|
|
5067
|
-
const wrapped = {
|
|
5068
|
-
get [RAW_PATCH]() {
|
|
5069
|
-
return target;
|
|
5070
|
-
},
|
|
5071
|
-
set: props => (target = target.set(props), wrapped),
|
|
5072
|
-
setIfMissing: props => (target = target.setIfMissing(props), wrapped),
|
|
5073
|
-
unset: paths => (target = target.unset(paths), wrapped),
|
|
5074
|
-
ifRevisionId: rev => (target = target.ifRevisionId(rev), wrapped),
|
|
5075
|
-
commit: options => target.commit(stamp(options))
|
|
5076
|
-
};
|
|
5077
|
-
return wrapped;
|
|
5078
|
-
}, wrapTransaction = tx => {
|
|
5079
|
-
let target = tx;
|
|
5080
|
-
const wrapped = {
|
|
5081
|
-
create: doc => (target = target.create(doc), wrapped),
|
|
5082
|
-
patch: patch => (target = target.patch(unwrapPatch(patch)), wrapped),
|
|
5083
|
-
delete: id => (target = target.delete(id), wrapped),
|
|
5084
|
-
commit: options => target.commit(stamp(options))
|
|
5085
|
-
};
|
|
5086
|
-
return wrapped;
|
|
5087
|
-
}, overrides = {
|
|
5088
|
-
[RAW_CLIENT]: unwrapRequestTag(client),
|
|
5089
|
-
fetch: (query, params, options) => client.fetch(query, params, stamp(options)),
|
|
5090
|
-
getDocument: (id, options) => client.getDocument(id, stamp(options)),
|
|
5091
|
-
patch: documentId => wrapPatch(client.patch(documentId)),
|
|
5092
|
-
create: (doc, options) => client.create(doc, stamp(options)),
|
|
5093
|
-
transaction: () => wrapTransaction(client.transaction()),
|
|
5094
|
-
...client.withConfig !== void 0 ? {
|
|
5095
|
-
withConfig: config => withRequestTag(client.withConfig(config), fallback)
|
|
5096
|
-
} : {},
|
|
5097
|
-
...client.action !== void 0 ? {
|
|
5098
|
-
action: (action, options) => client.action(action, stamp(options))
|
|
5099
|
-
} : {},
|
|
5100
|
-
...client.request !== void 0 ? {
|
|
5101
|
-
request: opts => client.request(stamp(opts))
|
|
5102
|
-
} : {}
|
|
5103
|
-
};
|
|
5104
|
-
return new Proxy(client, {
|
|
5105
|
-
has: (target, property) => Object.hasOwn(overrides, property) || property in target,
|
|
5106
|
-
get: (target, property) => {
|
|
5107
|
-
if (Object.hasOwn(overrides, property)) return Reflect.get(overrides, property, overrides);
|
|
5108
|
-
const value = Reflect.get(target, property, target);
|
|
5109
|
-
return typeof value == "function" ? value.bind(target) : value;
|
|
5110
|
-
}
|
|
5111
|
-
});
|
|
5112
|
-
}
|
|
5113
|
-
|
|
5114
|
-
const pinCache = /* @__PURE__ */ new WeakMap, enginePinned = /* @__PURE__ */ new WeakSet;
|
|
5115
|
-
|
|
5116
|
-
function pinApiVersion(client) {
|
|
5117
|
-
const raw = unwrapRequestTag(client);
|
|
5118
|
-
if (enginePinned.has(raw) || raw.withConfig === void 0) return client;
|
|
5119
|
-
let sibling = pinCache.get(raw);
|
|
5120
|
-
return sibling === void 0 && (sibling = raw.withConfig({
|
|
5121
|
-
apiVersion: ENGINE_API_VERSION
|
|
5122
|
-
}), pinCache.set(raw, sibling), enginePinned.add(unwrapRequestTag(sibling))), sibling;
|
|
5123
|
-
}
|
|
5124
|
-
|
|
5125
|
-
function taggedResolver(resolver, fallback) {
|
|
5126
|
-
return mapResourceClientResolver(resolver, client => withRequestTag(pinApiVersion(client), fallback));
|
|
5127
|
-
}
|
|
5128
|
-
|
|
5129
|
-
function taggedScope(args, tag) {
|
|
5130
|
-
const resourceClients = taggedResolver(args.resourceClients, tag);
|
|
5131
|
-
return {
|
|
5132
|
-
...args,
|
|
5133
|
-
client: withRequestTag(pinApiVersion(args.client), tag),
|
|
5134
|
-
...resourceClients !== void 0 ? {
|
|
5135
|
-
resourceClients: resourceClients
|
|
5136
|
-
} : {}
|
|
5137
|
-
};
|
|
5671
|
+
});
|
|
5138
5672
|
}
|
|
5139
5673
|
|
|
5140
5674
|
async function fetchGuards(args) {
|
|
@@ -5350,7 +5884,8 @@ function resolvedStageGuards(args) {
|
|
|
5350
5884
|
resolved !== null && out.push({
|
|
5351
5885
|
client: args.clientForGdr(resolved.routeGdr),
|
|
5352
5886
|
resourceKey: resourceGdr(resourceFromParsed(resolved.routeGdr)),
|
|
5353
|
-
value: resolved.doc
|
|
5887
|
+
value: resolved.doc,
|
|
5888
|
+
guard: guard
|
|
5354
5889
|
});
|
|
5355
5890
|
}
|
|
5356
5891
|
return out;
|
|
@@ -5424,11 +5959,18 @@ async function deployStageGuards(args) {
|
|
|
5424
5959
|
if (live === void 0 || live.currentStage !== args.stageName || live.abortedAt !== void 0) return;
|
|
5425
5960
|
const routed = resolvedStageGuards(args), existingByResource = await existingGuardIds(groupByResource(routed));
|
|
5426
5961
|
let deployed = 0;
|
|
5427
|
-
for (const {client: client, resourceKey: resourceKey, value: doc} of routed) {
|
|
5962
|
+
for (const {client: client, resourceKey: resourceKey, value: doc, guard: guard} of routed) {
|
|
5428
5963
|
try {
|
|
5964
|
+
const localized = await localizeGuardMetadata({
|
|
5965
|
+
doc: doc,
|
|
5966
|
+
guard: guard,
|
|
5967
|
+
client: client,
|
|
5968
|
+
instance: args.instance,
|
|
5969
|
+
definition: args.definition
|
|
5970
|
+
});
|
|
5429
5971
|
await upsertGuard({
|
|
5430
5972
|
client: client,
|
|
5431
|
-
doc:
|
|
5973
|
+
doc: localized,
|
|
5432
5974
|
exists: existingByResource.get(resourceKey)?.has(doc._id) ?? !1
|
|
5433
5975
|
});
|
|
5434
5976
|
} catch (cause) {
|
|
@@ -5548,7 +6090,8 @@ async function commitAbort({ctx: ctx, reason: reason, requestRecord: requestReco
|
|
|
5548
6090
|
...actor !== void 0 ? {
|
|
5549
6091
|
actor: actor
|
|
5550
6092
|
} : {}
|
|
5551
|
-
}), mutation.completedAt = at, mutation.abortedAt = at
|
|
6093
|
+
}), mutation.completedAt = at, mutation.abortedAt = at;
|
|
6094
|
+
const instance = readInstanceDoc(await persist(ctx, mutation));
|
|
5552
6095
|
await retractStageGuards({
|
|
5553
6096
|
client: ctx.client,
|
|
5554
6097
|
clientForGdr: ctx.clientForGdr,
|
|
@@ -5568,7 +6111,8 @@ async function commitAbort({ctx: ctx, reason: reason, requestRecord: requestReco
|
|
|
5568
6111
|
});
|
|
5569
6112
|
return {
|
|
5570
6113
|
fired: !0,
|
|
5571
|
-
stage: stage.name
|
|
6114
|
+
stage: stage.name,
|
|
6115
|
+
instance: instance
|
|
5572
6116
|
};
|
|
5573
6117
|
}
|
|
5574
6118
|
|
|
@@ -6319,18 +6863,42 @@ async function fetchGrants(args) {
|
|
|
6319
6863
|
});
|
|
6320
6864
|
}
|
|
6321
6865
|
|
|
6322
|
-
async function
|
|
6866
|
+
async function advisoryCanForCall(args) {
|
|
6867
|
+
const actor = args.options?.actor;
|
|
6868
|
+
if (!(args.options?.grants === void 0 || actor === void 0)) return advisoryCan({
|
|
6869
|
+
instance: args.instance,
|
|
6870
|
+
identity: lakePrincipalId({
|
|
6871
|
+
actor: actor,
|
|
6872
|
+
localPrincipalId: args.options.localPrincipalId
|
|
6873
|
+
}),
|
|
6874
|
+
grants: args.options.grants
|
|
6875
|
+
});
|
|
6876
|
+
}
|
|
6877
|
+
|
|
6878
|
+
async function advisoryCan({instance: instance, identity: identity, grants: grants}) {
|
|
6323
6879
|
if (grants === void 0) return;
|
|
6324
6880
|
const can = {};
|
|
6325
6881
|
for (const permission of DOCUMENT_VALUE_PERMISSIONS) can[permission] = await grantsPermissionOn({
|
|
6326
6882
|
document: instance,
|
|
6327
6883
|
grants: grants,
|
|
6328
6884
|
permission: permission,
|
|
6329
|
-
userId:
|
|
6885
|
+
userId: identity
|
|
6330
6886
|
});
|
|
6331
6887
|
return can;
|
|
6332
6888
|
}
|
|
6333
6889
|
|
|
6890
|
+
function requirementDescriptor(requirement) {
|
|
6891
|
+
return {
|
|
6892
|
+
name: requirement.name,
|
|
6893
|
+
...requirement.title !== void 0 ? {
|
|
6894
|
+
title: requirement.title
|
|
6895
|
+
} : {},
|
|
6896
|
+
...requirement.description !== void 0 ? {
|
|
6897
|
+
description: requirement.description
|
|
6898
|
+
} : {}
|
|
6899
|
+
};
|
|
6900
|
+
}
|
|
6901
|
+
|
|
6334
6902
|
function subjectDenialLabels(denied) {
|
|
6335
6903
|
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
6336
6904
|
}
|
|
@@ -6351,10 +6919,10 @@ class ActionDisabledError extends WorkflowError {
|
|
|
6351
6919
|
|
|
6352
6920
|
class StartNotAllowedError extends WorkflowError {
|
|
6353
6921
|
definition;
|
|
6354
|
-
|
|
6922
|
+
unmetRequirements;
|
|
6355
6923
|
constructor(args) {
|
|
6356
|
-
super("start-not-allowed", `startInstance refused
|
|
6357
|
-
this.name = "StartNotAllowedError", this.definition = args.definition, this.
|
|
6924
|
+
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
6925
|
+
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
6358
6926
|
}
|
|
6359
6927
|
}
|
|
6360
6928
|
|
|
@@ -6370,7 +6938,7 @@ const disabledReasonDetail = {
|
|
|
6370
6938
|
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
6371
6939
|
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
6372
6940
|
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
6373
|
-
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.join(", ")}`,
|
|
6941
|
+
"requirements-unmet": r => `unmet requirement(s): ${r.unmetRequirements.map(requirement => requirement.name).join(", ")}`,
|
|
6374
6942
|
"subject-permission-denied": r => `missing subject permission(s): ${subjectDenialLabels(r.denied).join(", ")}`
|
|
6375
6943
|
};
|
|
6376
6944
|
|
|
@@ -6439,11 +7007,10 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
|
|
|
6439
7007
|
}
|
|
6440
7008
|
});
|
|
6441
7009
|
if (action.filter !== void 0) {
|
|
6442
|
-
const can =
|
|
7010
|
+
const can = await advisoryCanForCall({
|
|
6443
7011
|
instance: ctx.instance,
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
}) : void 0;
|
|
7012
|
+
options: options
|
|
7013
|
+
});
|
|
6447
7014
|
if (!await ctxEvaluateCondition({
|
|
6448
7015
|
ctx: ctx,
|
|
6449
7016
|
condition: action.filter,
|
|
@@ -6696,30 +7263,12 @@ async function fireTriggeredAction({ctx: ctx, mutation: mutation, activity: acti
|
|
|
6696
7263
|
};
|
|
6697
7264
|
}
|
|
6698
7265
|
|
|
6699
|
-
async function primeInitialStage(
|
|
6700
|
-
const instance = await getInstanceDocument(client, instanceId);
|
|
7266
|
+
async function primeInitialStage(args) {
|
|
7267
|
+
const {client: client, instanceId: instanceId, refSurface: refSurface, clientForGdr: clientForGdr} = args, instance = await getInstanceDocument(client, instanceId);
|
|
6701
7268
|
if (!instance || instance.stages.length > 0) return;
|
|
6702
|
-
const
|
|
7269
|
+
const ctx = await buildCascadeStepContext(args, instance), {definition: definition} = ctx, stage = definition.stages.find(s => s.name === instance.currentStage);
|
|
6703
7270
|
if (stage === void 0) return;
|
|
6704
|
-
const ctx =
|
|
6705
|
-
client: client,
|
|
6706
|
-
clientForGdr: clientForGdr,
|
|
6707
|
-
refSurface: refSurface,
|
|
6708
|
-
instance: instance,
|
|
6709
|
-
definition: definition,
|
|
6710
|
-
...clock ? {
|
|
6711
|
-
clock: clock
|
|
6712
|
-
} : {},
|
|
6713
|
-
...actor ? {
|
|
6714
|
-
actor: actor
|
|
6715
|
-
} : {},
|
|
6716
|
-
...executionContext ? {
|
|
6717
|
-
executionContext: executionContext
|
|
6718
|
-
} : {},
|
|
6719
|
-
...telemetry ? {
|
|
6720
|
-
telemetry: telemetry
|
|
6721
|
-
} : {}
|
|
6722
|
-
}), now = ctx.now, discards = [], initialStageEntry = {
|
|
7271
|
+
const now = ctx.now, discards = [], initialStageEntry = {
|
|
6723
7272
|
_key: randomKey(),
|
|
6724
7273
|
name: stage.name,
|
|
6725
7274
|
enteredAt: now,
|
|
@@ -6788,29 +7337,37 @@ async function primeInitialStage({client: client, instanceId: instanceId, actor:
|
|
|
6788
7337
|
|
|
6789
7338
|
const CASCADE_LIMIT = 100;
|
|
6790
7339
|
|
|
6791
|
-
async function runCascadeHop({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
|
|
6792
|
-
const
|
|
7340
|
+
async function runCascadeHop({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts, instance: instance}) {
|
|
7341
|
+
const contextOptions = {
|
|
7342
|
+
clientForGdr: clientForGdr,
|
|
7343
|
+
refSurface: refSurface,
|
|
7344
|
+
...actor ? {
|
|
7345
|
+
actor: actor
|
|
7346
|
+
} : {},
|
|
7347
|
+
...clock ? {
|
|
7348
|
+
clock: clock
|
|
7349
|
+
} : {},
|
|
7350
|
+
...executionContext ? {
|
|
7351
|
+
executionContext: executionContext
|
|
7352
|
+
} : {},
|
|
7353
|
+
...telemetry ? {
|
|
7354
|
+
telemetry: telemetry
|
|
7355
|
+
} : {},
|
|
7356
|
+
...overlay ? {
|
|
7357
|
+
overlay: overlay
|
|
7358
|
+
} : {},
|
|
7359
|
+
...settlingCohorts ? {
|
|
7360
|
+
settlingCohorts: settlingCohorts
|
|
7361
|
+
} : {}
|
|
7362
|
+
}, ctx = instance === void 0 ? await loadContext({
|
|
6793
7363
|
client: client,
|
|
6794
7364
|
instanceId: instanceId,
|
|
6795
|
-
options:
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
...clock ? {
|
|
6802
|
-
clock: clock
|
|
6803
|
-
} : {},
|
|
6804
|
-
...executionContext ? {
|
|
6805
|
-
executionContext: executionContext
|
|
6806
|
-
} : {},
|
|
6807
|
-
...telemetry ? {
|
|
6808
|
-
telemetry: telemetry
|
|
6809
|
-
} : {},
|
|
6810
|
-
...overlay ? {
|
|
6811
|
-
overlay: overlay
|
|
6812
|
-
} : {}
|
|
6813
|
-
}
|
|
7365
|
+
options: contextOptions
|
|
7366
|
+
}) : await buildEngineContext({
|
|
7367
|
+
client: client,
|
|
7368
|
+
instance: instance,
|
|
7369
|
+
definition: parseDefinitionSnapshot(instance),
|
|
7370
|
+
...contextOptions
|
|
6814
7371
|
});
|
|
6815
7372
|
if (isTerminal(ctx)) return {
|
|
6816
7373
|
moved: !1
|
|
@@ -6840,10 +7397,10 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
6840
7397
|
});
|
|
6841
7398
|
}
|
|
6842
7399
|
|
|
6843
|
-
async function cascadeAutoTransitions({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
|
|
7400
|
+
async function cascadeAutoTransitions({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts}) {
|
|
6844
7401
|
let count = 0;
|
|
6845
7402
|
for (;;) {
|
|
6846
|
-
|
|
7403
|
+
const drained = await drainCondemnedChildren({
|
|
6847
7404
|
client: client,
|
|
6848
7405
|
instanceId: instanceId,
|
|
6849
7406
|
actor: actor,
|
|
@@ -6852,7 +7409,8 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
6852
7409
|
clock: clock,
|
|
6853
7410
|
executionContext: executionContext,
|
|
6854
7411
|
telemetry: telemetry
|
|
6855
|
-
})
|
|
7412
|
+
});
|
|
7413
|
+
if (!(await runCascadeHop({
|
|
6856
7414
|
client: client,
|
|
6857
7415
|
instanceId: instanceId,
|
|
6858
7416
|
actor: actor,
|
|
@@ -6861,7 +7419,11 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
6861
7419
|
clock: clock,
|
|
6862
7420
|
executionContext: executionContext,
|
|
6863
7421
|
telemetry: telemetry,
|
|
6864
|
-
overlay: overlay
|
|
7422
|
+
overlay: overlay,
|
|
7423
|
+
settlingCohorts: settlingCohorts,
|
|
7424
|
+
...drained.drained ? {} : {
|
|
7425
|
+
instance: drained.instance
|
|
7426
|
+
}
|
|
6865
7427
|
})).moved) return count;
|
|
6866
7428
|
if (count++, count >= CASCADE_LIMIT) throw new CascadeLimitError({
|
|
6867
7429
|
instanceId: instanceId,
|
|
@@ -6870,39 +7432,50 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
|
|
|
6870
7432
|
}
|
|
6871
7433
|
}
|
|
6872
7434
|
|
|
6873
|
-
async function drainCondemnedChildren({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining = /* @__PURE__ */ new Set}) {
|
|
6874
|
-
if (draining.has(instanceId)) return
|
|
7435
|
+
async function drainCondemnedChildren({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining = /* @__PURE__ */ new Set, instance: preloadedInstance}) {
|
|
7436
|
+
if (draining.has(instanceId)) return {
|
|
7437
|
+
instance: preloadedInstance,
|
|
7438
|
+
drained: !1
|
|
7439
|
+
};
|
|
6875
7440
|
draining.add(instanceId);
|
|
6876
|
-
const instance = await getInstanceDocument(client, instanceId);
|
|
6877
|
-
if (!instance) return
|
|
7441
|
+
const instance = preloadedInstance ?? await getInstanceDocument(client, instanceId);
|
|
7442
|
+
if (!instance) return {
|
|
7443
|
+
instance: void 0,
|
|
7444
|
+
drained: !1
|
|
7445
|
+
};
|
|
6878
7446
|
const condemned = condemnedSubworkflows(instance);
|
|
6879
|
-
if (condemned.length
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
7447
|
+
if (condemned.length === 0) return {
|
|
7448
|
+
instance: instance,
|
|
7449
|
+
drained: !1
|
|
7450
|
+
};
|
|
7451
|
+
for (const row of condemned) await settleCondemnedRow({
|
|
7452
|
+
client: client,
|
|
7453
|
+
ownerId: instanceId,
|
|
7454
|
+
row: row,
|
|
7455
|
+
actor: actor,
|
|
7456
|
+
clientForGdr: clientForGdr,
|
|
7457
|
+
refSurface: refSurface,
|
|
7458
|
+
clock: clock,
|
|
7459
|
+
executionContext: executionContext,
|
|
7460
|
+
telemetry: telemetry,
|
|
7461
|
+
draining: draining
|
|
7462
|
+
});
|
|
7463
|
+
return await stampDrainedRows({
|
|
7464
|
+
client: client,
|
|
7465
|
+
instance: instance,
|
|
7466
|
+
condemned: condemned,
|
|
7467
|
+
clock: clock,
|
|
7468
|
+
executionContext: executionContext
|
|
7469
|
+
}), {
|
|
7470
|
+
instance: instance,
|
|
7471
|
+
drained: !0
|
|
7472
|
+
};
|
|
6900
7473
|
}
|
|
6901
7474
|
|
|
6902
7475
|
async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining}) {
|
|
6903
7476
|
const childId = toBareId(row.ref.id);
|
|
6904
7477
|
try {
|
|
6905
|
-
await abortInstance({
|
|
7478
|
+
const result = await abortInstance({
|
|
6906
7479
|
client: client,
|
|
6907
7480
|
instanceId: childId,
|
|
6908
7481
|
reason: row.abortPending?.reason ?? "condemned by parent",
|
|
@@ -6922,7 +7495,8 @@ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, a
|
|
|
6922
7495
|
telemetry: telemetry
|
|
6923
7496
|
} : {}
|
|
6924
7497
|
}
|
|
6925
|
-
})
|
|
7498
|
+
});
|
|
7499
|
+
await drainCondemnedChildren({
|
|
6926
7500
|
client: client,
|
|
6927
7501
|
instanceId: childId,
|
|
6928
7502
|
actor: actor,
|
|
@@ -6931,7 +7505,10 @@ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, a
|
|
|
6931
7505
|
clock: clock,
|
|
6932
7506
|
executionContext: executionContext,
|
|
6933
7507
|
telemetry: telemetry,
|
|
6934
|
-
draining: draining
|
|
7508
|
+
draining: draining,
|
|
7509
|
+
...result.fired ? {
|
|
7510
|
+
instance: result.instance
|
|
7511
|
+
} : {}
|
|
6935
7512
|
});
|
|
6936
7513
|
} catch (cause) {
|
|
6937
7514
|
if (cause instanceof InstanceNotFoundError) return;
|
|
@@ -6944,9 +7521,7 @@ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, a
|
|
|
6944
7521
|
}
|
|
6945
7522
|
|
|
6946
7523
|
async function stampDrainedRows({client: client, instance: instance, condemned: condemned, clock: clock, executionContext: executionContext}) {
|
|
6947
|
-
const now = (clock ?? wallClock)(), stamp = resolveExecutionContext(executionContext), ids = condemned.map(row => toBareId(row.ref.id)),
|
|
6948
|
-
ids: ids
|
|
6949
|
-
}), byId = new Map(children.map(c => [ assertReadableModel(c)._id, c ])), condemnedKeys = new Set(condemned.map(row => row._key)), history = [ ...instance.history ], subworkflows = (instance.subworkflows ?? []).map(row => {
|
|
7524
|
+
const now = (clock ?? wallClock)(), stamp = resolveExecutionContext(executionContext), ids = condemned.map(row => toBareId(row.ref.id)), byId = await loadInstancesById(client, ids), condemnedKeys = new Set(condemned.map(row => row._key)), history = [ ...instance.history ], subworkflows = (instance.subworkflows ?? []).map(row => {
|
|
6950
7525
|
if (row.resolved !== void 0 || !condemnedKeys.has(row._key)) return row;
|
|
6951
7526
|
const child = byId.get(toBareId(row.ref.id)), resolved = child !== void 0 ? terminalResolution(child) : {
|
|
6952
7527
|
at: now,
|
|
@@ -6968,6 +7543,16 @@ async function stampDrainedRows({client: client, instance: instance, condemned:
|
|
|
6968
7543
|
}).ifRevisionId(instance._rev).commit(SYNC_COMMIT);
|
|
6969
7544
|
}
|
|
6970
7545
|
|
|
7546
|
+
async function loadInstancesById(client, ids) {
|
|
7547
|
+
const children = await client.fetch("*[_id in $ids]", {
|
|
7548
|
+
ids: ids
|
|
7549
|
+
});
|
|
7550
|
+
return new Map(children.filter(child => child._type === WORKFLOW_INSTANCE_TYPE).map(child => {
|
|
7551
|
+
const instance = readInstanceDoc(child);
|
|
7552
|
+
return [ instance._id, instance ];
|
|
7553
|
+
}));
|
|
7554
|
+
}
|
|
7555
|
+
|
|
6971
7556
|
function terminalResolution(child) {
|
|
6972
7557
|
const status = resolvedChildStatus(child);
|
|
6973
7558
|
if (!(status === void 0 || child.completedAt === void 0 || child.completedAt === null)) return {
|
|
@@ -6990,28 +7575,18 @@ function subworkflowResolvedEntry({row: row, at: at, status: status}) {
|
|
|
6990
7575
|
};
|
|
6991
7576
|
}
|
|
6992
7577
|
|
|
6993
|
-
async function propagateToAncestors(
|
|
6994
|
-
const loaded = await loadPropagationPair(
|
|
6995
|
-
if (loaded === void 0) return;
|
|
6996
|
-
const {child: child, parent: parent} = loaded, definition = parseDefinitionSnapshot(parent), ctx = await buildEngineContext({
|
|
7578
|
+
async function propagateToAncestors(args) {
|
|
7579
|
+
const {instance: instance, ...stepArgs} = args, {client: client, instanceId: instanceId} = stepArgs, loaded = await loadPropagationPair({
|
|
6997
7580
|
client: client,
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
definition: definition,
|
|
7002
|
-
...clock ? {
|
|
7003
|
-
clock: clock
|
|
7004
|
-
} : {},
|
|
7005
|
-
...actor ? {
|
|
7006
|
-
actor: actor
|
|
7007
|
-
} : {},
|
|
7008
|
-
...executionContext ? {
|
|
7009
|
-
executionContext: executionContext
|
|
7010
|
-
} : {},
|
|
7011
|
-
...telemetry ? {
|
|
7012
|
-
telemetry: telemetry
|
|
7581
|
+
instanceId: instanceId,
|
|
7582
|
+
...instance !== void 0 ? {
|
|
7583
|
+
instance: instance
|
|
7013
7584
|
} : {}
|
|
7014
|
-
})
|
|
7585
|
+
});
|
|
7586
|
+
if (loaded === void 0) return;
|
|
7587
|
+
const {child: child, parent: parent} = loaded;
|
|
7588
|
+
if (stepArgs.settlingCohorts?.has(parent._id)) return;
|
|
7589
|
+
const ctx = await buildCascadeStepContext(stepArgs, parent), mutation = startMutation(parent), row = mutation.subworkflows.find(r => toBareId(r.ref.id) === child._id);
|
|
7015
7590
|
if (row === void 0) {
|
|
7016
7591
|
await recordOrphanedPropagation({
|
|
7017
7592
|
ctx: ctx,
|
|
@@ -7026,29 +7601,11 @@ async function propagateToAncestors({client: client, instanceId: instanceId, act
|
|
|
7026
7601
|
child: child,
|
|
7027
7602
|
now: ctx.now
|
|
7028
7603
|
}), parentTerminal = parent.completedAt !== void 0;
|
|
7029
|
-
changed && await persist(ctx, mutation), !parentTerminal &&
|
|
7030
|
-
client: client,
|
|
7031
|
-
instanceId: parent._id,
|
|
7032
|
-
actor: actor,
|
|
7033
|
-
clientForGdr: clientForGdr,
|
|
7034
|
-
refSurface: refSurface,
|
|
7035
|
-
clock: clock,
|
|
7036
|
-
executionContext: executionContext,
|
|
7037
|
-
telemetry: telemetry
|
|
7038
|
-
}), await propagateToAncestors({
|
|
7039
|
-
client: client,
|
|
7040
|
-
instanceId: parent._id,
|
|
7041
|
-
actor: actor,
|
|
7042
|
-
clientForGdr: clientForGdr,
|
|
7043
|
-
refSurface: refSurface,
|
|
7044
|
-
clock: clock,
|
|
7045
|
-
executionContext: executionContext,
|
|
7046
|
-
telemetry: telemetry
|
|
7047
|
-
}));
|
|
7604
|
+
changed && await persist(ctx, mutation), !parentTerminal && await cascadeAndPropagateParent(stepArgs, parent);
|
|
7048
7605
|
}
|
|
7049
7606
|
|
|
7050
|
-
async function loadPropagationPair(client, instanceId) {
|
|
7051
|
-
const child = await getInstanceDocument(client, instanceId);
|
|
7607
|
+
async function loadPropagationPair({client: client, instanceId: instanceId, instance: instance}) {
|
|
7608
|
+
const child = instance ?? await getInstanceDocument(client, instanceId);
|
|
7052
7609
|
if (!child) return;
|
|
7053
7610
|
const parentGdr = parentRef(child);
|
|
7054
7611
|
if (parentGdr === void 0) return;
|
|
@@ -7059,6 +7616,83 @@ async function loadPropagationPair(client, instanceId) {
|
|
|
7059
7616
|
};
|
|
7060
7617
|
}
|
|
7061
7618
|
|
|
7619
|
+
async function propagateSpawnBatch(args) {
|
|
7620
|
+
const {childIds: childIds, ...stepArgs} = args, {client: client, instanceId: instanceId} = stepArgs, parent = await getInstanceDocument(client, instanceId);
|
|
7621
|
+
if (parent === void 0) return;
|
|
7622
|
+
const children = await loadInstancesById(client, childIds);
|
|
7623
|
+
if (children.size !== childIds.length) throw new Error(`Spawn batch for ${instanceId} could not reload every child`);
|
|
7624
|
+
const ctx = await buildCascadeStepContext(stepArgs, parent), mutation = startMutation(parent);
|
|
7625
|
+
stampSpawnBatch({
|
|
7626
|
+
mutation: mutation,
|
|
7627
|
+
parent: parent,
|
|
7628
|
+
children: children,
|
|
7629
|
+
childIds: childIds,
|
|
7630
|
+
now: ctx.now
|
|
7631
|
+
}) && await persist(ctx, mutation), parent.completedAt === void 0 && await cascadeAndPropagateParent(stepArgs, parent);
|
|
7632
|
+
}
|
|
7633
|
+
|
|
7634
|
+
async function buildCascadeStepContext(args, instance) {
|
|
7635
|
+
return buildEngineContext({
|
|
7636
|
+
client: args.client,
|
|
7637
|
+
clientForGdr: args.clientForGdr,
|
|
7638
|
+
refSurface: args.refSurface,
|
|
7639
|
+
instance: instance,
|
|
7640
|
+
definition: parseDefinitionSnapshot(instance),
|
|
7641
|
+
...args.clock ? {
|
|
7642
|
+
clock: args.clock
|
|
7643
|
+
} : {},
|
|
7644
|
+
...args.actor ? {
|
|
7645
|
+
actor: args.actor
|
|
7646
|
+
} : {},
|
|
7647
|
+
...args.executionContext ? {
|
|
7648
|
+
executionContext: args.executionContext
|
|
7649
|
+
} : {},
|
|
7650
|
+
...args.telemetry ? {
|
|
7651
|
+
telemetry: args.telemetry
|
|
7652
|
+
} : {},
|
|
7653
|
+
...args.settlingCohorts ? {
|
|
7654
|
+
settlingCohorts: args.settlingCohorts
|
|
7655
|
+
} : {}
|
|
7656
|
+
});
|
|
7657
|
+
}
|
|
7658
|
+
|
|
7659
|
+
async function cascadeAndPropagateParent(args, parent) {
|
|
7660
|
+
await cascadeAutoTransitions({
|
|
7661
|
+
...args,
|
|
7662
|
+
instanceId: parent._id
|
|
7663
|
+
}), await propagateToAncestors({
|
|
7664
|
+
...args,
|
|
7665
|
+
instanceId: parent._id
|
|
7666
|
+
});
|
|
7667
|
+
}
|
|
7668
|
+
|
|
7669
|
+
function stampSpawnBatch({mutation: mutation, parent: parent, children: children, childIds: childIds, now: now}) {
|
|
7670
|
+
let changed = !1;
|
|
7671
|
+
for (const childId of childIds) {
|
|
7672
|
+
const child = requireSpawnBatchChild({
|
|
7673
|
+
parent: parent,
|
|
7674
|
+
children: children,
|
|
7675
|
+
childId: childId
|
|
7676
|
+
}), row = mutation.subworkflows.find(entry => toBareId(entry.ref.id) === childId);
|
|
7677
|
+
if (row === void 0) throw new Error(`Spawn batch child ${childId} has no registry row on parent ${parent._id}`);
|
|
7678
|
+
changed = stampResolvedChild({
|
|
7679
|
+
mutation: mutation,
|
|
7680
|
+
row: row,
|
|
7681
|
+
child: child,
|
|
7682
|
+
now: now
|
|
7683
|
+
}) || changed;
|
|
7684
|
+
}
|
|
7685
|
+
return changed;
|
|
7686
|
+
}
|
|
7687
|
+
|
|
7688
|
+
function requireSpawnBatchChild({parent: parent, children: children, childId: childId}) {
|
|
7689
|
+
const child = children.get(childId);
|
|
7690
|
+
if (child === void 0) throw new Error(`Spawn batch child ${childId} disappeared`);
|
|
7691
|
+
const expectedParent = parentRef(child);
|
|
7692
|
+
if (expectedParent === void 0 || toBareId(expectedParent.id) !== parent._id) throw new Error(`Spawn batch child ${childId} does not belong to parent ${parent._id}`);
|
|
7693
|
+
return child;
|
|
7694
|
+
}
|
|
7695
|
+
|
|
7062
7696
|
function stampResolvedChild({mutation: mutation, row: row, child: child, now: now}) {
|
|
7063
7697
|
if (row.resolved !== void 0) return !1;
|
|
7064
7698
|
const resolved = terminalResolution(child);
|
|
@@ -7194,36 +7828,14 @@ async function persist(ctx, mutation) {
|
|
|
7194
7828
|
for (const {body: body} of pendingCreates) tx.create(body);
|
|
7195
7829
|
tx.patch(ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev)),
|
|
7196
7830
|
await tx.commit(), mutation.pendingCreates = [];
|
|
7197
|
-
const actorForPriming = ctx.actor;
|
|
7198
|
-
for (const {body: body
|
|
7199
|
-
|
|
7200
|
-
client: ctx.client,
|
|
7201
|
-
instanceId: body._id,
|
|
7202
|
-
actor: actorForPriming,
|
|
7203
|
-
clientForGdr: ctx.clientForGdr,
|
|
7204
|
-
refSurface: ctx.refSurface,
|
|
7205
|
-
clock: ctx.clock,
|
|
7206
|
-
executionContext: ctx.executionContext,
|
|
7207
|
-
telemetry: ctx.telemetry
|
|
7208
|
-
}), await cascadeAutoTransitions({
|
|
7209
|
-
client: ctx.client,
|
|
7210
|
-
instanceId: body._id,
|
|
7211
|
-
actor: actorForPriming,
|
|
7212
|
-
clientForGdr: ctx.clientForGdr,
|
|
7213
|
-
refSurface: ctx.refSurface,
|
|
7214
|
-
clock: ctx.clock,
|
|
7215
|
-
executionContext: ctx.executionContext,
|
|
7216
|
-
telemetry: ctx.telemetry
|
|
7217
|
-
}), await propagateToAncestors({
|
|
7218
|
-
client: ctx.client,
|
|
7831
|
+
const actorForPriming = ctx.actor, settlingCohorts = new Set(ctx.settlingCohorts).add(ctx.instance._id);
|
|
7832
|
+
for (const {body: body} of pendingCreates) try {
|
|
7833
|
+
const stepArgs = spawnStepArgs(ctx, {
|
|
7219
7834
|
instanceId: body._id,
|
|
7220
7835
|
actor: actorForPriming,
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
executionContext: ctx.executionContext,
|
|
7225
|
-
telemetry: ctx.telemetry
|
|
7226
|
-
}), ctx.telemetry.log(WorkflowInstanceStarted, started);
|
|
7836
|
+
settlingCohorts: settlingCohorts
|
|
7837
|
+
});
|
|
7838
|
+
await primeInitialStage(stepArgs), await cascadeAutoTransitions(stepArgs);
|
|
7227
7839
|
} catch (cause) {
|
|
7228
7840
|
throw cause instanceof WorkflowStateDivergedError ? cause : new WorkflowStateDivergedError({
|
|
7229
7841
|
instanceId: ctx.instance._id,
|
|
@@ -7231,11 +7843,50 @@ async function persist(ctx, mutation) {
|
|
|
7231
7843
|
reason: `spawned child "${body._id}" failed to settle after the spawn transaction committed`
|
|
7232
7844
|
});
|
|
7233
7845
|
}
|
|
7846
|
+
await settleSpawnBatch(ctx, {
|
|
7847
|
+
pendingCreates: pendingCreates,
|
|
7848
|
+
actor: actorForPriming,
|
|
7849
|
+
settlingCohorts: settlingCohorts
|
|
7850
|
+
});
|
|
7851
|
+
for (const {started: started} of pendingCreates) ctx.telemetry.log(WorkflowInstanceStarted, started);
|
|
7234
7852
|
const reloaded = await getInstanceDocument(ctx.client, ctx.instance._id);
|
|
7235
7853
|
if (!reloaded) throw new Error(`Instance ${ctx.instance._id} disappeared after transaction commit`);
|
|
7236
7854
|
return reloaded;
|
|
7237
7855
|
}
|
|
7238
7856
|
|
|
7857
|
+
async function settleSpawnBatch(ctx, args) {
|
|
7858
|
+
try {
|
|
7859
|
+
await propagateSpawnBatch({
|
|
7860
|
+
...spawnStepArgs(ctx, {
|
|
7861
|
+
instanceId: ctx.instance._id,
|
|
7862
|
+
actor: args.actor,
|
|
7863
|
+
settlingCohorts: args.settlingCohorts
|
|
7864
|
+
}),
|
|
7865
|
+
childIds: args.pendingCreates.map(({body: body}) => body._id)
|
|
7866
|
+
});
|
|
7867
|
+
} catch (cause) {
|
|
7868
|
+
throw cause instanceof WorkflowStateDivergedError ? cause : new WorkflowStateDivergedError({
|
|
7869
|
+
instanceId: ctx.instance._id,
|
|
7870
|
+
guardError: cause,
|
|
7871
|
+
reason: "spawned children failed to propagate after the spawn transaction committed"
|
|
7872
|
+
});
|
|
7873
|
+
}
|
|
7874
|
+
}
|
|
7875
|
+
|
|
7876
|
+
function spawnStepArgs(ctx, args) {
|
|
7877
|
+
return {
|
|
7878
|
+
client: ctx.client,
|
|
7879
|
+
instanceId: args.instanceId,
|
|
7880
|
+
actor: args.actor,
|
|
7881
|
+
clientForGdr: ctx.clientForGdr,
|
|
7882
|
+
refSurface: ctx.refSurface,
|
|
7883
|
+
clock: ctx.clock,
|
|
7884
|
+
executionContext: ctx.executionContext,
|
|
7885
|
+
telemetry: ctx.telemetry,
|
|
7886
|
+
settlingCohorts: args.settlingCohorts ?? ctx.settlingCohorts
|
|
7887
|
+
};
|
|
7888
|
+
}
|
|
7889
|
+
|
|
7239
7890
|
function stampExecutionContext(ctx, mutation) {
|
|
7240
7891
|
const stamp = ctx.executionContext, appended = mutation.history.slice(ctx.instance.history.length);
|
|
7241
7892
|
mutation.history = [ ...mutation.history.slice(0, ctx.instance.history.length), ...stampHistoryEntries(appended, stamp) ];
|
|
@@ -7363,24 +8014,25 @@ function buildEffectSettlement(pending, outcome) {
|
|
|
7363
8014
|
}
|
|
7364
8015
|
|
|
7365
8016
|
function validateEffectOutputs(args) {
|
|
7366
|
-
const {outputs: outputs, declared: declared, effectName: effectName} = args, byName = new Map(declared.map(shape => [ shape.name, shape ])), issues = [];
|
|
8017
|
+
const {outputs: outputs, declared: declared, effectName: effectName} = args, byName = new Map(declared.map(shape => [ shape.name, shape ])), issues = [], normalized = {};
|
|
7367
8018
|
for (const [key, value] of Object.entries(outputs)) {
|
|
7368
8019
|
const shape = byName.get(key);
|
|
7369
8020
|
if (shape === void 0) {
|
|
7370
8021
|
issues.push(`"${key}" is not a declared output`);
|
|
7371
8022
|
continue;
|
|
7372
8023
|
}
|
|
7373
|
-
const
|
|
7374
|
-
|
|
8024
|
+
const check = effectOutputCheck(shape, value);
|
|
8025
|
+
"issues" in check ? issues.push(...check.issues.map(i => `"${key}": ${i}`)) : normalized[key] = check.output;
|
|
7375
8026
|
}
|
|
7376
8027
|
if (issues.length > 0) throw new EffectOutputsInvalidError({
|
|
7377
8028
|
effect: effectName,
|
|
7378
8029
|
issues: issues
|
|
7379
8030
|
});
|
|
8031
|
+
return normalized;
|
|
7380
8032
|
}
|
|
7381
8033
|
|
|
7382
|
-
function
|
|
7383
|
-
return
|
|
8034
|
+
function effectOutputCheck(shape, value) {
|
|
8035
|
+
return parseFieldValue({
|
|
7384
8036
|
entryType: shape.type,
|
|
7385
8037
|
value: value,
|
|
7386
8038
|
...shape.fields !== void 0 ? {
|
|
@@ -7426,15 +8078,15 @@ function validateCompletionInput({pending: pending, definition: definition, stat
|
|
|
7426
8078
|
effect: pending.name,
|
|
7427
8079
|
issues: [ "outputs cannot accompany a failed completion — report outputs on a done completion instead" ]
|
|
7428
8080
|
});
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
8081
|
+
const normalizedOutputs = outputs !== void 0 ? validateEffectOutputs({
|
|
8082
|
+
outputs: outputs,
|
|
8083
|
+
declared: findEffect(definition, pending.name)?.outputs ?? [],
|
|
8084
|
+
effectName: pending.name
|
|
8085
|
+
}) : void 0;
|
|
8086
|
+
return {
|
|
8087
|
+
ops: ops !== void 0 ? validateEffectOps(ops, pending.name) : [],
|
|
8088
|
+
outputs: normalizedOutputs
|
|
8089
|
+
};
|
|
7438
8090
|
}
|
|
7439
8091
|
|
|
7440
8092
|
async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: status, outputs: outputs, ops: ops, detail: detail, error: error, durationMs: durationMs, requestRecord: requestRecord, actor: actor}) {
|
|
@@ -7443,7 +8095,7 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
|
|
|
7443
8095
|
record: requestRecord,
|
|
7444
8096
|
now: ctx.now
|
|
7445
8097
|
});
|
|
7446
|
-
const pending = requirePendingEffect(ctx.instance, effectKey), validatedOps = validateCompletionInput({
|
|
8098
|
+
const pending = requirePendingEffect(ctx.instance, effectKey), {ops: validatedOps, outputs: validatedOutputs} = validateCompletionInput({
|
|
7447
8099
|
pending: pending,
|
|
7448
8100
|
definition: ctx.definition,
|
|
7449
8101
|
status: status,
|
|
@@ -7462,7 +8114,7 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
|
|
|
7462
8114
|
detail: detail,
|
|
7463
8115
|
error: error,
|
|
7464
8116
|
durationMs: durationMs,
|
|
7465
|
-
outputs:
|
|
8117
|
+
outputs: validatedOutputs
|
|
7466
8118
|
});
|
|
7467
8119
|
mutation.effectHistory.push(settlement.run);
|
|
7468
8120
|
const wroteEffectOutputs = status === "done" && outputs !== void 0;
|
|
@@ -7660,6 +8312,64 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
7660
8312
|
};
|
|
7661
8313
|
}
|
|
7662
8314
|
|
|
8315
|
+
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
8316
|
+
|
|
8317
|
+
function isResetActivityTarget(value) {
|
|
8318
|
+
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
8319
|
+
}
|
|
8320
|
+
|
|
8321
|
+
async function resetActivity(args) {
|
|
8322
|
+
const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
|
|
8323
|
+
client: client,
|
|
8324
|
+
instanceId: instanceId,
|
|
8325
|
+
options: options
|
|
8326
|
+
});
|
|
8327
|
+
return commitResetActivity({
|
|
8328
|
+
ctx: ctx,
|
|
8329
|
+
activity: activity,
|
|
8330
|
+
to: to,
|
|
8331
|
+
requestRecord: requestRecord,
|
|
8332
|
+
actor: options?.actor
|
|
8333
|
+
});
|
|
8334
|
+
}
|
|
8335
|
+
|
|
8336
|
+
async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
|
|
8337
|
+
if (assertRequestUnprocessed({
|
|
8338
|
+
instance: ctx.instance,
|
|
8339
|
+
record: requestRecord,
|
|
8340
|
+
now: ctx.now
|
|
8341
|
+
}), isTerminal(ctx)) return {
|
|
8342
|
+
fired: !1
|
|
8343
|
+
};
|
|
8344
|
+
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
8345
|
+
if (openStage2 === void 0 || entry === void 0) throw new ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
8346
|
+
const from = entry.status;
|
|
8347
|
+
if (from === to) return {
|
|
8348
|
+
fired: !1
|
|
8349
|
+
};
|
|
8350
|
+
if (!isTerminalActivityStatus(from)) throw new ContractViolationError(`resetActivity: activity "${activity}" is "${from}", not a terminal status — a reset only recovers a resolved (typically failed) activity. Use setStage to force past a live stage.`);
|
|
8351
|
+
return recordProcessedRequest({
|
|
8352
|
+
mutation: mutation,
|
|
8353
|
+
record: requestRecord,
|
|
8354
|
+
now: ctx.now
|
|
8355
|
+
}), applyActivityStatusChange({
|
|
8356
|
+
entry: entry,
|
|
8357
|
+
history: mutation.history,
|
|
8358
|
+
stage: openStage2.name,
|
|
8359
|
+
to: to,
|
|
8360
|
+
at: ctx.now,
|
|
8361
|
+
...actor !== void 0 ? {
|
|
8362
|
+
actor: actor
|
|
8363
|
+
} : {}
|
|
8364
|
+
}), await persist(ctx, mutation), {
|
|
8365
|
+
fired: !0,
|
|
8366
|
+
stage: openStage2.name,
|
|
8367
|
+
activity: activity,
|
|
8368
|
+
from: from,
|
|
8369
|
+
to: to
|
|
8370
|
+
};
|
|
8371
|
+
}
|
|
8372
|
+
|
|
7663
8373
|
const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap;
|
|
7664
8374
|
|
|
7665
8375
|
async function resolveAccess(taggedClient, args = {}) {
|
|
@@ -7669,10 +8379,13 @@ async function resolveAccess(taggedClient, args = {}) {
|
|
|
7669
8379
|
client: client,
|
|
7670
8380
|
requestFn: requestFn,
|
|
7671
8381
|
resourcePath: args.grantsFromPath
|
|
7672
|
-
}) : Promise.resolve(void 0), [
|
|
7673
|
-
if (
|
|
8382
|
+
}) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
|
|
8383
|
+
if (identity === void 0) throw new ContractViolationError("workflow: failed to resolve actor from `/users/me`. The client is configured but the endpoint returned no usable identity — check the token.");
|
|
7674
8384
|
return {
|
|
7675
|
-
actor: actor,
|
|
8385
|
+
actor: identity.actor,
|
|
8386
|
+
...identity.localPrincipalId !== void 0 ? {
|
|
8387
|
+
localPrincipalId: identity.localPrincipalId
|
|
8388
|
+
} : {},
|
|
7676
8389
|
...grants !== void 0 ? {
|
|
7677
8390
|
grants: grants
|
|
7678
8391
|
} : {}
|
|
@@ -7682,7 +8395,7 @@ async function resolveAccess(taggedClient, args = {}) {
|
|
|
7682
8395
|
function cachedActor(client, requestFn) {
|
|
7683
8396
|
const cached = actorCache.get(client);
|
|
7684
8397
|
if (cached !== void 0) return cached;
|
|
7685
|
-
const pending = fetchActor(requestFn).catch(err => {
|
|
8398
|
+
const pending = fetchActor(client, requestFn).catch(err => {
|
|
7686
8399
|
throw actorCache.get(client) === pending && actorCache.delete(client), err;
|
|
7687
8400
|
});
|
|
7688
8401
|
return actorCache.set(client, pending), pending;
|
|
@@ -7709,27 +8422,90 @@ function cachedGrants({client: client, requestFn: requestFn, resourcePath: resou
|
|
|
7709
8422
|
byPath.set(resourcePath, cached)), cached;
|
|
7710
8423
|
}
|
|
7711
8424
|
|
|
7712
|
-
async function fetchActor(requestFn) {
|
|
7713
|
-
|
|
8425
|
+
async function fetchActor(client, requestFn) {
|
|
8426
|
+
const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalId = usableId(globalUser.user), id = globalId ?? resourceId;
|
|
8427
|
+
if (id === void 0) return;
|
|
8428
|
+
refuseProjectPrincipalWithoutGlobal({
|
|
8429
|
+
resourceId: resourceId,
|
|
8430
|
+
globalId: globalId,
|
|
8431
|
+
globalUser: globalUser
|
|
8432
|
+
});
|
|
8433
|
+
const roleNames = (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
|
|
8434
|
+
return {
|
|
8435
|
+
actor: {
|
|
8436
|
+
kind: "person",
|
|
8437
|
+
id: id,
|
|
8438
|
+
...roleNames.length > 0 ? {
|
|
8439
|
+
roles: roleNames
|
|
8440
|
+
} : {}
|
|
8441
|
+
},
|
|
8442
|
+
...resourceId !== void 0 && resourceId !== id ? {
|
|
8443
|
+
localPrincipalId: resourceId
|
|
8444
|
+
} : {}
|
|
8445
|
+
};
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8448
|
+
function refuseProjectPrincipalWithoutGlobal(args) {
|
|
8449
|
+
const {resourceId: resourceId, globalId: globalId, globalUser: globalUser} = args;
|
|
8450
|
+
if (globalId !== void 0 || resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project") return;
|
|
8451
|
+
const reason = "reason" in globalUser ? globalUser.reason : "no record";
|
|
8452
|
+
throw new Error(`workflow: the caller's identity on the workflow resource host is project-scoped ("${resourceId}") and the account-global record could not be resolved (${reason}). The engine speaks account-global user ids only and never acts as a project-scoped principal.`, "cause" in globalUser ? {
|
|
8453
|
+
cause: globalUser.cause
|
|
8454
|
+
} : void 0);
|
|
8455
|
+
}
|
|
8456
|
+
|
|
8457
|
+
function usableId(user) {
|
|
8458
|
+
if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
|
|
8459
|
+
}
|
|
8460
|
+
|
|
8461
|
+
async function fetchCurrentUser(requestFn, hostDescription) {
|
|
7714
8462
|
try {
|
|
7715
|
-
|
|
8463
|
+
return await requestFn({
|
|
7716
8464
|
uri: "/users/me",
|
|
7717
8465
|
tag: REQUEST_TAG.accessResolveActor
|
|
7718
8466
|
});
|
|
7719
8467
|
} catch (err) {
|
|
7720
|
-
throw new Error(
|
|
8468
|
+
throw new Error(`workflow: /users/me request against ${hostDescription} failed. The engine resolves the actor from the client's token via \`client.request({ uri: '/users/me' })\`. Check the token/connectivity.`, {
|
|
7721
8469
|
cause: err
|
|
7722
8470
|
});
|
|
7723
8471
|
}
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
roles: roleNames
|
|
7731
|
-
} : {}
|
|
8472
|
+
}
|
|
8473
|
+
|
|
8474
|
+
async function fetchGlobalUser(client) {
|
|
8475
|
+
if (typeof client.withConfig != "function") return {
|
|
8476
|
+
user: void 0,
|
|
8477
|
+
reason: "the client cannot reach the global API host (no withConfig)"
|
|
7732
8478
|
};
|
|
8479
|
+
let globalRequest, globalClient;
|
|
8480
|
+
try {
|
|
8481
|
+
globalClient = client.withConfig({
|
|
8482
|
+
useProjectHostname: !1
|
|
8483
|
+
}), globalRequest = lazyRequest(globalClient);
|
|
8484
|
+
} catch (err) {
|
|
8485
|
+
return {
|
|
8486
|
+
user: void 0,
|
|
8487
|
+
reason: `building the global-host sibling client failed: ${errorMessage(err)}`,
|
|
8488
|
+
cause: err
|
|
8489
|
+
};
|
|
8490
|
+
}
|
|
8491
|
+
if (globalRequest === void 0) return {
|
|
8492
|
+
user: void 0,
|
|
8493
|
+
reason: "the global-host sibling client cannot issue requests"
|
|
8494
|
+
};
|
|
8495
|
+
try {
|
|
8496
|
+
return {
|
|
8497
|
+
user: await globalRequest({
|
|
8498
|
+
uri: "/users/me",
|
|
8499
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
8500
|
+
})
|
|
8501
|
+
};
|
|
8502
|
+
} catch (err) {
|
|
8503
|
+
return {
|
|
8504
|
+
user: void 0,
|
|
8505
|
+
reason: `global-host /users/me failed: ${errorMessage(err)}`,
|
|
8506
|
+
cause: err
|
|
8507
|
+
};
|
|
8508
|
+
}
|
|
7733
8509
|
}
|
|
7734
8510
|
|
|
7735
8511
|
async function fetchGrantsCached(requestFn, resourcePath) {
|
|
@@ -7905,12 +8681,25 @@ async function subjectResourceGrants(args) {
|
|
|
7905
8681
|
const resolved = await Promise.all([ ...clients.entries() ].map(async ([key, entry]) => {
|
|
7906
8682
|
const path = aclPathForResource(entry.resource);
|
|
7907
8683
|
if (path === void 0) return;
|
|
7908
|
-
const grants = await grantsForClientPath(entry.client, path);
|
|
7909
|
-
|
|
8684
|
+
const [grants, actorId] = await Promise.all([ grantsForClientPath(entry.client, path), resourceActorId(entry.client) ]);
|
|
8685
|
+
if (!(grants === void 0 || actorId === void 0)) return [ key, {
|
|
8686
|
+
grants: grants,
|
|
8687
|
+
actorId: actorId
|
|
8688
|
+
} ];
|
|
7910
8689
|
}));
|
|
7911
8690
|
return new Map(resolved.filter(entry => entry !== void 0));
|
|
7912
8691
|
}
|
|
7913
8692
|
|
|
8693
|
+
async function resourceActorId(client) {
|
|
8694
|
+
try {
|
|
8695
|
+
const access = await resolveAccess(client);
|
|
8696
|
+
return lakePrincipalId(access);
|
|
8697
|
+
} catch (err) {
|
|
8698
|
+
console.warn(`workflow: failed to resolve the actor identity on a subject resource; the subject-write forecast omits this resource (degrade open — the lake still enforces writes). Original error: ${errorMessage(err)}`);
|
|
8699
|
+
return;
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
|
|
7914
8703
|
async function evaluateInstance(args) {
|
|
7915
8704
|
const {client: client, tag: tag, workflowResource: workflowResource, instanceId: instanceId, resourceClients: resourceClients} = args, now = (args.clock ?? wallClock)();
|
|
7916
8705
|
validateTag(tag);
|
|
@@ -7922,7 +8711,7 @@ async function evaluateInstance(args) {
|
|
|
7922
8711
|
client: client,
|
|
7923
8712
|
instanceId: instanceId,
|
|
7924
8713
|
tag: tag
|
|
7925
|
-
}) ]), {actor: actor, grants: grants} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
|
|
8714
|
+
}) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
|
|
7926
8715
|
client: client,
|
|
7927
8716
|
workflowResource: workflowResource,
|
|
7928
8717
|
resourceClients: resourceClients
|
|
@@ -7942,6 +8731,9 @@ async function evaluateInstance(args) {
|
|
|
7942
8731
|
guards: guards,
|
|
7943
8732
|
now: now,
|
|
7944
8733
|
resourceGrants: resourceGrants,
|
|
8734
|
+
...localPrincipalId !== void 0 ? {
|
|
8735
|
+
localPrincipalId: localPrincipalId
|
|
8736
|
+
} : {},
|
|
7945
8737
|
...grants !== void 0 ? {
|
|
7946
8738
|
grants: grants
|
|
7947
8739
|
} : {}
|
|
@@ -7997,9 +8789,12 @@ async function evaluateFromSnapshot(args) {
|
|
|
7997
8789
|
definition: definition,
|
|
7998
8790
|
snapshot: snapshot,
|
|
7999
8791
|
now: now
|
|
8000
|
-
},
|
|
8001
|
-
instance: instance,
|
|
8792
|
+
}, anchorIdentity = lakePrincipalId({
|
|
8002
8793
|
actor: actor,
|
|
8794
|
+
localPrincipalId: args.localPrincipalId
|
|
8795
|
+
}), can = await advisoryCan({
|
|
8796
|
+
instance: instance,
|
|
8797
|
+
identity: anchorIdentity,
|
|
8003
8798
|
grants: grants
|
|
8004
8799
|
}), scope = await renderConditionScope(scopeSource, {
|
|
8005
8800
|
actor: actor,
|
|
@@ -8016,11 +8811,10 @@ async function evaluateFromSnapshot(args) {
|
|
|
8016
8811
|
activityName: activityName
|
|
8017
8812
|
})), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
8018
8813
|
instance: instance,
|
|
8019
|
-
|
|
8814
|
+
identity: anchorIdentity,
|
|
8020
8815
|
guards: args.guards
|
|
8021
8816
|
}), subjectDenials = await forecastSubjectDenials({
|
|
8022
8817
|
instance: instance,
|
|
8023
|
-
actor: actor,
|
|
8024
8818
|
snapshot: snapshot,
|
|
8025
8819
|
resourceGrants: args.resourceGrants
|
|
8026
8820
|
}), subjectPermissionReason = subjectDenials.length > 0 ? {
|
|
@@ -8164,20 +8958,20 @@ async function editPredicateInsight(args) {
|
|
|
8164
8958
|
}
|
|
8165
8959
|
|
|
8166
8960
|
async function forecastSubjectDenials(args) {
|
|
8167
|
-
const {instance: instance,
|
|
8961
|
+
const {instance: instance, snapshot: snapshot, resourceGrants: resourceGrants} = args;
|
|
8168
8962
|
if (resourceGrants === void 0 || resourceGrants.size === 0) return [];
|
|
8169
8963
|
const denials = [], seen = /* @__PURE__ */ new Set;
|
|
8170
8964
|
for (const {ref: ref, parsed: parsed, resource: resource} of foreignSubjectRefs(instance)) {
|
|
8171
8965
|
if (seen.has(ref.id)) continue;
|
|
8172
8966
|
seen.add(ref.id);
|
|
8173
|
-
const
|
|
8174
|
-
if (
|
|
8967
|
+
const access = resourceGrants.get(resourceGdr(resource));
|
|
8968
|
+
if (access === void 0) continue;
|
|
8175
8969
|
const doc = snapshot.docs.find(d => d._id === ref.id);
|
|
8176
8970
|
doc !== void 0 && await subjectUpdateAllowed({
|
|
8177
8971
|
doc: doc,
|
|
8178
8972
|
parsed: parsed,
|
|
8179
|
-
grants: grants,
|
|
8180
|
-
actorId:
|
|
8973
|
+
grants: access.grants,
|
|
8974
|
+
actorId: access.actorId
|
|
8181
8975
|
}) === !1 && denials.push({
|
|
8182
8976
|
subject: ref.id,
|
|
8183
8977
|
resource: resourceGdr(resource),
|
|
@@ -8258,12 +9052,12 @@ async function explainActivityConditions({activity: activity, activityScope: act
|
|
|
8258
9052
|
snapshot: snapshot,
|
|
8259
9053
|
sites: sites
|
|
8260
9054
|
}), requirementEntries = [];
|
|
8261
|
-
for (const
|
|
9055
|
+
for (const requirement of activity.requirements ?? []) requirementEntries.push([ requirement, await explainAt({
|
|
8262
9056
|
kind: "requirement",
|
|
8263
9057
|
activity: activity.name,
|
|
8264
|
-
requirement: name
|
|
8265
|
-
},
|
|
8266
|
-
const requirementInsights = Object.fromEntries(requirementEntries), unmetRequirements = requirementEntries.filter(([, insight]) => insight.outcome !== "satisfied").map(([
|
|
9058
|
+
requirement: requirement.name
|
|
9059
|
+
}, requirement.query) ]);
|
|
9060
|
+
const requirementInsights = Object.fromEntries(requirementEntries.map(([requirement, insight]) => [ requirement.name, insight ])), unmetRequirements = requirementEntries.filter(([, insight]) => insight.outcome !== "satisfied").map(([requirement]) => requirementDescriptor(requirement)), filterInsight = activity.filter !== void 0 ? await explainSite({
|
|
8267
9061
|
site: {
|
|
8268
9062
|
kind: "activity-filter",
|
|
8269
9063
|
activity: activity.name
|
|
@@ -8409,12 +9203,12 @@ function actionEvaluationIdentity(action) {
|
|
|
8409
9203
|
};
|
|
8410
9204
|
}
|
|
8411
9205
|
|
|
8412
|
-
async function instanceGuardReason({instance: instance,
|
|
9206
|
+
async function instanceGuardReason({instance: instance, identity: identity, guards: guards}) {
|
|
8413
9207
|
if (guards === void 0 || guards.length === 0) return;
|
|
8414
9208
|
const denied = await instanceWriteDenials({
|
|
8415
9209
|
instance: instance,
|
|
8416
9210
|
guards: guards,
|
|
8417
|
-
identity:
|
|
9211
|
+
identity: identity
|
|
8418
9212
|
});
|
|
8419
9213
|
if (denied.length !== 0) return {
|
|
8420
9214
|
kind: "mutation-guard-denied",
|
|
@@ -8453,12 +9247,12 @@ function inFlightFilter() {
|
|
|
8453
9247
|
return "!defined(completedAt)";
|
|
8454
9248
|
}
|
|
8455
9249
|
|
|
8456
|
-
const FIELD_REFS_DOC = "count(fields[value.id in $documents]) > 0 || count(fields[count(value[id in $documents]) > 0]) > 0",
|
|
9250
|
+
const FIELD_REFS_DOC = "count(fields[value.id in $documents]) > 0 || count(fields[count(value[id in $documents]) > 0]) > 0", OPEN_STAGE_REFS_DOC = `count(stages[!defined(exitedAt) && (${FIELD_REFS_DOC} || count(activities[${FIELD_REFS_DOC}]) > 0)]) > 0`, LIVE_SUBWORKFLOW_REFS_DOC = "count(subworkflows[!defined(resolved) && ref.id in $documents]) > 0";
|
|
8457
9251
|
|
|
8458
9252
|
function documentPrefilter(documents, params) {
|
|
8459
9253
|
for (const document of documents) if (!isGdrUri(document)) throw new ContractViolationError(`every document must be a resource-qualified GDR URI (e.g. "dataset:project:dataset:doc-id"); got: ${JSON.stringify(document)}`);
|
|
8460
9254
|
return params.documents = [ ...documents ], params.bareIds = documents.map(extractDocumentId),
|
|
8461
|
-
`_id in $bareIds || count(ancestors[id in $documents]) > 0 || ${
|
|
9255
|
+
`_id in $bareIds || count(ancestors[id in $documents]) > 0 || ${LIVE_SUBWORKFLOW_REFS_DOC} || ${FIELD_REFS_DOC} || ${OPEN_STAGE_REFS_DOC}`;
|
|
8462
9256
|
}
|
|
8463
9257
|
|
|
8464
9258
|
function documentArm(filter, params) {
|
|
@@ -8884,11 +9678,10 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
|
|
|
8884
9678
|
}
|
|
8885
9679
|
|
|
8886
9680
|
async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
|
|
8887
|
-
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), can =
|
|
9681
|
+
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), can = await advisoryCanForCall({
|
|
8888
9682
|
instance: ctx.instance,
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
}) : void 0, predicateSatisfied = window.open && site.effective !== !0 && site.effective !== void 0 ? await ctxEvaluateCondition({
|
|
9683
|
+
options: options
|
|
9684
|
+
}), predicateSatisfied = window.open && site.effective !== !0 && site.effective !== void 0 ? await ctxEvaluateCondition({
|
|
8892
9685
|
ctx: ctx,
|
|
8893
9686
|
condition: site.effective,
|
|
8894
9687
|
opts: {
|
|
@@ -9246,8 +10039,7 @@ async function abortAndPropagate(args) {
|
|
|
9246
10039
|
executionContext: executionContext,
|
|
9247
10040
|
telemetry: telemetry
|
|
9248
10041
|
})
|
|
9249
|
-
})
|
|
9250
|
-
return await drainCondemnedChildren({
|
|
10042
|
+
}), drained = await drainCondemnedChildren({
|
|
9251
10043
|
client: client,
|
|
9252
10044
|
instanceId: instanceId,
|
|
9253
10045
|
actor: actor,
|
|
@@ -9259,8 +10051,12 @@ async function abortAndPropagate(args) {
|
|
|
9259
10051
|
} : {},
|
|
9260
10052
|
...telemetry !== void 0 ? {
|
|
9261
10053
|
telemetry: telemetry
|
|
10054
|
+
} : {},
|
|
10055
|
+
...result.fired ? {
|
|
10056
|
+
instance: result.instance
|
|
9262
10057
|
} : {}
|
|
9263
|
-
})
|
|
10058
|
+
});
|
|
10059
|
+
return await propagateToAncestors({
|
|
9264
10060
|
client: client,
|
|
9265
10061
|
instanceId: instanceId,
|
|
9266
10062
|
actor: actor,
|
|
@@ -9272,6 +10068,9 @@ async function abortAndPropagate(args) {
|
|
|
9272
10068
|
} : {},
|
|
9273
10069
|
...telemetry !== void 0 ? {
|
|
9274
10070
|
telemetry: telemetry
|
|
10071
|
+
} : {},
|
|
10072
|
+
...result.fired && !drained.drained ? {
|
|
10073
|
+
instance: drained.instance
|
|
9275
10074
|
} : {}
|
|
9276
10075
|
}), result.fired;
|
|
9277
10076
|
}
|
|
@@ -9379,6 +10178,9 @@ function buildEngineCallOptions(args) {
|
|
|
9379
10178
|
actor: args.actor,
|
|
9380
10179
|
clientForGdr: args.clientForGdr,
|
|
9381
10180
|
refSurface: args.refSurface,
|
|
10181
|
+
...args.localPrincipalId !== void 0 ? {
|
|
10182
|
+
localPrincipalId: args.localPrincipalId
|
|
10183
|
+
} : {},
|
|
9382
10184
|
...args.grants !== void 0 ? {
|
|
9383
10185
|
grants: args.grants
|
|
9384
10186
|
} : {},
|
|
@@ -9520,6 +10322,15 @@ async function abortInstances(args) {
|
|
|
9520
10322
|
return aborted;
|
|
9521
10323
|
}
|
|
9522
10324
|
|
|
10325
|
+
function projectStartSliceRow(instance) {
|
|
10326
|
+
const subject = (instance.fields ?? []).find(field => field._type === "subject")?.value;
|
|
10327
|
+
return {
|
|
10328
|
+
definition: instance.definition,
|
|
10329
|
+
subject: typeof subject == "object" && subject !== null && "id" in subject && isGdrUri(subject.id) ? subject.id : null,
|
|
10330
|
+
completedAt: instance.completedAt ?? null
|
|
10331
|
+
};
|
|
10332
|
+
}
|
|
10333
|
+
|
|
9523
10334
|
async function fetchStartSlice(args) {
|
|
9524
10335
|
const {client: client, tag: tag} = args, {query: query, params: params} = instancesQuery({
|
|
9525
10336
|
tag: tag,
|
|
@@ -9527,7 +10338,7 @@ async function fetchStartSlice(args) {
|
|
|
9527
10338
|
includeCompleted: !0
|
|
9528
10339
|
}
|
|
9529
10340
|
});
|
|
9530
|
-
return (await client.fetch(query, params)).map(assertReadableModel);
|
|
10341
|
+
return (await client.fetch(query, params)).map(assertReadableModel).map(projectStartSliceRow);
|
|
9531
10342
|
}
|
|
9532
10343
|
|
|
9533
10344
|
const workflow = {
|
|
@@ -9676,6 +10487,9 @@ const workflow = {
|
|
|
9676
10487
|
...access.grants !== void 0 ? {
|
|
9677
10488
|
grants: access.grants
|
|
9678
10489
|
} : {},
|
|
10490
|
+
...access.localPrincipalId !== void 0 ? {
|
|
10491
|
+
localPrincipalId: access.localPrincipalId
|
|
10492
|
+
} : {},
|
|
9679
10493
|
clock: clock,
|
|
9680
10494
|
clientForGdr: clientForGdr,
|
|
9681
10495
|
refSurface: refSurface,
|
|
@@ -9744,6 +10558,9 @@ const workflow = {
|
|
|
9744
10558
|
...access.grants !== void 0 ? {
|
|
9745
10559
|
grants: access.grants
|
|
9746
10560
|
} : {},
|
|
10561
|
+
...access.localPrincipalId !== void 0 ? {
|
|
10562
|
+
localPrincipalId: access.localPrincipalId
|
|
10563
|
+
} : {},
|
|
9747
10564
|
clock: clock,
|
|
9748
10565
|
clientForGdr: clientForGdr,
|
|
9749
10566
|
refSurface: refSurface,
|
|
@@ -9903,7 +10720,7 @@ const workflow = {
|
|
|
9903
10720
|
});
|
|
9904
10721
|
},
|
|
9905
10722
|
tick: async rawArgs => {
|
|
9906
|
-
const args = taggedScope(rawArgs, REQUEST_TAG.tick), {client: client, tag: tag, instanceId: instanceId, executionContext: executionContext} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, current = await reload({
|
|
10723
|
+
const args = taggedScope(rawArgs, REQUEST_TAG.tick), {client: client, tag: tag, instanceId: instanceId, executionContext: executionContext} = args, {access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, current = await reload({
|
|
9907
10724
|
client: client,
|
|
9908
10725
|
instanceId: instanceId,
|
|
9909
10726
|
tag: tag
|
|
@@ -9911,7 +10728,7 @@ const workflow = {
|
|
|
9911
10728
|
await assertInstanceWriteAllowed({
|
|
9912
10729
|
instance: current,
|
|
9913
10730
|
guards: guards,
|
|
9914
|
-
identity:
|
|
10731
|
+
identity: lakePrincipalId(access)
|
|
9915
10732
|
});
|
|
9916
10733
|
const {cascaded: cascaded, instance: instance} = await cascadeAndReload({
|
|
9917
10734
|
client: client,
|
|
@@ -10028,6 +10845,59 @@ const workflow = {
|
|
|
10028
10845
|
}
|
|
10029
10846
|
});
|
|
10030
10847
|
},
|
|
10848
|
+
resetActivity: async rawArgs => {
|
|
10849
|
+
const args = taggedScope(rawArgs, REQUEST_TAG.resetActivity), {client: client, tag: tag, instanceId: instanceId, activity: activity, executionContext: executionContext} = args, to = args.to ?? "active";
|
|
10850
|
+
if (!isResetActivityTarget(to)) throw new ContractViolationError(`resetActivity: "to" must be "active" or "skipped"; got ${JSON.stringify(args.to)}`);
|
|
10851
|
+
return runCommitVerb({
|
|
10852
|
+
args: args,
|
|
10853
|
+
op: "resetActivity",
|
|
10854
|
+
run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
|
|
10855
|
+
const result = await resetActivity({
|
|
10856
|
+
client: client,
|
|
10857
|
+
instanceId: instanceId,
|
|
10858
|
+
activity: activity,
|
|
10859
|
+
to: to,
|
|
10860
|
+
...record !== void 0 ? {
|
|
10861
|
+
requestRecord: record
|
|
10862
|
+
} : {},
|
|
10863
|
+
options: engineOptionsForActor({
|
|
10864
|
+
actor: actor,
|
|
10865
|
+
clock: clock,
|
|
10866
|
+
clientForGdr: clientForGdr,
|
|
10867
|
+
refSurface: refSurface,
|
|
10868
|
+
executionContext: executionContext,
|
|
10869
|
+
telemetry: args.telemetry
|
|
10870
|
+
})
|
|
10871
|
+
}), cascaded = result.fired ? await cascade({
|
|
10872
|
+
client: client,
|
|
10873
|
+
instanceId: instanceId,
|
|
10874
|
+
actor: actor,
|
|
10875
|
+
clientForGdr: clientForGdr,
|
|
10876
|
+
refSurface: refSurface,
|
|
10877
|
+
clock: clock,
|
|
10878
|
+
...executionContext !== void 0 ? {
|
|
10879
|
+
executionContext: executionContext
|
|
10880
|
+
} : {},
|
|
10881
|
+
...args.telemetry !== void 0 ? {
|
|
10882
|
+
telemetry: args.telemetry
|
|
10883
|
+
} : {}
|
|
10884
|
+
}) : 0;
|
|
10885
|
+
return resolveTelemetry(args.telemetry).log(WorkflowActivityReset, {
|
|
10886
|
+
...definitionHashFragment(before.pinnedContentHash),
|
|
10887
|
+
instanceId: instanceId,
|
|
10888
|
+
changed: result.fired
|
|
10889
|
+
}), {
|
|
10890
|
+
instance: await reload({
|
|
10891
|
+
client: client,
|
|
10892
|
+
instanceId: instanceId,
|
|
10893
|
+
tag: tag
|
|
10894
|
+
}),
|
|
10895
|
+
cascaded: cascaded,
|
|
10896
|
+
changed: result.fired
|
|
10897
|
+
};
|
|
10898
|
+
}
|
|
10899
|
+
});
|
|
10900
|
+
},
|
|
10031
10901
|
getInstance: async rawArgs => {
|
|
10032
10902
|
const args = taggedScope(rawArgs, REQUEST_TAG.getInstance), {client: client, tag: tag, instanceId: instanceId} = args;
|
|
10033
10903
|
return validateTag(tag), reload({
|
|
@@ -10174,21 +11044,18 @@ const workflow = {
|
|
|
10174
11044
|
return (await client.fetch(query, params)).map(readInstanceDoc).filter(instance => instanceWatchesDocument(instance, document));
|
|
10175
11045
|
},
|
|
10176
11046
|
definitionsForDocument: async rawArgs => {
|
|
10177
|
-
const args = taggedScope(rawArgs, REQUEST_TAG.definitionsForDocument), {client: client, tag: tag, document: document
|
|
11047
|
+
const args = taggedScope(rawArgs, REQUEST_TAG.definitionsForDocument), {client: client, tag: tag, document: document} = args;
|
|
10178
11048
|
validateTag(tag);
|
|
10179
|
-
const clock = args.clock ?? wallClock, deployed = (await client.fetch(
|
|
11049
|
+
const clock = args.clock ?? wallClock, deployed = (await client.fetch(latestDefinitionsGroq(), {
|
|
10180
11050
|
tag: tag
|
|
10181
|
-
})).map(assertReadableModel)
|
|
11051
|
+
})).map(assertReadableModel);
|
|
10182
11052
|
let slice;
|
|
10183
11053
|
return applicableDefinitions({
|
|
10184
|
-
definitions:
|
|
11054
|
+
definitions: deployed,
|
|
10185
11055
|
document: document,
|
|
10186
11056
|
scope: {
|
|
10187
11057
|
tag: tag,
|
|
10188
11058
|
now: clock(),
|
|
10189
|
-
...subject !== void 0 ? {
|
|
10190
|
-
subject: subject
|
|
10191
|
-
} : {},
|
|
10192
11059
|
fetchDataset: () => slice ??= fetchStartSlice({
|
|
10193
11060
|
client: client,
|
|
10194
11061
|
tag: tag
|
|
@@ -10211,34 +11078,17 @@ const workflow = {
|
|
|
10211
11078
|
}), missingRequired = missingRequiredInputs({
|
|
10212
11079
|
entryDefs: definition.fields ?? [],
|
|
10213
11080
|
initialFields: initialFields ?? []
|
|
10214
|
-
}),
|
|
10215
|
-
if (allowed === void 0) return {
|
|
10216
|
-
allowed: invalidInitialFields.length === 0,
|
|
10217
|
-
outcome: "satisfied",
|
|
10218
|
-
unboundReads: [],
|
|
10219
|
-
missingRequired: missingRequired,
|
|
10220
|
-
invalidInitialFields: invalidInitialFields
|
|
10221
|
-
};
|
|
10222
|
-
const unboundReads = unboundAllowedReadsWithSubject({
|
|
10223
|
-
allowed: allowed,
|
|
10224
|
-
fields: startFieldsParam({
|
|
10225
|
-
entryDefs: definition.fields ?? [],
|
|
10226
|
-
initialFields: initialFields ?? []
|
|
10227
|
-
}),
|
|
10228
|
-
definition: definition
|
|
10229
|
-
}), insight = await startAllowedInsight({
|
|
11081
|
+
}), verdict = await startRequirementVerdict({
|
|
10230
11082
|
client: client,
|
|
10231
11083
|
tag: tag,
|
|
10232
11084
|
definition: definition,
|
|
10233
|
-
allowed: allowed,
|
|
10234
11085
|
initialFields: initialFields ?? [],
|
|
10235
|
-
now: clock()
|
|
10236
|
-
|
|
11086
|
+
now: clock(),
|
|
11087
|
+
preflight: !0
|
|
11088
|
+
});
|
|
10237
11089
|
return {
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
insight: insight,
|
|
10241
|
-
unboundReads: unboundReads,
|
|
11090
|
+
...verdict,
|
|
11091
|
+
allowed: invalidInitialFields.length === 0 && verdict.allowed,
|
|
10242
11092
|
missingRequired: missingRequired,
|
|
10243
11093
|
invalidInitialFields: invalidInitialFields
|
|
10244
11094
|
};
|
|
@@ -10250,11 +11100,10 @@ const workflow = {
|
|
|
10250
11100
|
}
|
|
10251
11101
|
};
|
|
10252
11102
|
|
|
10253
|
-
|
|
10254
|
-
const {client: client, tag: tag, definition: definition,
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
definition: definition,
|
|
11103
|
+
function startPredicateContext(args) {
|
|
11104
|
+
const {client: client, tag: tag, definition: definition, initialFields: initialFields, now: now} = args;
|
|
11105
|
+
let slice;
|
|
11106
|
+
return {
|
|
10258
11107
|
fields: startFieldsParam({
|
|
10259
11108
|
entryDefs: definition.fields ?? [],
|
|
10260
11109
|
initialFields: initialFields
|
|
@@ -10262,12 +11111,71 @@ async function startAllowedInsight(args) {
|
|
|
10262
11111
|
scope: {
|
|
10263
11112
|
tag: tag,
|
|
10264
11113
|
now: now,
|
|
10265
|
-
fetchDataset: () => fetchStartSlice({
|
|
11114
|
+
fetchDataset: () => slice ??= fetchStartSlice({
|
|
10266
11115
|
client: client,
|
|
10267
11116
|
tag: tag
|
|
10268
11117
|
})
|
|
10269
11118
|
}
|
|
10270
|
-
}
|
|
11119
|
+
};
|
|
11120
|
+
}
|
|
11121
|
+
|
|
11122
|
+
async function startRequirementVerdict(args) {
|
|
11123
|
+
const {client: client, tag: tag, definition: definition, initialFields: initialFields, now: now, preflight: preflight = !1} = args, declared = definition.start?.requirements ?? [];
|
|
11124
|
+
if (declared.length === 0) return {
|
|
11125
|
+
allowed: !0,
|
|
11126
|
+
outcome: "satisfied",
|
|
11127
|
+
requirements: [],
|
|
11128
|
+
unboundReads: []
|
|
11129
|
+
};
|
|
11130
|
+
const {fields: fields, scope: scope} = startPredicateContext({
|
|
11131
|
+
client: client,
|
|
11132
|
+
tag: tag,
|
|
11133
|
+
definition: definition,
|
|
11134
|
+
initialFields: initialFields,
|
|
11135
|
+
now: now
|
|
11136
|
+
}), subjectEntry = (definition.fields ?? []).find(isSubjectEntry)?.name, requirements = [], unbound = /* @__PURE__ */ new Set;
|
|
11137
|
+
for (const requirement of declared) {
|
|
11138
|
+
const descriptor = requirementDescriptor(requirement);
|
|
11139
|
+
if (requirement.type === "singleSubject") {
|
|
11140
|
+
if (preflight && subjectEntry !== void 0 && !Object.hasOwn(fields, subjectEntry)) unbound.add(subjectEntry),
|
|
11141
|
+
requirements.push({
|
|
11142
|
+
...descriptor,
|
|
11143
|
+
outcome: "unevaluable"
|
|
11144
|
+
}); else {
|
|
11145
|
+
const refused = await singleSubjectRequirementRefused({
|
|
11146
|
+
definition: definition,
|
|
11147
|
+
fields: fields,
|
|
11148
|
+
scope: scope
|
|
11149
|
+
});
|
|
11150
|
+
requirements.push({
|
|
11151
|
+
...descriptor,
|
|
11152
|
+
outcome: refused ? "unsatisfied" : "satisfied"
|
|
11153
|
+
});
|
|
11154
|
+
}
|
|
11155
|
+
continue;
|
|
11156
|
+
}
|
|
11157
|
+
const missing = unboundRequirementReads(requirement.query, fields);
|
|
11158
|
+
missing.forEach(name => unbound.add(name));
|
|
11159
|
+
const insight = await explainStartRequirement({
|
|
11160
|
+
query: requirement.query,
|
|
11161
|
+
definition: definition,
|
|
11162
|
+
fields: fields,
|
|
11163
|
+
scope: scope
|
|
11164
|
+
});
|
|
11165
|
+
requirements.push({
|
|
11166
|
+
...descriptor,
|
|
11167
|
+
outcome: preflight && missing.length > 0 ? "unevaluable" : insight.outcome,
|
|
11168
|
+
insight: insight
|
|
11169
|
+
});
|
|
11170
|
+
}
|
|
11171
|
+
let outcome = "satisfied";
|
|
11172
|
+
return requirements.some(requirement => requirement.outcome === "unsatisfied") ? outcome = "unsatisfied" : requirements.some(requirement => requirement.outcome === "unevaluable") && (outcome = "unevaluable"),
|
|
11173
|
+
{
|
|
11174
|
+
allowed: outcome === "satisfied",
|
|
11175
|
+
outcome: outcome,
|
|
11176
|
+
requirements: requirements,
|
|
11177
|
+
unboundReads: [ ...unbound ]
|
|
11178
|
+
};
|
|
10271
11179
|
}
|
|
10272
11180
|
|
|
10273
11181
|
async function startFreshInstance(args) {
|
|
@@ -10367,19 +11275,16 @@ async function assertStartInputs(args) {
|
|
|
10367
11275
|
initialFields: initialFields,
|
|
10368
11276
|
definitionName: definition.name
|
|
10369
11277
|
});
|
|
10370
|
-
const
|
|
10371
|
-
if (allowed === void 0) return;
|
|
10372
|
-
const insight = await startAllowedInsight({
|
|
11278
|
+
const unmetRequirements = (await startRequirementVerdict({
|
|
10373
11279
|
client: client,
|
|
10374
11280
|
tag: tag,
|
|
10375
11281
|
definition: definition,
|
|
10376
|
-
allowed: allowed,
|
|
10377
11282
|
initialFields: initialFields,
|
|
10378
11283
|
now: now
|
|
10379
|
-
});
|
|
10380
|
-
if (
|
|
11284
|
+
})).requirements.filter(requirement => requirement.outcome !== "satisfied").map(requirementDescriptor);
|
|
11285
|
+
if (unmetRequirements.length > 0) throw new StartNotAllowedError({
|
|
10381
11286
|
definition: definition.name,
|
|
10382
|
-
|
|
11287
|
+
unmetRequirements: unmetRequirements
|
|
10383
11288
|
});
|
|
10384
11289
|
}
|
|
10385
11290
|
|
|
@@ -10412,97 +11317,6 @@ async function resolveStartFields(args) {
|
|
|
10412
11317
|
};
|
|
10413
11318
|
}
|
|
10414
11319
|
|
|
10415
|
-
function isRecord(value) {
|
|
10416
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
10417
|
-
}
|
|
10418
|
-
|
|
10419
|
-
function isClientProjectUser(value) {
|
|
10420
|
-
return isRecord(value) && typeof value.id == "string" && (value.displayName === void 0 || typeof value.displayName == "string") && (value.email === void 0 || typeof value.email == "string") && (value.imageUrl === void 0 || value.imageUrl === null || typeof value.imageUrl == "string");
|
|
10421
|
-
}
|
|
10422
|
-
|
|
10423
|
-
function objectProperty(value, property) {
|
|
10424
|
-
if (!isRecord(value)) return;
|
|
10425
|
-
const propertyValue = value[property];
|
|
10426
|
-
return typeof propertyValue == "object" && propertyValue !== null ? propertyValue : void 0;
|
|
10427
|
-
}
|
|
10428
|
-
|
|
10429
|
-
function stringProperty(value, property) {
|
|
10430
|
-
const propertyValue = Reflect.get(value, property);
|
|
10431
|
-
return typeof propertyValue == "string" ? propertyValue : void 0;
|
|
10432
|
-
}
|
|
10433
|
-
|
|
10434
|
-
function apiErrorType(error) {
|
|
10435
|
-
const response = objectProperty(error, "response"), body = objectProperty(response, "body");
|
|
10436
|
-
if (!body) return;
|
|
10437
|
-
const nestedError = objectProperty(body, "error");
|
|
10438
|
-
return (nestedError ? stringProperty(nestedError, "type") : void 0) ?? stringProperty(body, "type");
|
|
10439
|
-
}
|
|
10440
|
-
|
|
10441
|
-
function isProjectUserNotFoundError(error) {
|
|
10442
|
-
return apiErrorType(error) === "projectUserNotFoundError";
|
|
10443
|
-
}
|
|
10444
|
-
|
|
10445
|
-
function clientProjectUserDirectory(client, projectId) {
|
|
10446
|
-
return {
|
|
10447
|
-
findById: async id => {
|
|
10448
|
-
if (!client.request) return {
|
|
10449
|
-
status: "inaccessible",
|
|
10450
|
-
cause: new Error("Project-user resolution requires WorkflowClient.request")
|
|
10451
|
-
};
|
|
10452
|
-
try {
|
|
10453
|
-
const response = await client.request({
|
|
10454
|
-
uri: `/projects/${encodeURIComponent(projectId)}/users/${encodeURIComponent(id)}`
|
|
10455
|
-
}), candidate = Array.isArray(response) ? response[0] : response;
|
|
10456
|
-
return candidate == null ? {
|
|
10457
|
-
status: "missing"
|
|
10458
|
-
} : isClientProjectUser(candidate) ? {
|
|
10459
|
-
status: "resolved",
|
|
10460
|
-
user: candidate
|
|
10461
|
-
} : {
|
|
10462
|
-
status: "inaccessible",
|
|
10463
|
-
cause: new Error("Project-user response had an invalid shape")
|
|
10464
|
-
};
|
|
10465
|
-
} catch (cause) {
|
|
10466
|
-
return isProjectUserNotFoundError(cause) ? {
|
|
10467
|
-
status: "missing"
|
|
10468
|
-
} : {
|
|
10469
|
-
status: "inaccessible",
|
|
10470
|
-
cause: cause
|
|
10471
|
-
};
|
|
10472
|
-
}
|
|
10473
|
-
}
|
|
10474
|
-
};
|
|
10475
|
-
}
|
|
10476
|
-
|
|
10477
|
-
function resolveClientActor(client, args) {
|
|
10478
|
-
return resolveActor(clientProjectUserDirectory(client, args.projectId), args.actor);
|
|
10479
|
-
}
|
|
10480
|
-
|
|
10481
|
-
async function resolveActor(directory, actor) {
|
|
10482
|
-
if (actor.kind !== "person") return {
|
|
10483
|
-
status: "not-person",
|
|
10484
|
-
actor: actor
|
|
10485
|
-
};
|
|
10486
|
-
const personActor = {
|
|
10487
|
-
...actor,
|
|
10488
|
-
kind: "person"
|
|
10489
|
-
}, lookup = await directory.findById(personActor.id);
|
|
10490
|
-
return lookup.status === "resolved" ? {
|
|
10491
|
-
status: "resolved",
|
|
10492
|
-
actor: personActor,
|
|
10493
|
-
user: lookup.user
|
|
10494
|
-
} : lookup.status === "inaccessible" ? {
|
|
10495
|
-
status: "inaccessible",
|
|
10496
|
-
actor: personActor,
|
|
10497
|
-
...lookup.cause === void 0 ? {} : {
|
|
10498
|
-
cause: lookup.cause
|
|
10499
|
-
}
|
|
10500
|
-
} : {
|
|
10501
|
-
status: "missing",
|
|
10502
|
-
actor: personActor
|
|
10503
|
-
};
|
|
10504
|
-
}
|
|
10505
|
-
|
|
10506
11320
|
const EFFECT_COMMIT_QUEUE_DEPTH = 32, EFFECT_COMMIT_DISPATCH_CAP = 200;
|
|
10507
11321
|
|
|
10508
11322
|
class EffectCommitQueueOverflowError extends WorkflowError {
|
|
@@ -11128,17 +11942,23 @@ function createInstanceSession(args) {
|
|
|
11128
11942
|
refSurface: evalScope.refSurface
|
|
11129
11943
|
});
|
|
11130
11944
|
}, evaluateWith = async ({held: held, guards: guards, self: self}) => {
|
|
11131
|
-
const {actor: actor, grants: grants} = await access(), resourceGrants = await subjectResourceGrants({
|
|
11945
|
+
const {actor: actor, localPrincipalId: localPrincipalId, grants: grants} = await access(), resourceGrants = await subjectResourceGrants({
|
|
11132
11946
|
clientForGdr: evalScope.clientForGdr,
|
|
11133
11947
|
instance: instance
|
|
11948
|
+
}), normalizedSelf = await normalizeInstanceIdentities({
|
|
11949
|
+
client: evalScope.client,
|
|
11950
|
+
instance: self
|
|
11134
11951
|
});
|
|
11135
11952
|
return evaluateFromSnapshot({
|
|
11136
|
-
instance:
|
|
11953
|
+
instance: normalizedSelf,
|
|
11137
11954
|
definition: definitionOf(),
|
|
11138
11955
|
actor: actor,
|
|
11139
|
-
snapshot: snapshotFrom(held,
|
|
11956
|
+
snapshot: snapshotFrom(held, normalizedSelf),
|
|
11140
11957
|
guards: guards,
|
|
11141
11958
|
resourceGrants: resourceGrants,
|
|
11959
|
+
...localPrincipalId !== void 0 ? {
|
|
11960
|
+
localPrincipalId: localPrincipalId
|
|
11961
|
+
} : {},
|
|
11142
11962
|
...clock !== void 0 ? {
|
|
11143
11963
|
now: clock()
|
|
11144
11964
|
} : {},
|
|
@@ -11184,8 +12004,13 @@ function createInstanceSession(args) {
|
|
|
11184
12004
|
committing = !0;
|
|
11185
12005
|
const held = new Map(overlay);
|
|
11186
12006
|
try {
|
|
11187
|
-
const {actor: actor} = await access();
|
|
11188
|
-
return await run(
|
|
12007
|
+
const {actor: actor, localPrincipalId: localPrincipalId} = await access();
|
|
12008
|
+
return await run({
|
|
12009
|
+
actor: actor,
|
|
12010
|
+
...localPrincipalId !== void 0 ? {
|
|
12011
|
+
localPrincipalId: localPrincipalId
|
|
12012
|
+
} : {}
|
|
12013
|
+
}, held);
|
|
11189
12014
|
} finally {
|
|
11190
12015
|
if (committing = !1, buffered !== void 0) {
|
|
11191
12016
|
const next = buffered;
|
|
@@ -11260,11 +12085,14 @@ function createInstanceSession(args) {
|
|
|
11260
12085
|
site !== void 0 && previews.delete(siteKey(site));
|
|
11261
12086
|
},
|
|
11262
12087
|
tick() {
|
|
11263
|
-
return commit(async (actor, held) => {
|
|
12088
|
+
return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
|
|
11264
12089
|
await assertInstanceWriteAllowed({
|
|
11265
12090
|
instance: instance,
|
|
11266
12091
|
guards: heldGuards,
|
|
11267
|
-
identity:
|
|
12092
|
+
identity: lakePrincipalId({
|
|
12093
|
+
actor: actor,
|
|
12094
|
+
localPrincipalId: localPrincipalId
|
|
12095
|
+
})
|
|
11268
12096
|
});
|
|
11269
12097
|
const before = await reload({
|
|
11270
12098
|
client: tickScope.client,
|
|
@@ -11291,7 +12119,7 @@ function createInstanceSession(args) {
|
|
|
11291
12119
|
});
|
|
11292
12120
|
},
|
|
11293
12121
|
fireAction({activity: activity, action: action, params: params}) {
|
|
11294
|
-
return commit(async (actor, held) => {
|
|
12122
|
+
return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
|
|
11295
12123
|
assertActionAllowed({
|
|
11296
12124
|
evaluation: await evaluateWith({
|
|
11297
12125
|
held: held,
|
|
@@ -11307,6 +12135,9 @@ function createInstanceSession(args) {
|
|
|
11307
12135
|
activity: activity,
|
|
11308
12136
|
action: action,
|
|
11309
12137
|
actor: actor,
|
|
12138
|
+
...localPrincipalId !== void 0 ? {
|
|
12139
|
+
localPrincipalId: localPrincipalId
|
|
12140
|
+
} : {},
|
|
11310
12141
|
clientForGdr: fireScope.clientForGdr,
|
|
11311
12142
|
refSurface: fireScope.refSurface,
|
|
11312
12143
|
...grants !== void 0 ? {
|
|
@@ -11349,7 +12180,7 @@ function createInstanceSession(args) {
|
|
|
11349
12180
|
} catch (err) {
|
|
11350
12181
|
return Promise.reject(err);
|
|
11351
12182
|
}
|
|
11352
|
-
return commit(async (actor, held) => {
|
|
12183
|
+
return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
|
|
11353
12184
|
assertEditAllowed(await evaluateWith({
|
|
11354
12185
|
held: held,
|
|
11355
12186
|
guards: heldGuards,
|
|
@@ -11366,6 +12197,9 @@ function createInstanceSession(args) {
|
|
|
11366
12197
|
value: value
|
|
11367
12198
|
} : {},
|
|
11368
12199
|
actor: actor,
|
|
12200
|
+
...localPrincipalId !== void 0 ? {
|
|
12201
|
+
localPrincipalId: localPrincipalId
|
|
12202
|
+
} : {},
|
|
11369
12203
|
clientForGdr: editScope.clientForGdr,
|
|
11370
12204
|
refSurface: editScope.refSurface,
|
|
11371
12205
|
...grants !== void 0 ? {
|
|
@@ -11476,6 +12310,7 @@ function createEngine(args) {
|
|
|
11476
12310
|
availableActions: rest => workflow.availableActions(withScope(rest)),
|
|
11477
12311
|
setStage: rest => workflow.setStage(withScope(rest)),
|
|
11478
12312
|
abortInstance: rest => workflow.abortInstance(withScope(rest)),
|
|
12313
|
+
resetActivity: rest => workflow.resetActivity(withScope(rest)),
|
|
11479
12314
|
deleteDefinition: rest => workflow.deleteDefinition(withScope(rest)),
|
|
11480
12315
|
getInstance: rest => workflow.getInstance(withScope(rest)),
|
|
11481
12316
|
subscriptionDocumentsForInstance: rest => workflow.getInstance(withScope(rest)).then(subscriptionDocumentsForInstance),
|
|
@@ -12042,4 +12877,4 @@ function displayDescription(typeKey) {
|
|
|
12042
12877
|
if (typeKey) return DISPLAY[typeKey]?.description;
|
|
12043
12878
|
}
|
|
12044
12879
|
|
|
12045
|
-
export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, 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, OP_DISPLAY, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError,
|
|
12880
|
+
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_MIN_READER, DATA_MODEL_VERSION, 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, OP_DISPLAY, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, 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, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
|