@sanity/workflow-engine 0.27.0 → 0.29.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 +197 -0
- package/DATAMODEL.md +107 -0
- package/dist/_chunks-cjs/invariants.cjs +212 -442
- package/dist/_chunks-es/invariants.js +209 -405
- package/dist/define.cjs +1 -6
- package/dist/define.d.cts +232 -24
- package/dist/define.d.ts +232 -24
- package/dist/define.js +2 -7
- package/dist/index.cjs +1216 -510
- package/dist/index.d.cts +452 -34
- package/dist/index.d.ts +452 -34
- package/dist/index.js +1106 -415
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -55,6 +55,53 @@ function findCurrentActivityEntry(host, activityName) {
|
|
|
55
55
|
return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
|
|
59
|
+
|
|
60
|
+
function terminalState(instance) {
|
|
61
|
+
return instance.abortedAt !== void 0 ? "aborted" : instance.completedAt !== void 0 ? "completed" : "in-flight";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isUnprimed(instance) {
|
|
65
|
+
return instance.stages.length === 0 && terminalState(instance) === "in-flight";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function parseDefinitionSnapshotValue(instance) {
|
|
69
|
+
try {
|
|
70
|
+
return normalizeLegacyActivityRequirements(JSON.parse(instance.definitionSnapshot));
|
|
71
|
+
} catch (err) {
|
|
72
|
+
invariants.rethrowWithContext(err, `Failed to parse definitionSnapshot on instance "${instance._id}"`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function normalizeLegacyActivityRequirements(value) {
|
|
77
|
+
for (const stage of arrayMember(value, "stages")) for (const activity of arrayMember(stage, "activities")) normalizeLegacyRequirementMap(activity);
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function arrayMember(value, key) {
|
|
82
|
+
if (typeof value != "object" || value === null) return [];
|
|
83
|
+
const member = value[key];
|
|
84
|
+
return Array.isArray(member) ? member : [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function normalizeLegacyRequirementMap(value) {
|
|
88
|
+
if (typeof value != "object" || value === null) return;
|
|
89
|
+
const activity = value, requirements = activity.requirements;
|
|
90
|
+
typeof requirements != "object" || requirements === null || Array.isArray(requirements) || (activity.requirements = Object.entries(requirements).map(([name, query]) => ({
|
|
91
|
+
type: "groq",
|
|
92
|
+
name: name,
|
|
93
|
+
query: query
|
|
94
|
+
})));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function parseDefinitionSnapshot(instance) {
|
|
98
|
+
return parseDefinitionSnapshotValue(instance);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function parentRef(instance) {
|
|
102
|
+
return instance.ancestors.at(-1);
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
function effectiveEditable(baseline, override) {
|
|
59
106
|
if (baseline === void 0) return;
|
|
60
107
|
if (override === void 0) return baseline;
|
|
@@ -131,7 +178,7 @@ function resolveEditTarget(args) {
|
|
|
131
178
|
}
|
|
132
179
|
|
|
133
180
|
function fieldWindowOpen(instance, site) {
|
|
134
|
-
const terminal =
|
|
181
|
+
const terminal = terminalState(instance);
|
|
135
182
|
if (terminal !== "in-flight") return {
|
|
136
183
|
open: !1,
|
|
137
184
|
detail: `instance ${terminal}`
|
|
@@ -198,7 +245,7 @@ function editDisabledReason(args) {
|
|
|
198
245
|
}
|
|
199
246
|
|
|
200
247
|
function instanceTerminalReason(instance) {
|
|
201
|
-
const terminal =
|
|
248
|
+
const terminal = terminalState(instance);
|
|
202
249
|
if (terminal === "aborted" && instance.abortedAt !== void 0) return {
|
|
203
250
|
kind: "instance-aborted",
|
|
204
251
|
abortedAt: instance.abortedAt
|
|
@@ -328,7 +375,7 @@ function instanceStartedData(args) {
|
|
|
328
375
|
function instanceStartedDataFor(args) {
|
|
329
376
|
return instanceStartedData({
|
|
330
377
|
definition: {
|
|
331
|
-
...
|
|
378
|
+
...parseDefinitionSnapshot(args.instance),
|
|
332
379
|
...args.instance.pinnedContentHash !== void 0 ? {
|
|
333
380
|
contentHash: args.instance.pinnedContentHash
|
|
334
381
|
} : {}
|
|
@@ -356,7 +403,7 @@ function stageTransitionedData(args) {
|
|
|
356
403
|
}
|
|
357
404
|
|
|
358
405
|
function openStage$1(instance) {
|
|
359
|
-
const definition =
|
|
406
|
+
const definition = parseDefinitionSnapshot(instance);
|
|
360
407
|
return {
|
|
361
408
|
definition: definition,
|
|
362
409
|
stage: definition.stages.find(s => s.name === instance.currentStage)
|
|
@@ -402,6 +449,313 @@ function fieldEditedData(args) {
|
|
|
402
449
|
};
|
|
403
450
|
}
|
|
404
451
|
|
|
452
|
+
const DATA_MODEL_VERSION = 7, DATA_MODEL_MIN_READER = 4, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
|
|
453
|
+
|
|
454
|
+
class ReaderModelAcknowledgementError extends invariants.WorkflowError {
|
|
455
|
+
code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
|
|
456
|
+
expectedMinReaderModel;
|
|
457
|
+
engineMinReaderModel=DATA_MODEL_MIN_READER;
|
|
458
|
+
engineModelVersion=DATA_MODEL_VERSION;
|
|
459
|
+
documentationUrl=READER_MODEL_ROLLOUT_URL;
|
|
460
|
+
constructor(expectedMinReaderModel, context = "Deployment") {
|
|
461
|
+
const expected = expectedMinReaderModel === void 0 ? "missing" : String(expectedMinReaderModel);
|
|
462
|
+
super("reader-model-acknowledgement", `${context} expected reader floor ${expected}; the installed engine requires acknowledgement ${DATA_MODEL_MIN_READER}.\nDo not change the acknowledgement yet: accepting ${DATA_MODEL_MIN_READER} authorizes this engine to write documents that older readers will refuse.\nUpgrade every Studio, CLI, MCP server, Function, and other runtime that reads engine-owned documents; verify that rollout in every environment sharing the workflow resource; then change the literal in deployment configuration and deploy the writer.\nRollout guide: ${READER_MODEL_ROLLOUT_URL}`),
|
|
463
|
+
this.name = "ReaderModelAcknowledgementError", this.expectedMinReaderModel = expectedMinReaderModel;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function assertReaderModelAcknowledgement(expectedMinReaderModel, context) {
|
|
468
|
+
if (typeof expectedMinReaderModel != "number" || !Number.isFinite(expectedMinReaderModel) || !Number.isInteger(expectedMinReaderModel) || expectedMinReaderModel < 0 || expectedMinReaderModel !== DATA_MODEL_MIN_READER) throw new ReaderModelAcknowledgementError(expectedMinReaderModel, context);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
|
|
472
|
+
id: "governed-model-stamps",
|
|
473
|
+
introducedInModel: 1,
|
|
474
|
+
minReaderModel: 0,
|
|
475
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
476
|
+
compatibility: "additive",
|
|
477
|
+
applicability: "unconditional",
|
|
478
|
+
summary: "Definition and instance documents carry model provenance and reader-floor stamps."
|
|
479
|
+
}), Object.freeze({
|
|
480
|
+
id: "subject-field-kind",
|
|
481
|
+
introducedInModel: 2,
|
|
482
|
+
minReaderModel: 0,
|
|
483
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
484
|
+
compatibility: "additive",
|
|
485
|
+
applicability: "detectable",
|
|
486
|
+
summary: "A workflow-level subject field identifies the document a workflow is about."
|
|
487
|
+
}), Object.freeze({
|
|
488
|
+
id: "typed-scalar-choice-lists",
|
|
489
|
+
introducedInModel: 2,
|
|
490
|
+
minReaderModel: 2,
|
|
491
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
492
|
+
compatibility: "reader-floor",
|
|
493
|
+
applicability: "detectable",
|
|
494
|
+
summary: "Scalar fields may constrain writes to a persisted typed choice list."
|
|
495
|
+
}), Object.freeze({
|
|
496
|
+
id: "action-semantics",
|
|
497
|
+
introducedInModel: 2,
|
|
498
|
+
minReaderModel: 0,
|
|
499
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
500
|
+
compatibility: "additive",
|
|
501
|
+
applicability: "detectable",
|
|
502
|
+
summary: "Ordinary actions may carry advisory workflow semantics."
|
|
503
|
+
}), Object.freeze({
|
|
504
|
+
id: "inclusive-scalar-bounds",
|
|
505
|
+
introducedInModel: 2,
|
|
506
|
+
minReaderModel: 2,
|
|
507
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
508
|
+
compatibility: "reader-floor",
|
|
509
|
+
applicability: "detectable",
|
|
510
|
+
summary: "String, text, and number values may carry persisted inclusive bounds."
|
|
511
|
+
}), Object.freeze({
|
|
512
|
+
id: "progress-field-kind",
|
|
513
|
+
introducedInModel: 3,
|
|
514
|
+
minReaderModel: 0,
|
|
515
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
516
|
+
compatibility: "additive",
|
|
517
|
+
applicability: "detectable",
|
|
518
|
+
summary: "A progress field kind carries application-defined 0–100 completion."
|
|
519
|
+
}), Object.freeze({
|
|
520
|
+
id: "effect-claim-tokens",
|
|
521
|
+
introducedInModel: 3,
|
|
522
|
+
minReaderModel: 0,
|
|
523
|
+
documentTypes: Object.freeze([ "instance" ]),
|
|
524
|
+
compatibility: "additive",
|
|
525
|
+
applicability: "detectable",
|
|
526
|
+
summary: "Pending-effect claims carry an exact-claim token gating mid-dispatch state reports."
|
|
527
|
+
}), Object.freeze({
|
|
528
|
+
id: "classified-principal-ids",
|
|
529
|
+
introducedInModel: 4,
|
|
530
|
+
minReaderModel: 4,
|
|
531
|
+
documentTypes: Object.freeze([ "instance" ]),
|
|
532
|
+
compatibility: "reader-floor",
|
|
533
|
+
applicability: "unconditional",
|
|
534
|
+
summary: "Principal ids are namespace-classified: actor and assignee writes carry the account-global user id only, and readers resolve legacy project-scoped ids through the prefix classifier at the instance read funnel."
|
|
535
|
+
}), Object.freeze({
|
|
536
|
+
id: "readiness-requirements",
|
|
537
|
+
introducedInModel: 4,
|
|
538
|
+
minReaderModel: 4,
|
|
539
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
540
|
+
compatibility: "reader-floor",
|
|
541
|
+
applicability: "detectable",
|
|
542
|
+
summary: "Start and activity readiness use named polymorphic requirement arrays."
|
|
543
|
+
}), Object.freeze({
|
|
544
|
+
id: "due-date-field-kinds",
|
|
545
|
+
introducedInModel: 5,
|
|
546
|
+
minReaderModel: 0,
|
|
547
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
548
|
+
compatibility: "additive",
|
|
549
|
+
applicability: "detectable",
|
|
550
|
+
summary: "Due-date field kinds (dueDate, dueDatetime) mark a level deadline, elevated aliases of date/datetime carrying the same stored value."
|
|
551
|
+
}), Object.freeze({
|
|
552
|
+
id: "node-semantics",
|
|
553
|
+
introducedInModel: 6,
|
|
554
|
+
minReaderModel: 0,
|
|
555
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
556
|
+
compatibility: "additive",
|
|
557
|
+
applicability: "detectable",
|
|
558
|
+
summary: "Workflow, stage, activity, and action nodes may carry signal or custom advisory semantics."
|
|
559
|
+
}), Object.freeze({
|
|
560
|
+
id: "field-patch-ops",
|
|
561
|
+
introducedInModel: 6,
|
|
562
|
+
minReaderModel: 0,
|
|
563
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
564
|
+
compatibility: "additive",
|
|
565
|
+
applicability: "detectable",
|
|
566
|
+
summary: "Field ops may increment, decrement, or initialize a missing field value."
|
|
567
|
+
}), Object.freeze({
|
|
568
|
+
id: "attributes-condition-var",
|
|
569
|
+
introducedInModel: 7,
|
|
570
|
+
minReaderModel: 0,
|
|
571
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
572
|
+
compatibility: "additive",
|
|
573
|
+
applicability: "unconditional",
|
|
574
|
+
summary: "Caller-bound $attributes condition variable binds the acting token's org-level User Attributes (advisory; absent when unavailable)."
|
|
575
|
+
}) ]);
|
|
576
|
+
|
|
577
|
+
function recordOf(value) {
|
|
578
|
+
return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function recordsAt(record, key) {
|
|
582
|
+
const value = record[key];
|
|
583
|
+
return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function nestedFieldEntries(entries) {
|
|
587
|
+
return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function parsedDefinitionSnapshot(root) {
|
|
591
|
+
if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
|
|
592
|
+
_id: typeof root._id == "string" ? root._id : "<unknown instance>",
|
|
593
|
+
definitionSnapshot: root.definitionSnapshot
|
|
594
|
+
}));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function persistedDefinitionTree(document) {
|
|
598
|
+
const root = recordOf(document);
|
|
599
|
+
if (root === void 0) return;
|
|
600
|
+
const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], {stages: stages, activities: activities, actions: actions} = definitionDescendants(roots);
|
|
601
|
+
return {
|
|
602
|
+
roots: roots,
|
|
603
|
+
stages: stages,
|
|
604
|
+
activities: activities,
|
|
605
|
+
actions: actions
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function persistedFieldEntries(document) {
|
|
610
|
+
const tree = persistedDefinitionTree(document);
|
|
611
|
+
if (tree === void 0) return [];
|
|
612
|
+
const {roots: roots, stages: stages, activities: activities, actions: actions} = tree, effects = actions.flatMap(action => recordsAt(action, "effects"));
|
|
613
|
+
return nestedFieldEntries([ ...roots.flatMap(candidate => recordsAt(candidate, "fields")), ...stages.flatMap(stage => recordsAt(stage, "fields")), ...activities.flatMap(activity => recordsAt(activity, "fields")), ...actions.flatMap(action => recordsAt(action, "params")), ...effects.flatMap(effect => recordsAt(effect, "outputs")) ]);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function definitionDescendants(roots) {
|
|
617
|
+
const stages = roots.flatMap(root => recordsAt(root, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions"));
|
|
618
|
+
return {
|
|
619
|
+
stages: stages,
|
|
620
|
+
activities: activities,
|
|
621
|
+
actions: actions
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function hasChoiceList(document) {
|
|
626
|
+
return persistedFieldEntries(document).some(entry => {
|
|
627
|
+
const options = recordOf(entry.options);
|
|
628
|
+
return options !== void 0 && Array.isArray(options.list);
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function hasFieldKind(document, kind) {
|
|
633
|
+
return persistedFieldEntries(document).some(entry => entry.type === kind || entry._type === kind);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function definitionNodes(document) {
|
|
637
|
+
const root = recordOf(document);
|
|
638
|
+
if (root !== void 0) return {
|
|
639
|
+
root: root,
|
|
640
|
+
...definitionDescendants([ root ])
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function hasActionSemantics(document) {
|
|
645
|
+
return definitionNodes(document)?.actions.some(hasSemantics) ?? !1;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function hasNodeSemantics(document) {
|
|
649
|
+
const nodes = definitionNodes(document);
|
|
650
|
+
return nodes === void 0 ? !1 : [ nodes.root, ...nodes.stages, ...nodes.activities ].some(hasSemantics) ? !0 : nodes.actions.some(action => hasSemantics(action) && action.semantics.some(isNodeSemanticValue));
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function isNodeSemanticValue(semantic) {
|
|
654
|
+
return typeof semantic == "string" && (semantic.startsWith("signal.") || semantic.startsWith("custom."));
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function hasSemantics(node) {
|
|
658
|
+
return Array.isArray(node.semantics);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function hasPersistedOpType(document, types) {
|
|
662
|
+
const tree = persistedDefinitionTree(document);
|
|
663
|
+
return tree === void 0 ? !1 : tree.actions.flatMap(action => recordsAt(action, "ops")).some(op => typeof op.type == "string" && types.includes(op.type)) ? !0 : tree.roots.some(root => recordsAt(root, "history").some(entry => entry._type === "opApplied" && typeof entry.opType == "string" && types.includes(entry.opType)));
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function hasScalarValidation(document) {
|
|
667
|
+
return persistedFieldEntries(document).some(entry => {
|
|
668
|
+
const validation = recordOf(entry.validation);
|
|
669
|
+
return typeof validation?.min == "number" || typeof validation?.max == "number";
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function hasClaimTokens(document) {
|
|
674
|
+
const root = recordOf(document);
|
|
675
|
+
return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
|
|
676
|
+
const claim = recordOf(entry.claim);
|
|
677
|
+
return claim !== void 0 && typeof claim.claimToken == "string";
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
function hasReadinessRequirements(document) {
|
|
682
|
+
const root = recordOf(document);
|
|
683
|
+
return root === void 0 ? !1 : Array.isArray(recordOf(root.start)?.requirements) ? !0 : recordsAt(root, "stages").some(stage => recordsAt(stage, "activities").some(activity => Array.isArray(activity.requirements)));
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const featureDetectors = {
|
|
687
|
+
"governed-model-stamps": () => !0,
|
|
688
|
+
"subject-field-kind": document => hasFieldKind(document, "subject"),
|
|
689
|
+
"typed-scalar-choice-lists": hasChoiceList,
|
|
690
|
+
"action-semantics": hasActionSemantics,
|
|
691
|
+
"inclusive-scalar-bounds": hasScalarValidation,
|
|
692
|
+
"progress-field-kind": document => hasFieldKind(document, "progress"),
|
|
693
|
+
"effect-claim-tokens": hasClaimTokens,
|
|
694
|
+
"classified-principal-ids": () => !0,
|
|
695
|
+
"readiness-requirements": hasReadinessRequirements,
|
|
696
|
+
"due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime"),
|
|
697
|
+
"node-semantics": hasNodeSemantics,
|
|
698
|
+
"field-patch-ops": document => hasPersistedOpType(document, [ "field.inc", "field.dec", "field.setIfMissing" ]),
|
|
699
|
+
"attributes-condition-var": () => !0
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
function requiredModelFeatures(documentType, document) {
|
|
703
|
+
return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function requiredReaderModel(documentType, document) {
|
|
707
|
+
return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function modelStampFor(args) {
|
|
711
|
+
return {
|
|
712
|
+
modelVersion: DATA_MODEL_VERSION,
|
|
713
|
+
minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
function fieldTreeShape(value) {
|
|
718
|
+
if (Array.isArray(value)) return value.map(fieldTreeShape);
|
|
719
|
+
if (value === null) return "null";
|
|
720
|
+
if (typeof value == "object") {
|
|
721
|
+
const record = value;
|
|
722
|
+
return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
|
|
723
|
+
}
|
|
724
|
+
return typeof value;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function modelVersionOf(doc) {
|
|
728
|
+
const stamp = doc.modelVersion;
|
|
729
|
+
return typeof stamp == "number" ? stamp : 0;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
function minReaderModelOf(doc) {
|
|
733
|
+
const floor = doc.minReaderModel;
|
|
734
|
+
return typeof floor == "number" ? floor : modelVersionOf(doc);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
class ModelVersionAheadError extends invariants.WorkflowError {
|
|
738
|
+
documentId;
|
|
739
|
+
documentModelVersion;
|
|
740
|
+
requiredReaderModel;
|
|
741
|
+
engineModelVersion;
|
|
742
|
+
constructor(args) {
|
|
743
|
+
super("model-version-ahead", `Document "${args.documentId}" was written by engine data model ${args.documentModelVersion} and requires a reader at model ${args.requiredReaderModel} or newer; this engine reads up to model ${DATA_MODEL_VERSION}. Upgrade @sanity/workflow-engine to a version that understands it.`),
|
|
744
|
+
this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
|
|
745
|
+
this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
function assertReadableModel(doc) {
|
|
750
|
+
const documentReaderModel = minReaderModelOf(doc);
|
|
751
|
+
if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
|
|
752
|
+
documentId: doc._id,
|
|
753
|
+
documentModelVersion: modelVersionOf(doc),
|
|
754
|
+
requiredReaderModel: documentReaderModel
|
|
755
|
+
});
|
|
756
|
+
return doc;
|
|
757
|
+
}
|
|
758
|
+
|
|
405
759
|
function effectSites(def) {
|
|
406
760
|
const sites = [];
|
|
407
761
|
for (const stage of def.stages ?? []) for (const activity of stage.activities ?? []) for (const action of activity.actions ?? []) for (const effect of action.effects ?? []) sites.push({
|
|
@@ -876,12 +1230,8 @@ function renderWorkflowRead(read, ctx) {
|
|
|
876
1230
|
text: groqConditionDescribe.guillemets(title)
|
|
877
1231
|
});
|
|
878
1232
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
permission: read.path[0]
|
|
882
|
-
},
|
|
883
|
-
text: `your ${read.path[0]} permission`
|
|
884
|
-
});
|
|
1233
|
+
const keyed = keyedCallerRead(read);
|
|
1234
|
+
if (keyed !== void 0) return keyed;
|
|
885
1235
|
if (read.variable === "actor" && read.path.length === 1 && read.path[0] === "id") return groqConditionDescribe.phrase("read.actor-id", {
|
|
886
1236
|
params: {},
|
|
887
1237
|
text: "your id"
|
|
@@ -903,6 +1253,24 @@ function renderWorkflowRead(read, ctx) {
|
|
|
903
1253
|
});
|
|
904
1254
|
}
|
|
905
1255
|
|
|
1256
|
+
function keyedCallerRead(read) {
|
|
1257
|
+
const key = read.path[0];
|
|
1258
|
+
if (typeof key == "string") {
|
|
1259
|
+
if (read.variable === "can") return groqConditionDescribe.phrase("read.permission", {
|
|
1260
|
+
params: {
|
|
1261
|
+
permission: key
|
|
1262
|
+
},
|
|
1263
|
+
text: `your ${key} permission`
|
|
1264
|
+
});
|
|
1265
|
+
if (read.variable === "attributes") return groqConditionDescribe.phrase("read.attribute", {
|
|
1266
|
+
params: {
|
|
1267
|
+
attribute: key
|
|
1268
|
+
},
|
|
1269
|
+
text: `your ${groqConditionDescribe.guillemets(key)} attribute`
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
906
1274
|
function workflowRequirement(requirement, ctx) {
|
|
907
1275
|
const {target: target} = requirement, clause = clauseVarRequirement(requirement);
|
|
908
1276
|
if (clause !== void 0) return clause;
|
|
@@ -1803,12 +2171,16 @@ function derefBase(ref, snapshot) {
|
|
|
1803
2171
|
};
|
|
1804
2172
|
}
|
|
1805
2173
|
|
|
2174
|
+
function isRecord(value) {
|
|
2175
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
2176
|
+
}
|
|
2177
|
+
|
|
1806
2178
|
function buildParams(args) {
|
|
1807
2179
|
const {instance: instance, now: now, snapshot: snapshot, extra: extra} = args, currentActivities2 = findOpenStageEntry(instance)?.activities ?? [];
|
|
1808
2180
|
return {
|
|
1809
2181
|
self: invariants.selfGdr(instance),
|
|
1810
2182
|
fields: renderedFields(instance.fields ?? [], snapshot),
|
|
1811
|
-
parent:
|
|
2183
|
+
parent: parentRef(instance)?.id ?? null,
|
|
1812
2184
|
ancestors: instance.ancestors.map(a => a.id),
|
|
1813
2185
|
stage: instance.currentStage,
|
|
1814
2186
|
now: now,
|
|
@@ -2273,6 +2645,12 @@ function isRevisionConflict(error) {
|
|
|
2273
2645
|
return statusCode === 409 ? !0 : typeof message == "string" && message.includes("ifRevisionId check failed");
|
|
2274
2646
|
}
|
|
2275
2647
|
|
|
2648
|
+
function isCreateIdCollision(error) {
|
|
2649
|
+
if (typeof error != "object" || error === null) return !1;
|
|
2650
|
+
const {message: message, responseBody: responseBody} = error;
|
|
2651
|
+
return typeof message == "string" && message.includes("already exists") && (message.includes("Document by ID") || message.includes("create() failed")) ? !0 : typeof responseBody == "string" && responseBody.includes("documentAlreadyExistsError");
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2276
2654
|
class ConcurrentEditFieldError extends invariants.WorkflowError {
|
|
2277
2655
|
instanceId;
|
|
2278
2656
|
target;
|
|
@@ -2325,7 +2703,7 @@ class CascadeLimitError extends invariants.WorkflowError {
|
|
|
2325
2703
|
}
|
|
2326
2704
|
}
|
|
2327
2705
|
|
|
2328
|
-
const FIELD_OP_TYPES = [ "field.set", "field.unset", "field.append", "field.updateWhere", "field.removeWhere" ];
|
|
2706
|
+
const FIELD_OP_TYPES = [ "field.set", "field.setIfMissing", "field.unset", "field.append", "field.inc", "field.dec", "field.updateWhere", "field.removeWhere" ];
|
|
2329
2707
|
|
|
2330
2708
|
function isFieldOp(summary) {
|
|
2331
2709
|
return FIELD_OP_TYPES.includes(summary.opType);
|
|
@@ -2426,7 +2804,7 @@ async function runOps(args) {
|
|
|
2426
2804
|
refSurface: refSurface,
|
|
2427
2805
|
opsFromDefinition: opsFromDefinition
|
|
2428
2806
|
});
|
|
2429
|
-
summaries.push(summary), mutation.history.push(opAppliedEntry({
|
|
2807
|
+
summaries.push(summary), shouldRecordOpApplied(summary) && mutation.history.push(opAppliedEntry({
|
|
2430
2808
|
origin: origin,
|
|
2431
2809
|
summary: summary,
|
|
2432
2810
|
stage: stage,
|
|
@@ -2437,6 +2815,10 @@ async function runOps(args) {
|
|
|
2437
2815
|
return summaries;
|
|
2438
2816
|
}
|
|
2439
2817
|
|
|
2818
|
+
function shouldRecordOpApplied(summary) {
|
|
2819
|
+
return summary.opType !== "field.setIfMissing" || summary.resolved !== void 0;
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2440
2822
|
function opAppliedEntry(args) {
|
|
2441
2823
|
const {origin: origin, summary: summary, stage: stage, actor: actor, now: now} = args;
|
|
2442
2824
|
return {
|
|
@@ -2508,12 +2890,19 @@ async function applyOp(op, ctx) {
|
|
|
2508
2890
|
case "field.set":
|
|
2509
2891
|
return applyFieldSet(op, ctx);
|
|
2510
2892
|
|
|
2893
|
+
case "field.setIfMissing":
|
|
2894
|
+
return applyFieldSetIfMissing(op, ctx);
|
|
2895
|
+
|
|
2511
2896
|
case "field.unset":
|
|
2512
2897
|
return applyFieldUnset(op, ctx);
|
|
2513
2898
|
|
|
2514
2899
|
case "field.append":
|
|
2515
2900
|
return applyFieldAppend(op, ctx);
|
|
2516
2901
|
|
|
2902
|
+
case "field.inc":
|
|
2903
|
+
case "field.dec":
|
|
2904
|
+
return applyFieldArithmetic(op, ctx);
|
|
2905
|
+
|
|
2517
2906
|
case "field.updateWhere":
|
|
2518
2907
|
return applyFieldUpdateWhere(op, ctx);
|
|
2519
2908
|
|
|
@@ -2552,6 +2941,78 @@ function applyFieldSet(op, ctx) {
|
|
|
2552
2941
|
};
|
|
2553
2942
|
}
|
|
2554
2943
|
|
|
2944
|
+
function applyFieldSetIfMissing(op, ctx) {
|
|
2945
|
+
const entry = locateEntry(ctx, op.target);
|
|
2946
|
+
return invariants.isAlwaysArrayFieldKind(entry._type) && rejectFieldOpTarget({
|
|
2947
|
+
entry: entry,
|
|
2948
|
+
op: op,
|
|
2949
|
+
issue: "is always array-valued — setIfMissing applies to nullable entries only; an empty array entry already holds []"
|
|
2950
|
+
}), entry.value !== null && entry.value !== void 0 ? {
|
|
2951
|
+
opType: op.type,
|
|
2952
|
+
target: op.target
|
|
2953
|
+
} : {
|
|
2954
|
+
...applyFieldSet({
|
|
2955
|
+
...op,
|
|
2956
|
+
type: "field.set"
|
|
2957
|
+
}, ctx),
|
|
2958
|
+
opType: op.type
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
function applyFieldArithmetic(op, ctx) {
|
|
2963
|
+
const entry = locateEntry(ctx, op.target);
|
|
2964
|
+
entry._type !== "number" && rejectFieldOpTarget({
|
|
2965
|
+
entry: entry,
|
|
2966
|
+
op: op,
|
|
2967
|
+
issue: `is a ${entry._type} entry — arithmetic ops target \`number\` entries only`
|
|
2968
|
+
}), typeof entry.value != "number" && rejectFieldOpTarget({
|
|
2969
|
+
entry: entry,
|
|
2970
|
+
op: op,
|
|
2971
|
+
issue: "has no numeric value — initialize it before applying arithmetic"
|
|
2972
|
+
});
|
|
2973
|
+
const resolvedDelta = op.value === void 0 ? 1 : resolveOpValue({
|
|
2974
|
+
src: op.value,
|
|
2975
|
+
ctx: ctx,
|
|
2976
|
+
target: {
|
|
2977
|
+
kind: "number"
|
|
2978
|
+
}
|
|
2979
|
+
});
|
|
2980
|
+
(typeof resolvedDelta != "number" || !Number.isFinite(resolvedDelta)) && rejectFieldOpTarget({
|
|
2981
|
+
entry: entry,
|
|
2982
|
+
op: op,
|
|
2983
|
+
issue: "value must resolve to a finite number"
|
|
2984
|
+
});
|
|
2985
|
+
const nextValue = entry.value + (op.type === "field.inc" ? resolvedDelta : -resolvedDelta);
|
|
2986
|
+
Number.isFinite(nextValue) || rejectFieldOpTarget({
|
|
2987
|
+
entry: entry,
|
|
2988
|
+
op: op,
|
|
2989
|
+
issue: "result must be a finite number"
|
|
2990
|
+
});
|
|
2991
|
+
const value = invariants.validateFieldValue({
|
|
2992
|
+
entryType: entry._type,
|
|
2993
|
+
entryName: entry.name,
|
|
2994
|
+
value: nextValue,
|
|
2995
|
+
...entryShape(entry)
|
|
2996
|
+
});
|
|
2997
|
+
return setEntryValue(entry, value), {
|
|
2998
|
+
opType: op.type,
|
|
2999
|
+
target: op.target,
|
|
3000
|
+
resolved: {
|
|
3001
|
+
value: value
|
|
3002
|
+
}
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
function rejectFieldOpTarget(args) {
|
|
3007
|
+
const {entry: entry, op: op, issue: issue} = args;
|
|
3008
|
+
throw new invariants.FieldValueShapeError({
|
|
3009
|
+
entryType: entry._type,
|
|
3010
|
+
entryName: entry.name,
|
|
3011
|
+
mode: "value",
|
|
3012
|
+
issues: [ `${op.type} target ${op.target.scope}:"${op.target.field}" ${issue}` ]
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
|
|
2555
3016
|
function entryShape(entry) {
|
|
2556
3017
|
return entry._type === "object" ? {
|
|
2557
3018
|
fields: entry.fields
|
|
@@ -2587,15 +3048,10 @@ function appendItemSlot(entry) {
|
|
|
2587
3048
|
};
|
|
2588
3049
|
}
|
|
2589
3050
|
|
|
2590
|
-
const EMPTY_BY_KIND = {
|
|
2591
|
-
"doc.refs": [],
|
|
2592
|
-
array: [],
|
|
2593
|
-
assignees: []
|
|
2594
|
-
};
|
|
2595
|
-
|
|
2596
3051
|
function applyFieldUnset(op, ctx) {
|
|
2597
3052
|
const entry = locateEntry(ctx, op.target);
|
|
2598
|
-
return setEntryValue(entry,
|
|
3053
|
+
return setEntryValue(entry, invariants.isAlwaysArrayFieldKind(entry._type) ? [] : null),
|
|
3054
|
+
{
|
|
2599
3055
|
opType: op.type,
|
|
2600
3056
|
target: op.target
|
|
2601
3057
|
};
|
|
@@ -2634,7 +3090,7 @@ function applyFieldAppend(op, ctx) {
|
|
|
2634
3090
|
}
|
|
2635
3091
|
|
|
2636
3092
|
function withRowKey(item) {
|
|
2637
|
-
return
|
|
3093
|
+
return isRecord(item) && !("_key" in item) ? {
|
|
2638
3094
|
_key: randomKey(),
|
|
2639
3095
|
...item
|
|
2640
3096
|
} : item;
|
|
@@ -3333,6 +3789,14 @@ function latestDeployedDefinitions(rows) {
|
|
|
3333
3789
|
return [ ...byName.values() ];
|
|
3334
3790
|
}
|
|
3335
3791
|
|
|
3792
|
+
function findStageNode(args) {
|
|
3793
|
+
return args.definition?.stages.find(entry => entry.name === args.stageName);
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
function findActivityNode(args) {
|
|
3797
|
+
return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3336
3800
|
function liveChildrenField(instance) {
|
|
3337
3801
|
const live = liveSubworkflows(instance).length;
|
|
3338
3802
|
return live > 0 ? {
|
|
@@ -3421,8 +3885,29 @@ function noTransitionFiresCause(input) {
|
|
|
3421
3885
|
};
|
|
3422
3886
|
}
|
|
3423
3887
|
|
|
3888
|
+
function stuckFromDocumentState(input) {
|
|
3889
|
+
return failedEffectCause(input) ?? failedActivityCause(input) ?? hungEffectCause(input);
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
function documentStuckCause(args) {
|
|
3893
|
+
const stage = findOpenStageEntry(args.instance);
|
|
3894
|
+
if (stage !== void 0) return stuckFromDocumentState({
|
|
3895
|
+
instance: args.instance,
|
|
3896
|
+
activities: stage.activities.map(entry => ({
|
|
3897
|
+
status: entry.status,
|
|
3898
|
+
activity: findActivityNode({
|
|
3899
|
+
activityName: entry.name,
|
|
3900
|
+
definition: args.definition,
|
|
3901
|
+
stageName: stage.name
|
|
3902
|
+
}) ?? {
|
|
3903
|
+
name: entry.name
|
|
3904
|
+
}
|
|
3905
|
+
}))
|
|
3906
|
+
});
|
|
3907
|
+
}
|
|
3908
|
+
|
|
3424
3909
|
function diagnoseInstance(input) {
|
|
3425
|
-
const {instance: instance} = input, terminal =
|
|
3910
|
+
const {instance: instance} = input, terminal = terminalState(instance);
|
|
3426
3911
|
if (terminal === "aborted" && instance.abortedAt !== void 0) {
|
|
3427
3912
|
const reason = abortReason(instance);
|
|
3428
3913
|
return {
|
|
@@ -3439,7 +3924,7 @@ function diagnoseInstance(input) {
|
|
|
3439
3924
|
at: instance.completedAt,
|
|
3440
3925
|
...liveChildrenField(instance)
|
|
3441
3926
|
};
|
|
3442
|
-
const cause =
|
|
3927
|
+
const cause = stuckFromDocumentState(input) ?? noTransitionFiresCause(input);
|
|
3443
3928
|
return cause !== void 0 ? {
|
|
3444
3929
|
state: "stuck",
|
|
3445
3930
|
cause: cause
|
|
@@ -3576,7 +4061,7 @@ function liveSubworkflowRefs(instance) {
|
|
|
3576
4061
|
}
|
|
3577
4062
|
|
|
3578
4063
|
function readsRaw(ref) {
|
|
3579
|
-
return ref.type ===
|
|
4064
|
+
return ref.type === WORKFLOW_INSTANCE_TYPE || ref.type === "system.release";
|
|
3580
4065
|
}
|
|
3581
4066
|
|
|
3582
4067
|
const DEFAULT_CONTENT_PERSPECTIVE = "drafts";
|
|
@@ -3818,10 +4303,8 @@ function assertRequiredInputProvided({entryDefs: entryDefs, initialFields: initi
|
|
|
3818
4303
|
});
|
|
3819
4304
|
}
|
|
3820
4305
|
|
|
3821
|
-
const ARRAY_FIELD_TYPES = /* @__PURE__ */ new Set([ "doc.refs", "array", "assignees" ]);
|
|
3822
|
-
|
|
3823
4306
|
function defaultEntryValue(entryType) {
|
|
3824
|
-
return
|
|
4307
|
+
return invariants.isAlwaysArrayFieldKind(entryType) ? [] : null;
|
|
3825
4308
|
}
|
|
3826
4309
|
|
|
3827
4310
|
function resolveInputValue({entry: entry, initialFields: initialFields, defaultValue: defaultValue}) {
|
|
@@ -4350,7 +4833,7 @@ const TransitionVia = v__namespace.exactOptional(v__namespace.picklist([ "transi
|
|
|
4350
4833
|
_type: v__namespace.pipe(v__namespace.string(), v__namespace.check(t => !knownHistoryTypes.has(t), "must not shadow a known history variant"))
|
|
4351
4834
|
}), HistoryEntrySchema = v__namespace.union([ v__namespace.variant("_type", HISTORY_ARMS), UnknownHistoryEntry ]), WorkflowInstanceSchema = v__namespace.looseObject(invariants.tolerantEntries()({
|
|
4352
4835
|
_id: NonEmpty,
|
|
4353
|
-
_type: v__namespace.literal(
|
|
4836
|
+
_type: v__namespace.literal(WORKFLOW_INSTANCE_TYPE),
|
|
4354
4837
|
_rev: v__namespace.string(),
|
|
4355
4838
|
_createdAt: invariants.IsoTimestamp,
|
|
4356
4839
|
_updatedAt: invariants.IsoTimestamp,
|
|
@@ -4383,7 +4866,7 @@ function parseInstanceDocument(doc) {
|
|
|
4383
4866
|
return invariants.parsePersistedDoc({
|
|
4384
4867
|
schema: WorkflowInstanceSchema,
|
|
4385
4868
|
doc: doc,
|
|
4386
|
-
docType:
|
|
4869
|
+
docType: WORKFLOW_INSTANCE_TYPE
|
|
4387
4870
|
});
|
|
4388
4871
|
}
|
|
4389
4872
|
|
|
@@ -4422,7 +4905,9 @@ const SYNC_COMMIT = {
|
|
|
4422
4905
|
effect: "workflow.effect",
|
|
4423
4906
|
verifyDefinitions: "workflow.verify-definitions",
|
|
4424
4907
|
accessResolveActor: "workflow.access.resolve-actor",
|
|
4425
|
-
accessGrants: "workflow.access.grants"
|
|
4908
|
+
accessGrants: "workflow.access.grants",
|
|
4909
|
+
accessResolveOrg: "workflow.access.resolve-org",
|
|
4910
|
+
accessAttributes: "workflow.access.attributes"
|
|
4426
4911
|
}, RAW_PATCH = /* @__PURE__ */ Symbol("workflow-engine.raw-patch");
|
|
4427
4912
|
|
|
4428
4913
|
function unwrapPatch(patch) {
|
|
@@ -4829,7 +5314,7 @@ async function getInstanceDocument(client, instanceId) {
|
|
|
4829
5314
|
}
|
|
4830
5315
|
|
|
4831
5316
|
function readInstanceDoc(doc) {
|
|
4832
|
-
return parseInstanceDocument(
|
|
5317
|
+
return parseInstanceDocument(assertReadableModel(doc));
|
|
4833
5318
|
}
|
|
4834
5319
|
|
|
4835
5320
|
async function reload({client: client, instanceId: instanceId, tag: tag}) {
|
|
@@ -4900,7 +5385,7 @@ function buildInstanceBase(args) {
|
|
|
4900
5385
|
} : {}
|
|
4901
5386
|
}, ...args.extraHistory ?? [] ], history = executionContext !== void 0 ? stampHistoryEntries(entries, executionContext) : entries, body = {
|
|
4902
5387
|
_id: id,
|
|
4903
|
-
_type:
|
|
5388
|
+
_type: WORKFLOW_INSTANCE_TYPE,
|
|
4904
5389
|
_rev: "",
|
|
4905
5390
|
_createdAt: now,
|
|
4906
5391
|
_updatedAt: now,
|
|
@@ -4929,7 +5414,7 @@ function buildInstanceBase(args) {
|
|
|
4929
5414
|
};
|
|
4930
5415
|
return {
|
|
4931
5416
|
...body,
|
|
4932
|
-
...
|
|
5417
|
+
...modelStampFor({
|
|
4933
5418
|
documentType: "instance",
|
|
4934
5419
|
document: body
|
|
4935
5420
|
})
|
|
@@ -5027,7 +5512,7 @@ async function readBatch(args) {
|
|
|
5027
5512
|
}
|
|
5028
5513
|
|
|
5029
5514
|
function validateRawDoc(doc, perspective) {
|
|
5030
|
-
return perspective !== "raw" ? doc : doc._type ===
|
|
5515
|
+
return perspective !== "raw" ? doc : doc._type === WORKFLOW_INSTANCE_TYPE ? readInstanceDoc(doc) : assertReadableModel(doc);
|
|
5031
5516
|
}
|
|
5032
5517
|
|
|
5033
5518
|
function groupReads(reads) {
|
|
@@ -5110,7 +5595,7 @@ async function loadContext({client: client, instanceId: instanceId, options: opt
|
|
|
5110
5595
|
clientForGdr: options.clientForGdr,
|
|
5111
5596
|
refSurface: options.refSurface,
|
|
5112
5597
|
instance: instance,
|
|
5113
|
-
definition:
|
|
5598
|
+
definition: parseDefinitionSnapshot(instance),
|
|
5114
5599
|
...options.actor !== void 0 ? {
|
|
5115
5600
|
actor: options.actor
|
|
5116
5601
|
} : {},
|
|
@@ -5390,10 +5875,6 @@ function userLoginProvider(user) {
|
|
|
5390
5875
|
return user?.provider ?? user?.loginProvider;
|
|
5391
5876
|
}
|
|
5392
5877
|
|
|
5393
|
-
function isRecord(value) {
|
|
5394
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
5395
|
-
}
|
|
5396
|
-
|
|
5397
5878
|
function optionalString(value) {
|
|
5398
5879
|
return value === void 0 || typeof value == "string";
|
|
5399
5880
|
}
|
|
@@ -5898,12 +6379,14 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
5898
6379
|
|
|
5899
6380
|
async function upsertGuard(args) {
|
|
5900
6381
|
const {client: client, doc: doc, exists: exists} = args;
|
|
5901
|
-
if (!exists) {
|
|
6382
|
+
if (!exists) try {
|
|
5902
6383
|
await client.create(doc, {
|
|
5903
6384
|
...SYNC_COMMIT,
|
|
5904
6385
|
tag: REQUEST_TAG.guardDeploy
|
|
5905
6386
|
});
|
|
5906
6387
|
return;
|
|
6388
|
+
} catch (error) {
|
|
6389
|
+
if (!isCreateIdCollision(error)) throw error;
|
|
5907
6390
|
}
|
|
5908
6391
|
const {_id: _id, _type: _type, _rev: _rev, _createdAt: _createdAt, _updatedAt: _updatedAt, ...body} = doc;
|
|
5909
6392
|
await client.patch(doc._id).set(body).commit({
|
|
@@ -6249,7 +6732,7 @@ async function persistThenDeploy({ctx: ctx, mutation: mutation, deploy: deploy})
|
|
|
6249
6732
|
committedRev: committed._rev,
|
|
6250
6733
|
restore: instanceStateFields({
|
|
6251
6734
|
...ctx.instance,
|
|
6252
|
-
minReaderModel:
|
|
6735
|
+
minReaderModel: minReaderModelOf(ctx.instance)
|
|
6253
6736
|
}),
|
|
6254
6737
|
unset: ctx.instance.completedAt === void 0 ? [ "completedAt" ] : [],
|
|
6255
6738
|
reversible: !spawned,
|
|
@@ -6615,16 +7098,16 @@ async function resolveDefinitionRef({client: client, ref: ref, tag: tag}) {
|
|
|
6615
7098
|
};
|
|
6616
7099
|
wantsExplicit && (params.version = ref.version);
|
|
6617
7100
|
const result = await client.fetch(definitionLookupGroq(wantsExplicit), params);
|
|
6618
|
-
return result ?
|
|
7101
|
+
return result ? assertReadableModel(result) : null;
|
|
6619
7102
|
}
|
|
6620
7103
|
|
|
6621
7104
|
async function prepareChildInstance(args) {
|
|
6622
7105
|
const {client: client, parent: parent, definition: definition, initialFields: initialFields, context: context, actor: actor, now: now, refSurface: refSurface} = args, childTag = parent.tag, workflowResource = parent.workflowResource, childDocId = instanceDocId(childTag), childRef = {
|
|
6623
7106
|
id: invariants.gdrFromResource(workflowResource, childDocId),
|
|
6624
|
-
type:
|
|
7107
|
+
type: WORKFLOW_INSTANCE_TYPE
|
|
6625
7108
|
}, ancestors = [ ...parent.ancestors, {
|
|
6626
7109
|
id: invariants.selfGdr(parent),
|
|
6627
|
-
type:
|
|
7110
|
+
type: WORKFLOW_INSTANCE_TYPE
|
|
6628
7111
|
} ], inheritedPerspective = parent.perspective, fieldDiscards = [], childFields = await resolveDeclaredFields({
|
|
6629
7112
|
entryDefs: definition.fields,
|
|
6630
7113
|
initialFields: initialFields,
|
|
@@ -6929,53 +7412,460 @@ async function advisoryCan({instance: instance, identity: identity, grants: gran
|
|
|
6929
7412
|
return can;
|
|
6930
7413
|
}
|
|
6931
7414
|
|
|
6932
|
-
|
|
7415
|
+
const DANGEROUS_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([ "__proto__", "constructor", "prototype" ]);
|
|
7416
|
+
|
|
7417
|
+
function attributeEntry(row) {
|
|
7418
|
+
if (!(!isRecord(row) || typeof row.key != "string" || row.key.length === 0) && !DANGEROUS_ATTRIBUTE_KEYS.has(row.key) && !(!("activeValue" in row) || row.activeValue === void 0)) return [ row.key, row.activeValue ];
|
|
7419
|
+
}
|
|
7420
|
+
|
|
7421
|
+
function normalizeUserAttributes(response) {
|
|
7422
|
+
if (!isRecord(response)) return;
|
|
7423
|
+
const rows = response.attributes;
|
|
7424
|
+
if (!Array.isArray(rows)) return;
|
|
7425
|
+
const out = {};
|
|
7426
|
+
for (const row of rows) {
|
|
7427
|
+
const entry = attributeEntry(row);
|
|
7428
|
+
entry !== void 0 && (out[entry[0]] = entry[1]);
|
|
7429
|
+
}
|
|
7430
|
+
return out;
|
|
7431
|
+
}
|
|
7432
|
+
|
|
7433
|
+
const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap, orgIdCache = /* @__PURE__ */ new WeakMap, attributesCache = /* @__PURE__ */ new WeakMap;
|
|
7434
|
+
|
|
7435
|
+
async function resolveAccess(taggedClient, args = {}) {
|
|
7436
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7437
|
+
if (requestFn === void 0) throw new invariants.ContractViolationError("workflow: no actor available. The engine resolves the actor from the client's token via `client.request({ uri: '/users/me' })`. Supply a real `@sanity/client` configured with a token (the test bench serves these endpoints per registered token).");
|
|
7438
|
+
const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
|
|
7439
|
+
client: client,
|
|
7440
|
+
requestFn: requestFn,
|
|
7441
|
+
resourcePath: args.grantsFromPath
|
|
7442
|
+
}) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
|
|
7443
|
+
if (identity === void 0) throw new invariants.ContractViolationError("workflow: failed to resolve actor from `/users/me`. The client is configured but the endpoint returned no usable identity — check the token.");
|
|
6933
7444
|
return {
|
|
6934
|
-
|
|
6935
|
-
...
|
|
6936
|
-
|
|
7445
|
+
actor: identity.actor,
|
|
7446
|
+
...identity.localPrincipalId !== void 0 ? {
|
|
7447
|
+
localPrincipalId: identity.localPrincipalId
|
|
6937
7448
|
} : {},
|
|
6938
|
-
...
|
|
6939
|
-
|
|
7449
|
+
...grants !== void 0 ? {
|
|
7450
|
+
grants: grants
|
|
6940
7451
|
} : {}
|
|
6941
7452
|
};
|
|
6942
7453
|
}
|
|
6943
7454
|
|
|
6944
|
-
function
|
|
6945
|
-
|
|
7455
|
+
async function resolveUserAttributes(taggedClient) {
|
|
7456
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7457
|
+
if (requestFn !== void 0) return cachedAttributes({
|
|
7458
|
+
client: client,
|
|
7459
|
+
requestFn: requestFn
|
|
7460
|
+
});
|
|
6946
7461
|
}
|
|
6947
7462
|
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
action: args.action,
|
|
6956
|
-
reason: args.reason
|
|
6957
|
-
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
6958
|
-
this.action = args.action;
|
|
6959
|
-
}
|
|
7463
|
+
function cachedActor(client, requestFn) {
|
|
7464
|
+
const cached = actorCache.get(client);
|
|
7465
|
+
if (cached !== void 0) return cached;
|
|
7466
|
+
const pending = fetchActor(client, requestFn).catch(err => {
|
|
7467
|
+
throw actorCache.get(client) === pending && actorCache.delete(client), err;
|
|
7468
|
+
});
|
|
7469
|
+
return actorCache.set(client, pending), pending;
|
|
6960
7470
|
}
|
|
6961
7471
|
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
}
|
|
7472
|
+
function grantsForClientPath(taggedClient, resourcePath) {
|
|
7473
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7474
|
+
return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
|
|
7475
|
+
client: client,
|
|
7476
|
+
requestFn: requestFn,
|
|
7477
|
+
resourcePath: resourcePath
|
|
7478
|
+
});
|
|
6969
7479
|
}
|
|
6970
7480
|
|
|
6971
|
-
function
|
|
6972
|
-
|
|
6973
|
-
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
7481
|
+
function lazyRequest(client) {
|
|
7482
|
+
return client.request === void 0 ? void 0 : opts => client.request(opts);
|
|
6974
7483
|
}
|
|
6975
7484
|
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
7485
|
+
function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
|
|
7486
|
+
return cachedByKey({
|
|
7487
|
+
store: grantsCache,
|
|
7488
|
+
client: client,
|
|
7489
|
+
key: resourcePath,
|
|
7490
|
+
load: () => fetchGrantsCached(requestFn, resourcePath)
|
|
7491
|
+
});
|
|
7492
|
+
}
|
|
7493
|
+
|
|
7494
|
+
function cachedByKey(args) {
|
|
7495
|
+
let byKey = args.store.get(args.client);
|
|
7496
|
+
byKey === void 0 && (byKey = /* @__PURE__ */ new Map, args.store.set(args.client, byKey));
|
|
7497
|
+
const cached = byKey.get(args.key);
|
|
7498
|
+
if (cached !== void 0) return cached;
|
|
7499
|
+
const pending = args.evictOnRejection ? args.load().catch(err => {
|
|
7500
|
+
throw byKey.get(args.key) === pending && byKey.delete(args.key), err;
|
|
7501
|
+
}) : args.load();
|
|
7502
|
+
return byKey.set(args.key, pending), pending;
|
|
7503
|
+
}
|
|
7504
|
+
|
|
7505
|
+
async function fetchActor(client, requestFn) {
|
|
7506
|
+
const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalHostId = usableId(globalUser.user), carriedId = invariants.firstCarriedGlobalId([ globalHostId, resourceId ]), sessionId = carriedId ?? globalHostId ?? resourceId;
|
|
7507
|
+
if (sessionId === void 0) return;
|
|
7508
|
+
const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
|
|
7509
|
+
client: client,
|
|
7510
|
+
sessionId: sessionId,
|
|
7511
|
+
resourceId: resourceId
|
|
7512
|
+
}) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
|
|
7513
|
+
refuseProjectScopedActor({
|
|
7514
|
+
id: id,
|
|
7515
|
+
globalUser: globalUser,
|
|
7516
|
+
globalHostId: globalHostId,
|
|
7517
|
+
bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
|
|
7518
|
+
});
|
|
7519
|
+
const roleNames = roleNamesFor(resourceUser, globalUser);
|
|
7520
|
+
return {
|
|
7521
|
+
actor: {
|
|
7522
|
+
kind: "person",
|
|
7523
|
+
id: id,
|
|
7524
|
+
...roleNames.length > 0 ? {
|
|
7525
|
+
roles: roleNames
|
|
7526
|
+
} : {}
|
|
7527
|
+
},
|
|
7528
|
+
...resourceId !== void 0 && resourceId !== id ? {
|
|
7529
|
+
localPrincipalId: resourceId
|
|
7530
|
+
} : {}
|
|
7531
|
+
};
|
|
7532
|
+
}
|
|
7533
|
+
|
|
7534
|
+
function roleNamesFor(resourceUser, globalUser) {
|
|
7535
|
+
return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
|
|
7536
|
+
}
|
|
7537
|
+
|
|
7538
|
+
const NO_BRIDGE = {
|
|
7539
|
+
status: "not-applicable"
|
|
7540
|
+
};
|
|
7541
|
+
|
|
7542
|
+
function globalRouteReason(globalUser, globalHostId) {
|
|
7543
|
+
return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
|
|
7544
|
+
}
|
|
7545
|
+
|
|
7546
|
+
async function bridgeProjectPrincipal(args) {
|
|
7547
|
+
const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
|
|
7548
|
+
return invariants.classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || invariants.classifyPrincipalId(resourceId).namespace !== "project" ? {
|
|
7549
|
+
status: "unavailable",
|
|
7550
|
+
reason: "no project-scoped principal from the resource host to address the directory with"
|
|
7551
|
+
} : directoryGlobalId({
|
|
7552
|
+
client: client,
|
|
7553
|
+
principalId: resourceId
|
|
7554
|
+
});
|
|
7555
|
+
}
|
|
7556
|
+
|
|
7557
|
+
async function directoryGlobalId(args) {
|
|
7558
|
+
const {client: client, principalId: principalId} = args, projectId = projectIdOf(client);
|
|
7559
|
+
if (projectId === void 0) return {
|
|
7560
|
+
status: "unavailable",
|
|
7561
|
+
reason: "the client reports no projectId, so its user directory has no address"
|
|
7562
|
+
};
|
|
7563
|
+
const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
|
|
7564
|
+
if (lookup.status !== "resolved") return {
|
|
7565
|
+
status: "unavailable",
|
|
7566
|
+
reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
|
|
7567
|
+
...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
|
|
7568
|
+
cause: lookup.cause
|
|
7569
|
+
} : {}
|
|
7570
|
+
};
|
|
7571
|
+
const globalId = invariants.directoryBridgeId(lookup.user.sanityUserId);
|
|
7572
|
+
return globalId === void 0 ? {
|
|
7573
|
+
status: "unavailable",
|
|
7574
|
+
reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
|
|
7575
|
+
} : {
|
|
7576
|
+
status: "resolved",
|
|
7577
|
+
globalId: globalId
|
|
7578
|
+
};
|
|
7579
|
+
}
|
|
7580
|
+
|
|
7581
|
+
function refuseProjectScopedActor(args) {
|
|
7582
|
+
const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
|
|
7583
|
+
if (invariants.classifyPrincipalId(id).namespace !== "project") return;
|
|
7584
|
+
const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
|
|
7585
|
+
bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
|
|
7586
|
+
const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
|
|
7587
|
+
throw new Error(`workflow: the caller's identity resolves to the project-scoped principal "${id}" and its account-global id could not be resolved. ${routes.join(" ")} The engine speaks account-global user ids only and never acts as a project-scoped principal.`, cause === void 0 ? void 0 : {
|
|
7588
|
+
cause: cause
|
|
7589
|
+
});
|
|
7590
|
+
}
|
|
7591
|
+
|
|
7592
|
+
function usableId(user) {
|
|
7593
|
+
if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
|
|
7594
|
+
}
|
|
7595
|
+
|
|
7596
|
+
async function fetchCurrentUser(requestFn, hostDescription) {
|
|
7597
|
+
try {
|
|
7598
|
+
return await requestFn({
|
|
7599
|
+
uri: "/users/me",
|
|
7600
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
7601
|
+
});
|
|
7602
|
+
} catch (err) {
|
|
7603
|
+
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.`, {
|
|
7604
|
+
cause: err
|
|
7605
|
+
});
|
|
7606
|
+
}
|
|
7607
|
+
}
|
|
7608
|
+
|
|
7609
|
+
async function fetchGlobalUser(client) {
|
|
7610
|
+
const sibling = globalHostRequestOf(client);
|
|
7611
|
+
if ("reason" in sibling) return {
|
|
7612
|
+
user: void 0,
|
|
7613
|
+
reason: sibling.reason,
|
|
7614
|
+
...sibling.cause !== void 0 ? {
|
|
7615
|
+
cause: sibling.cause
|
|
7616
|
+
} : {}
|
|
7617
|
+
};
|
|
7618
|
+
try {
|
|
7619
|
+
const user = await sibling.request({
|
|
7620
|
+
uri: "/users/me",
|
|
7621
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
7622
|
+
}), id = usableId(user);
|
|
7623
|
+
return sibling.requireGlobalPrincipal && id !== void 0 && invariants.classifyPrincipalId(id).namespace === "project" ? {
|
|
7624
|
+
user: void 0,
|
|
7625
|
+
reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
|
|
7626
|
+
} : {
|
|
7627
|
+
user: user
|
|
7628
|
+
};
|
|
7629
|
+
} catch (err) {
|
|
7630
|
+
return {
|
|
7631
|
+
user: void 0,
|
|
7632
|
+
reason: `global-host /users/me failed: ${invariants.errorMessage(err)}`,
|
|
7633
|
+
cause: err
|
|
7634
|
+
};
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
|
|
7638
|
+
function globalHostRequestOf(client) {
|
|
7639
|
+
if (typeof client.withConfig != "function") return {
|
|
7640
|
+
reason: "the client cannot reach the global API host (no withConfig)"
|
|
7641
|
+
};
|
|
7642
|
+
const hostResolution = resolveGlobalApiHost(client);
|
|
7643
|
+
try {
|
|
7644
|
+
const globalClient = client.withConfig({
|
|
7645
|
+
useProjectHostname: !1,
|
|
7646
|
+
apiVersion: ENGINE_API_VERSION,
|
|
7647
|
+
...hostResolution.apiHost === void 0 ? {} : {
|
|
7648
|
+
apiHost: hostResolution.apiHost
|
|
7649
|
+
}
|
|
7650
|
+
}), request = lazyRequest(globalClient);
|
|
7651
|
+
return request === void 0 ? {
|
|
7652
|
+
reason: "the global-host sibling client cannot issue requests"
|
|
7653
|
+
} : {
|
|
7654
|
+
request: request,
|
|
7655
|
+
requireGlobalPrincipal: hostResolution.requireGlobalPrincipal
|
|
7656
|
+
};
|
|
7657
|
+
} catch (err) {
|
|
7658
|
+
return {
|
|
7659
|
+
reason: `building the global-host sibling client failed: ${invariants.errorMessage(err)}`,
|
|
7660
|
+
cause: err
|
|
7661
|
+
};
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
|
|
7665
|
+
function resolveGlobalApiHost(client) {
|
|
7666
|
+
if (typeof client.config != "function") return {
|
|
7667
|
+
requireGlobalPrincipal: !1
|
|
7668
|
+
};
|
|
7669
|
+
const apiHost = client.config().apiHost;
|
|
7670
|
+
if (apiHost === void 0) return {
|
|
7671
|
+
requireGlobalPrincipal: !1
|
|
7672
|
+
};
|
|
7673
|
+
let parsed;
|
|
7674
|
+
try {
|
|
7675
|
+
parsed = new URL(apiHost);
|
|
7676
|
+
} catch {
|
|
7677
|
+
return {
|
|
7678
|
+
requireGlobalPrincipal: !0
|
|
7679
|
+
};
|
|
7680
|
+
}
|
|
7681
|
+
if (/^api\.sanity\.(io|work)$/.test(parsed.hostname)) return {
|
|
7682
|
+
requireGlobalPrincipal: !1
|
|
7683
|
+
};
|
|
7684
|
+
const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
|
|
7685
|
+
return match === null ? {
|
|
7686
|
+
requireGlobalPrincipal: !0
|
|
7687
|
+
} : (parsed.hostname = `api.sanity.${match[1]}`, {
|
|
7688
|
+
apiHost: parsed.origin,
|
|
7689
|
+
requireGlobalPrincipal: !0
|
|
7690
|
+
});
|
|
7691
|
+
}
|
|
7692
|
+
|
|
7693
|
+
async function fetchGrantsCached(requestFn, resourcePath) {
|
|
7694
|
+
try {
|
|
7695
|
+
return await fetchGrants({
|
|
7696
|
+
client: {
|
|
7697
|
+
request: requestFn
|
|
7698
|
+
},
|
|
7699
|
+
resourcePath: resourcePath
|
|
7700
|
+
});
|
|
7701
|
+
} catch (err) {
|
|
7702
|
+
console.warn(`workflow: failed to fetch grants from "${resourcePath}"; advisory permission reads that depend on them are skipped — a rendered $can stays undefined (conditions referencing it fail closed) and the subject-write forecast omits this resource. The lake still enforces writes. Original error: ${invariants.errorMessage(err)}`);
|
|
7703
|
+
return;
|
|
7704
|
+
}
|
|
7705
|
+
}
|
|
7706
|
+
|
|
7707
|
+
function projectIdOf(client) {
|
|
7708
|
+
if (typeof client.config != "function") return;
|
|
7709
|
+
const projectId = client.config().projectId;
|
|
7710
|
+
return typeof projectId == "string" && projectId.length > 0 ? projectId : void 0;
|
|
7711
|
+
}
|
|
7712
|
+
|
|
7713
|
+
function cachedAttributes(args) {
|
|
7714
|
+
const projectId = projectIdOf(args.client);
|
|
7715
|
+
return projectId === void 0 ? Promise.resolve(void 0) : resolveOrganizationId({
|
|
7716
|
+
client: args.client,
|
|
7717
|
+
requestFn: args.requestFn,
|
|
7718
|
+
projectId: projectId
|
|
7719
|
+
}).then(orgId => {
|
|
7720
|
+
if (orgId !== void 0) return cachedByKey({
|
|
7721
|
+
store: attributesCache,
|
|
7722
|
+
client: args.client,
|
|
7723
|
+
key: orgId,
|
|
7724
|
+
evictOnRejection: !0,
|
|
7725
|
+
load: () => fetchAttributesCached({
|
|
7726
|
+
client: args.client,
|
|
7727
|
+
orgId: orgId
|
|
7728
|
+
})
|
|
7729
|
+
});
|
|
7730
|
+
});
|
|
7731
|
+
}
|
|
7732
|
+
|
|
7733
|
+
async function resolveOrganizationId(args) {
|
|
7734
|
+
const {client: client, requestFn: requestFn, projectId: projectId} = args;
|
|
7735
|
+
return cachedByKey({
|
|
7736
|
+
store: orgIdCache,
|
|
7737
|
+
client: client,
|
|
7738
|
+
key: projectId,
|
|
7739
|
+
evictOnRejection: !0,
|
|
7740
|
+
load: async () => {
|
|
7741
|
+
try {
|
|
7742
|
+
const project = await requestFn({
|
|
7743
|
+
uri: `/projects/${encodeURIComponent(projectId)}`,
|
|
7744
|
+
tag: REQUEST_TAG.accessResolveOrg
|
|
7745
|
+
});
|
|
7746
|
+
if (!isRecord(project)) return;
|
|
7747
|
+
const orgId = project.organizationId;
|
|
7748
|
+
return typeof orgId == "string" && orgId.length > 0 ? orgId : void 0;
|
|
7749
|
+
} catch (err) {
|
|
7750
|
+
const status = httpStatusOf(err);
|
|
7751
|
+
if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
|
|
7752
|
+
throw new Error(`workflow: failed to resolve organizationId for project "${projectId}"; advisory $attributes cannot be bound. Original error: ${invariants.errorMessage(err)}`, {
|
|
7753
|
+
cause: err
|
|
7754
|
+
});
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
});
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7760
|
+
const ATTRIBUTES_FETCH_LIMIT = 100, EXPECTED_ATTRIBUTES_ABSENCE = /* @__PURE__ */ new Set([ 401, 402, 403, 404 ]);
|
|
7761
|
+
|
|
7762
|
+
function httpStatusOf(err) {
|
|
7763
|
+
if (!isRecord(err)) return;
|
|
7764
|
+
const status = err.statusCode;
|
|
7765
|
+
return typeof status == "number" ? status : void 0;
|
|
7766
|
+
}
|
|
7767
|
+
|
|
7768
|
+
async function fetchAttributesCached(args) {
|
|
7769
|
+
const {client: client, orgId: orgId} = args, sibling = globalHostRequestOf(client);
|
|
7770
|
+
if ("reason" in sibling) {
|
|
7771
|
+
console.warn(`workflow: skipped org attributes fetch (${sibling.reason}); advisory $attributes stays undefined (conditions referencing it fail closed).`);
|
|
7772
|
+
return;
|
|
7773
|
+
}
|
|
7774
|
+
try {
|
|
7775
|
+
const response = await sibling.request({
|
|
7776
|
+
uri: `/organizations/${encodeURIComponent(orgId)}/users/me/attributes?limit=${ATTRIBUTES_FETCH_LIMIT}`,
|
|
7777
|
+
tag: REQUEST_TAG.accessAttributes
|
|
7778
|
+
}), envelope = isRecord(response) ? response : void 0;
|
|
7779
|
+
if (envelope?.hasMore === !0) {
|
|
7780
|
+
const page = Array.isArray(envelope.attributes) ? envelope.attributes : [];
|
|
7781
|
+
console.warn(`workflow: org attributes for organization "${orgId}" report hasMore=true (bound ${page.length} of the requested limit ${ATTRIBUTES_FETCH_LIMIT}); advisory $attributes may be incomplete — the engine fetches no further pages. Conditions that read missing keys fail closed.`);
|
|
7782
|
+
}
|
|
7783
|
+
const normalized = normalizeUserAttributes(response);
|
|
7784
|
+
return normalized === void 0 && console.warn(`workflow: org attributes response for organization "${orgId}" was unusable; advisory $attributes stays undefined (conditions referencing it fail closed).`),
|
|
7785
|
+
normalized;
|
|
7786
|
+
} catch (err) {
|
|
7787
|
+
const status = httpStatusOf(err);
|
|
7788
|
+
if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
|
|
7789
|
+
throw new Error(`workflow: failed to fetch org attributes for organization "${orgId}". Original error: ${invariants.errorMessage(err)}`, {
|
|
7790
|
+
cause: err
|
|
7791
|
+
});
|
|
7792
|
+
}
|
|
7793
|
+
}
|
|
7794
|
+
|
|
7795
|
+
function callerBoundVars(args) {
|
|
7796
|
+
const vars = {
|
|
7797
|
+
...args.can !== void 0 ? {
|
|
7798
|
+
can: args.can
|
|
7799
|
+
} : {},
|
|
7800
|
+
...args.attributes !== void 0 ? {
|
|
7801
|
+
attributes: args.attributes
|
|
7802
|
+
} : {}
|
|
7803
|
+
};
|
|
7804
|
+
return Object.keys(vars).length > 0 ? vars : void 0;
|
|
7805
|
+
}
|
|
7806
|
+
|
|
7807
|
+
async function callerBoundVarsForCall(args) {
|
|
7808
|
+
const can = await advisoryCanForCall({
|
|
7809
|
+
instance: args.instance,
|
|
7810
|
+
options: args.options
|
|
7811
|
+
}), attributes = args.options?.attributes !== void 0 ? args.options.attributes : await resolveUserAttributes(args.client);
|
|
7812
|
+
return callerBoundVars({
|
|
7813
|
+
...can !== void 0 ? {
|
|
7814
|
+
can: can
|
|
7815
|
+
} : {},
|
|
7816
|
+
...attributes !== void 0 ? {
|
|
7817
|
+
attributes: attributes
|
|
7818
|
+
} : {}
|
|
7819
|
+
});
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
function requirementDescriptor(requirement) {
|
|
7823
|
+
return {
|
|
7824
|
+
name: requirement.name,
|
|
7825
|
+
...requirement.title !== void 0 ? {
|
|
7826
|
+
title: requirement.title
|
|
7827
|
+
} : {},
|
|
7828
|
+
...requirement.description !== void 0 ? {
|
|
7829
|
+
description: requirement.description
|
|
7830
|
+
} : {}
|
|
7831
|
+
};
|
|
7832
|
+
}
|
|
7833
|
+
|
|
7834
|
+
function subjectDenialLabels(denied) {
|
|
7835
|
+
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
7836
|
+
}
|
|
7837
|
+
|
|
7838
|
+
class ActionDisabledError extends invariants.WorkflowError {
|
|
7839
|
+
reason;
|
|
7840
|
+
activity;
|
|
7841
|
+
action;
|
|
7842
|
+
constructor(args) {
|
|
7843
|
+
super("action-disabled", formatDisabledReason({
|
|
7844
|
+
activity: args.activity,
|
|
7845
|
+
action: args.action,
|
|
7846
|
+
reason: args.reason
|
|
7847
|
+
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
7848
|
+
this.action = args.action;
|
|
7849
|
+
}
|
|
7850
|
+
}
|
|
7851
|
+
|
|
7852
|
+
class StartNotAllowedError extends invariants.WorkflowError {
|
|
7853
|
+
definition;
|
|
7854
|
+
unmetRequirements;
|
|
7855
|
+
constructor(args) {
|
|
7856
|
+
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
7857
|
+
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
7858
|
+
}
|
|
7859
|
+
}
|
|
7860
|
+
|
|
7861
|
+
function actionRendering(action) {
|
|
7862
|
+
const kind = action.disabledReason?.kind;
|
|
7863
|
+
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
7864
|
+
}
|
|
7865
|
+
|
|
7866
|
+
const disabledReasonDetail = {
|
|
7867
|
+
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
7868
|
+
"cascade-fired": r => `the action is cascade-fired (when: ${JSON.stringify(r.when)}) — the engine fires it on truth; it cannot be invoked via fireAction`,
|
|
6979
7869
|
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
6980
7870
|
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
6981
7871
|
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
@@ -7049,7 +7939,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
|
|
|
7049
7939
|
}
|
|
7050
7940
|
});
|
|
7051
7941
|
if (action.filter !== void 0) {
|
|
7052
|
-
const
|
|
7942
|
+
const vars = await callerBoundVarsForCall({
|
|
7943
|
+
client: ctx.client,
|
|
7053
7944
|
instance: ctx.instance,
|
|
7054
7945
|
options: options
|
|
7055
7946
|
});
|
|
@@ -7061,10 +7952,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
|
|
|
7061
7952
|
...actor !== void 0 ? {
|
|
7062
7953
|
actor: actor
|
|
7063
7954
|
} : {},
|
|
7064
|
-
...
|
|
7065
|
-
vars:
|
|
7066
|
-
can: can
|
|
7067
|
-
}
|
|
7955
|
+
...vars !== void 0 ? {
|
|
7956
|
+
vars: vars
|
|
7068
7957
|
} : {}
|
|
7069
7958
|
}
|
|
7070
7959
|
})) throw new ActionDisabledError({
|
|
@@ -7408,7 +8297,7 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
|
|
|
7408
8297
|
}) : await buildEngineContext({
|
|
7409
8298
|
client: client,
|
|
7410
8299
|
instance: instance,
|
|
7411
|
-
definition:
|
|
8300
|
+
definition: parseDefinitionSnapshot(instance),
|
|
7412
8301
|
...contextOptions
|
|
7413
8302
|
});
|
|
7414
8303
|
if (isTerminal(ctx)) return {
|
|
@@ -7589,7 +8478,7 @@ async function loadInstancesById(client, ids) {
|
|
|
7589
8478
|
const children = await client.fetch("*[_id in $ids]", {
|
|
7590
8479
|
ids: ids
|
|
7591
8480
|
});
|
|
7592
|
-
return new Map(children.filter(child => child._type ===
|
|
8481
|
+
return new Map(children.filter(child => child._type === WORKFLOW_INSTANCE_TYPE).map(child => {
|
|
7593
8482
|
const instance = readInstanceDoc(child);
|
|
7594
8483
|
return [ instance._id, instance ];
|
|
7595
8484
|
}));
|
|
@@ -7649,10 +8538,10 @@ async function propagateToAncestors(args) {
|
|
|
7649
8538
|
async function loadPropagationPair({client: client, instanceId: instanceId, instance: instance}) {
|
|
7650
8539
|
const child = instance ?? await getInstanceDocument(client, instanceId);
|
|
7651
8540
|
if (!child) return;
|
|
7652
|
-
const parentGdr =
|
|
8541
|
+
const parentGdr = parentRef(child);
|
|
7653
8542
|
if (parentGdr === void 0) return;
|
|
7654
8543
|
const parentDoc = await client.getDocument(invariants.toBareId(parentGdr.id));
|
|
7655
|
-
if (!(!parentDoc || parentDoc._type !==
|
|
8544
|
+
if (!(!parentDoc || parentDoc._type !== WORKFLOW_INSTANCE_TYPE)) return {
|
|
7656
8545
|
child: child,
|
|
7657
8546
|
parent: readInstanceDoc(parentDoc)
|
|
7658
8547
|
};
|
|
@@ -7679,7 +8568,7 @@ async function buildCascadeStepContext(args, instance) {
|
|
|
7679
8568
|
clientForGdr: args.clientForGdr,
|
|
7680
8569
|
refSurface: args.refSurface,
|
|
7681
8570
|
instance: instance,
|
|
7682
|
-
definition:
|
|
8571
|
+
definition: parseDefinitionSnapshot(instance),
|
|
7683
8572
|
...args.clock ? {
|
|
7684
8573
|
clock: args.clock
|
|
7685
8574
|
} : {},
|
|
@@ -7730,7 +8619,7 @@ function stampSpawnBatch({mutation: mutation, parent: parent, children: children
|
|
|
7730
8619
|
function requireSpawnBatchChild({parent: parent, children: children, childId: childId}) {
|
|
7731
8620
|
const child = children.get(childId);
|
|
7732
8621
|
if (child === void 0) throw new Error(`Spawn batch child ${childId} disappeared`);
|
|
7733
|
-
const expectedParent =
|
|
8622
|
+
const expectedParent = parentRef(child);
|
|
7734
8623
|
if (expectedParent === void 0 || invariants.toBareId(expectedParent.id) !== parent._id) throw new Error(`Spawn batch child ${childId} does not belong to parent ${parent._id}`);
|
|
7735
8624
|
return child;
|
|
7736
8625
|
}
|
|
@@ -7753,7 +8642,7 @@ async function recordOrphanedPropagation({ctx: ctx, mutation: mutation, child: c
|
|
|
7753
8642
|
at: ctx.now,
|
|
7754
8643
|
instanceRef: {
|
|
7755
8644
|
id: childUri,
|
|
7756
|
-
type:
|
|
8645
|
+
type: WORKFLOW_INSTANCE_TYPE
|
|
7757
8646
|
},
|
|
7758
8647
|
detail: `Instance "${child._id}" names this instance as its parent but no subworkflow-registry row matches it, so its state cannot drive any gate here.`
|
|
7759
8648
|
}), await persist(ctx, mutation));
|
|
@@ -7761,7 +8650,7 @@ async function recordOrphanedPropagation({ctx: ctx, mutation: mutation, child: c
|
|
|
7761
8650
|
|
|
7762
8651
|
function startMutation(instance) {
|
|
7763
8652
|
return {
|
|
7764
|
-
minReaderModel:
|
|
8653
|
+
minReaderModel: minReaderModelOf(instance),
|
|
7765
8654
|
currentStage: instance.currentStage,
|
|
7766
8655
|
fields: (instance.fields ?? []).map(s => ({
|
|
7767
8656
|
...s
|
|
@@ -7828,7 +8717,7 @@ function instanceStateFields(src) {
|
|
|
7828
8717
|
} : {}
|
|
7829
8718
|
};
|
|
7830
8719
|
return {
|
|
7831
|
-
...
|
|
8720
|
+
...modelStampFor({
|
|
7832
8721
|
documentType: "instance",
|
|
7833
8722
|
document: state,
|
|
7834
8723
|
storedMinReaderModel: src.minReaderModel
|
|
@@ -8307,352 +9196,109 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
8307
9196
|
});
|
|
8308
9197
|
const pending = requirePendingEffect(ctx.instance, effectKey), reason = staleClaimReason({
|
|
8309
9198
|
pending: pending,
|
|
8310
|
-
claimToken: claimToken,
|
|
8311
|
-
now: ctx.now
|
|
8312
|
-
});
|
|
8313
|
-
if (reason !== void 0) throw new StaleEffectClaimError({
|
|
8314
|
-
instanceId: ctx.instance._id,
|
|
8315
|
-
effectKey: effectKey,
|
|
8316
|
-
reason: reason
|
|
8317
|
-
});
|
|
8318
|
-
const validatedOps = validateEffectOps(ops, pending.name);
|
|
8319
|
-
if (validatedOps.length === 0) throw new EffectOpsInvalidError({
|
|
8320
|
-
effect: pending.name,
|
|
8321
|
-
issues: [ "a mid-dispatch report must carry at least one field op — there is nothing to commit" ]
|
|
8322
|
-
});
|
|
8323
|
-
const mutation = startMutation(ctx.instance);
|
|
8324
|
-
return recordProcessedRequest({
|
|
8325
|
-
mutation: mutation,
|
|
8326
|
-
record: requestRecord,
|
|
8327
|
-
now: ctx.now
|
|
8328
|
-
}), renewClaimLease({
|
|
8329
|
-
mutation: mutation,
|
|
8330
|
-
effectKey: effectKey,
|
|
8331
|
-
now: ctx.now,
|
|
8332
|
-
leaseMs: leaseMs
|
|
8333
|
-
}), await runOps({
|
|
8334
|
-
ops: validatedOps,
|
|
8335
|
-
mutation: mutation,
|
|
8336
|
-
stage: ctx.instance.currentStage,
|
|
8337
|
-
origin: {
|
|
8338
|
-
effect: pending.name
|
|
8339
|
-
},
|
|
8340
|
-
params: pending.params,
|
|
8341
|
-
actor: ctx.actor,
|
|
8342
|
-
self: invariants.selfGdr(ctx.instance),
|
|
8343
|
-
now: ctx.now,
|
|
8344
|
-
snapshot: ctx.snapshot,
|
|
8345
|
-
refSurface: ctx.refSurface
|
|
8346
|
-
}), await persistThenMaybeRefresh({
|
|
8347
|
-
ctx: ctx,
|
|
8348
|
-
mutation: mutation,
|
|
8349
|
-
stageName: ctx.instance.currentStage,
|
|
8350
|
-
didChangeState: !0
|
|
8351
|
-
}), {
|
|
8352
|
-
effectKey: effectKey,
|
|
8353
|
-
effect: pending.name
|
|
8354
|
-
};
|
|
8355
|
-
}
|
|
8356
|
-
|
|
8357
|
-
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
8358
|
-
|
|
8359
|
-
function isResetActivityTarget(value) {
|
|
8360
|
-
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
8361
|
-
}
|
|
8362
|
-
|
|
8363
|
-
async function resetActivity(args) {
|
|
8364
|
-
const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
|
|
8365
|
-
client: client,
|
|
8366
|
-
instanceId: instanceId,
|
|
8367
|
-
options: options
|
|
8368
|
-
});
|
|
8369
|
-
return commitResetActivity({
|
|
8370
|
-
ctx: ctx,
|
|
8371
|
-
activity: activity,
|
|
8372
|
-
to: to,
|
|
8373
|
-
requestRecord: requestRecord,
|
|
8374
|
-
actor: options?.actor
|
|
8375
|
-
});
|
|
8376
|
-
}
|
|
8377
|
-
|
|
8378
|
-
async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
|
|
8379
|
-
if (assertRequestUnprocessed({
|
|
8380
|
-
instance: ctx.instance,
|
|
8381
|
-
record: requestRecord,
|
|
8382
|
-
now: ctx.now
|
|
8383
|
-
}), isTerminal(ctx)) return {
|
|
8384
|
-
fired: !1
|
|
8385
|
-
};
|
|
8386
|
-
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
8387
|
-
if (openStage2 === void 0 || entry === void 0) throw new invariants.ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
8388
|
-
const from = entry.status;
|
|
8389
|
-
if (from === to) return {
|
|
8390
|
-
fired: !1
|
|
8391
|
-
};
|
|
8392
|
-
if (!invariants.isTerminalActivityStatus(from)) throw new invariants.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.`);
|
|
8393
|
-
return recordProcessedRequest({
|
|
8394
|
-
mutation: mutation,
|
|
8395
|
-
record: requestRecord,
|
|
8396
|
-
now: ctx.now
|
|
8397
|
-
}), applyActivityStatusChange({
|
|
8398
|
-
entry: entry,
|
|
8399
|
-
history: mutation.history,
|
|
8400
|
-
stage: openStage2.name,
|
|
8401
|
-
to: to,
|
|
8402
|
-
at: ctx.now,
|
|
8403
|
-
...actor !== void 0 ? {
|
|
8404
|
-
actor: actor
|
|
8405
|
-
} : {}
|
|
8406
|
-
}), await persist(ctx, mutation), {
|
|
8407
|
-
fired: !0,
|
|
8408
|
-
stage: openStage2.name,
|
|
8409
|
-
activity: activity,
|
|
8410
|
-
from: from,
|
|
8411
|
-
to: to
|
|
8412
|
-
};
|
|
8413
|
-
}
|
|
8414
|
-
|
|
8415
|
-
const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap;
|
|
8416
|
-
|
|
8417
|
-
async function resolveAccess(taggedClient, args = {}) {
|
|
8418
|
-
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
8419
|
-
if (requestFn === void 0) throw new invariants.ContractViolationError("workflow: no actor available. The engine resolves the actor from the client's token via `client.request({ uri: '/users/me' })`. Supply a real `@sanity/client` configured with a token (the test bench serves these endpoints per registered token).");
|
|
8420
|
-
const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
|
|
8421
|
-
client: client,
|
|
8422
|
-
requestFn: requestFn,
|
|
8423
|
-
resourcePath: args.grantsFromPath
|
|
8424
|
-
}) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
|
|
8425
|
-
if (identity === void 0) throw new invariants.ContractViolationError("workflow: failed to resolve actor from `/users/me`. The client is configured but the endpoint returned no usable identity — check the token.");
|
|
8426
|
-
return {
|
|
8427
|
-
actor: identity.actor,
|
|
8428
|
-
...identity.localPrincipalId !== void 0 ? {
|
|
8429
|
-
localPrincipalId: identity.localPrincipalId
|
|
8430
|
-
} : {},
|
|
8431
|
-
...grants !== void 0 ? {
|
|
8432
|
-
grants: grants
|
|
8433
|
-
} : {}
|
|
8434
|
-
};
|
|
8435
|
-
}
|
|
8436
|
-
|
|
8437
|
-
function cachedActor(client, requestFn) {
|
|
8438
|
-
const cached = actorCache.get(client);
|
|
8439
|
-
if (cached !== void 0) return cached;
|
|
8440
|
-
const pending = fetchActor(client, requestFn).catch(err => {
|
|
8441
|
-
throw actorCache.get(client) === pending && actorCache.delete(client), err;
|
|
8442
|
-
});
|
|
8443
|
-
return actorCache.set(client, pending), pending;
|
|
8444
|
-
}
|
|
8445
|
-
|
|
8446
|
-
function grantsForClientPath(taggedClient, resourcePath) {
|
|
8447
|
-
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
8448
|
-
return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
|
|
8449
|
-
client: client,
|
|
8450
|
-
requestFn: requestFn,
|
|
8451
|
-
resourcePath: resourcePath
|
|
8452
|
-
});
|
|
8453
|
-
}
|
|
8454
|
-
|
|
8455
|
-
function lazyRequest(client) {
|
|
8456
|
-
return client.request === void 0 ? void 0 : opts => client.request(opts);
|
|
8457
|
-
}
|
|
8458
|
-
|
|
8459
|
-
function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
|
|
8460
|
-
let byPath = grantsCache.get(client);
|
|
8461
|
-
byPath === void 0 && (byPath = /* @__PURE__ */ new Map, grantsCache.set(client, byPath));
|
|
8462
|
-
let cached = byPath.get(resourcePath);
|
|
8463
|
-
return cached === void 0 && (cached = fetchGrantsCached(requestFn, resourcePath),
|
|
8464
|
-
byPath.set(resourcePath, cached)), cached;
|
|
8465
|
-
}
|
|
8466
|
-
|
|
8467
|
-
async function fetchActor(client, requestFn) {
|
|
8468
|
-
const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalHostId = usableId(globalUser.user), carriedId = invariants.firstCarriedGlobalId([ globalHostId, resourceId ]), sessionId = carriedId ?? globalHostId ?? resourceId;
|
|
8469
|
-
if (sessionId === void 0) return;
|
|
8470
|
-
const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
|
|
8471
|
-
client: client,
|
|
8472
|
-
sessionId: sessionId,
|
|
8473
|
-
resourceId: resourceId
|
|
8474
|
-
}) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
|
|
8475
|
-
refuseProjectScopedActor({
|
|
8476
|
-
id: id,
|
|
8477
|
-
globalUser: globalUser,
|
|
8478
|
-
globalHostId: globalHostId,
|
|
8479
|
-
bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
|
|
8480
|
-
});
|
|
8481
|
-
const roleNames = roleNamesFor(resourceUser, globalUser);
|
|
8482
|
-
return {
|
|
8483
|
-
actor: {
|
|
8484
|
-
kind: "person",
|
|
8485
|
-
id: id,
|
|
8486
|
-
...roleNames.length > 0 ? {
|
|
8487
|
-
roles: roleNames
|
|
8488
|
-
} : {}
|
|
8489
|
-
},
|
|
8490
|
-
...resourceId !== void 0 && resourceId !== id ? {
|
|
8491
|
-
localPrincipalId: resourceId
|
|
8492
|
-
} : {}
|
|
8493
|
-
};
|
|
8494
|
-
}
|
|
8495
|
-
|
|
8496
|
-
function roleNamesFor(resourceUser, globalUser) {
|
|
8497
|
-
return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
|
|
8498
|
-
}
|
|
8499
|
-
|
|
8500
|
-
const NO_BRIDGE = {
|
|
8501
|
-
status: "not-applicable"
|
|
8502
|
-
};
|
|
8503
|
-
|
|
8504
|
-
function globalRouteReason(globalUser, globalHostId) {
|
|
8505
|
-
return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
|
|
8506
|
-
}
|
|
8507
|
-
|
|
8508
|
-
async function bridgeProjectPrincipal(args) {
|
|
8509
|
-
const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
|
|
8510
|
-
return invariants.classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || invariants.classifyPrincipalId(resourceId).namespace !== "project" ? {
|
|
8511
|
-
status: "unavailable",
|
|
8512
|
-
reason: "no project-scoped principal from the resource host to address the directory with"
|
|
8513
|
-
} : directoryGlobalId({
|
|
8514
|
-
client: client,
|
|
8515
|
-
principalId: resourceId
|
|
8516
|
-
});
|
|
8517
|
-
}
|
|
8518
|
-
|
|
8519
|
-
async function directoryGlobalId(args) {
|
|
8520
|
-
const {client: client, principalId: principalId} = args, projectId = typeof client.config == "function" ? client.config().projectId : void 0;
|
|
8521
|
-
if (projectId === void 0) return {
|
|
8522
|
-
status: "unavailable",
|
|
8523
|
-
reason: "the client reports no projectId, so its user directory has no address"
|
|
8524
|
-
};
|
|
8525
|
-
const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
|
|
8526
|
-
if (lookup.status !== "resolved") return {
|
|
8527
|
-
status: "unavailable",
|
|
8528
|
-
reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
|
|
8529
|
-
...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
|
|
8530
|
-
cause: lookup.cause
|
|
8531
|
-
} : {}
|
|
8532
|
-
};
|
|
8533
|
-
const globalId = invariants.directoryBridgeId(lookup.user.sanityUserId);
|
|
8534
|
-
return globalId === void 0 ? {
|
|
8535
|
-
status: "unavailable",
|
|
8536
|
-
reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
|
|
8537
|
-
} : {
|
|
8538
|
-
status: "resolved",
|
|
8539
|
-
globalId: globalId
|
|
8540
|
-
};
|
|
8541
|
-
}
|
|
8542
|
-
|
|
8543
|
-
function refuseProjectScopedActor(args) {
|
|
8544
|
-
const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
|
|
8545
|
-
if (invariants.classifyPrincipalId(id).namespace !== "project") return;
|
|
8546
|
-
const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
|
|
8547
|
-
bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
|
|
8548
|
-
const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
|
|
8549
|
-
throw new Error(`workflow: the caller's identity resolves to the project-scoped principal "${id}" and its account-global id could not be resolved. ${routes.join(" ")} The engine speaks account-global user ids only and never acts as a project-scoped principal.`, cause === void 0 ? void 0 : {
|
|
8550
|
-
cause: cause
|
|
9199
|
+
claimToken: claimToken,
|
|
9200
|
+
now: ctx.now
|
|
9201
|
+
});
|
|
9202
|
+
if (reason !== void 0) throw new StaleEffectClaimError({
|
|
9203
|
+
instanceId: ctx.instance._id,
|
|
9204
|
+
effectKey: effectKey,
|
|
9205
|
+
reason: reason
|
|
9206
|
+
});
|
|
9207
|
+
const validatedOps = validateEffectOps(ops, pending.name);
|
|
9208
|
+
if (validatedOps.length === 0) throw new EffectOpsInvalidError({
|
|
9209
|
+
effect: pending.name,
|
|
9210
|
+
issues: [ "a mid-dispatch report must carry at least one field op — there is nothing to commit" ]
|
|
8551
9211
|
});
|
|
9212
|
+
const mutation = startMutation(ctx.instance);
|
|
9213
|
+
return recordProcessedRequest({
|
|
9214
|
+
mutation: mutation,
|
|
9215
|
+
record: requestRecord,
|
|
9216
|
+
now: ctx.now
|
|
9217
|
+
}), renewClaimLease({
|
|
9218
|
+
mutation: mutation,
|
|
9219
|
+
effectKey: effectKey,
|
|
9220
|
+
now: ctx.now,
|
|
9221
|
+
leaseMs: leaseMs
|
|
9222
|
+
}), await runOps({
|
|
9223
|
+
ops: validatedOps,
|
|
9224
|
+
mutation: mutation,
|
|
9225
|
+
stage: ctx.instance.currentStage,
|
|
9226
|
+
origin: {
|
|
9227
|
+
effect: pending.name
|
|
9228
|
+
},
|
|
9229
|
+
params: pending.params,
|
|
9230
|
+
actor: ctx.actor,
|
|
9231
|
+
self: invariants.selfGdr(ctx.instance),
|
|
9232
|
+
now: ctx.now,
|
|
9233
|
+
snapshot: ctx.snapshot,
|
|
9234
|
+
refSurface: ctx.refSurface
|
|
9235
|
+
}), await persistThenMaybeRefresh({
|
|
9236
|
+
ctx: ctx,
|
|
9237
|
+
mutation: mutation,
|
|
9238
|
+
stageName: ctx.instance.currentStage,
|
|
9239
|
+
didChangeState: !0
|
|
9240
|
+
}), {
|
|
9241
|
+
effectKey: effectKey,
|
|
9242
|
+
effect: pending.name
|
|
9243
|
+
};
|
|
8552
9244
|
}
|
|
8553
9245
|
|
|
8554
|
-
|
|
8555
|
-
if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
|
|
8556
|
-
}
|
|
9246
|
+
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
8557
9247
|
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
return await requestFn({
|
|
8561
|
-
uri: "/users/me",
|
|
8562
|
-
tag: REQUEST_TAG.accessResolveActor
|
|
8563
|
-
});
|
|
8564
|
-
} catch (err) {
|
|
8565
|
-
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.`, {
|
|
8566
|
-
cause: err
|
|
8567
|
-
});
|
|
8568
|
-
}
|
|
9248
|
+
function isResetActivityTarget(value) {
|
|
9249
|
+
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
8569
9250
|
}
|
|
8570
9251
|
|
|
8571
|
-
async function
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
}), globalRequest = lazyRequest(globalClient);
|
|
8585
|
-
} catch (err) {
|
|
8586
|
-
return {
|
|
8587
|
-
user: void 0,
|
|
8588
|
-
reason: `building the global-host sibling client failed: ${invariants.errorMessage(err)}`,
|
|
8589
|
-
cause: err
|
|
8590
|
-
};
|
|
8591
|
-
}
|
|
8592
|
-
if (globalRequest === void 0) return {
|
|
8593
|
-
user: void 0,
|
|
8594
|
-
reason: "the global-host sibling client cannot issue requests"
|
|
8595
|
-
};
|
|
8596
|
-
try {
|
|
8597
|
-
const user = await globalRequest({
|
|
8598
|
-
uri: "/users/me",
|
|
8599
|
-
tag: REQUEST_TAG.accessResolveActor
|
|
8600
|
-
}), id = usableId(user);
|
|
8601
|
-
return hostResolution.requireGlobalPrincipal && id !== void 0 && invariants.classifyPrincipalId(id).namespace === "project" ? {
|
|
8602
|
-
user: void 0,
|
|
8603
|
-
reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
|
|
8604
|
-
} : {
|
|
8605
|
-
user: user
|
|
8606
|
-
};
|
|
8607
|
-
} catch (err) {
|
|
8608
|
-
return {
|
|
8609
|
-
user: void 0,
|
|
8610
|
-
reason: `global-host /users/me failed: ${invariants.errorMessage(err)}`,
|
|
8611
|
-
cause: err
|
|
8612
|
-
};
|
|
8613
|
-
}
|
|
9252
|
+
async function resetActivity(args) {
|
|
9253
|
+
const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
|
|
9254
|
+
client: client,
|
|
9255
|
+
instanceId: instanceId,
|
|
9256
|
+
options: options
|
|
9257
|
+
});
|
|
9258
|
+
return commitResetActivity({
|
|
9259
|
+
ctx: ctx,
|
|
9260
|
+
activity: activity,
|
|
9261
|
+
to: to,
|
|
9262
|
+
requestRecord: requestRecord,
|
|
9263
|
+
actor: options?.actor
|
|
9264
|
+
});
|
|
8614
9265
|
}
|
|
8615
9266
|
|
|
8616
|
-
function
|
|
8617
|
-
if (
|
|
8618
|
-
|
|
9267
|
+
async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
|
|
9268
|
+
if (assertRequestUnprocessed({
|
|
9269
|
+
instance: ctx.instance,
|
|
9270
|
+
record: requestRecord,
|
|
9271
|
+
now: ctx.now
|
|
9272
|
+
}), isTerminal(ctx)) return {
|
|
9273
|
+
fired: !1
|
|
8619
9274
|
};
|
|
8620
|
-
const
|
|
8621
|
-
if (
|
|
8622
|
-
|
|
9275
|
+
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
9276
|
+
if (openStage2 === void 0 || entry === void 0) throw new invariants.ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
9277
|
+
const from = entry.status;
|
|
9278
|
+
if (from === to) return {
|
|
9279
|
+
fired: !1
|
|
8623
9280
|
};
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
9281
|
+
if (!invariants.isTerminalActivityStatus(from)) throw new invariants.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.`);
|
|
9282
|
+
return recordProcessedRequest({
|
|
9283
|
+
mutation: mutation,
|
|
9284
|
+
record: requestRecord,
|
|
9285
|
+
now: ctx.now
|
|
9286
|
+
}), applyActivityStatusChange({
|
|
9287
|
+
entry: entry,
|
|
9288
|
+
history: mutation.history,
|
|
9289
|
+
stage: openStage2.name,
|
|
9290
|
+
to: to,
|
|
9291
|
+
at: ctx.now,
|
|
9292
|
+
...actor !== void 0 ? {
|
|
9293
|
+
actor: actor
|
|
9294
|
+
} : {}
|
|
9295
|
+
}), await persist(ctx, mutation), {
|
|
9296
|
+
fired: !0,
|
|
9297
|
+
stage: openStage2.name,
|
|
9298
|
+
activity: activity,
|
|
9299
|
+
from: from,
|
|
9300
|
+
to: to
|
|
8634
9301
|
};
|
|
8635
|
-
const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
|
|
8636
|
-
return match === null ? {
|
|
8637
|
-
requireGlobalPrincipal: !0
|
|
8638
|
-
} : (parsed.hostname = `api.sanity.${match[1]}`, {
|
|
8639
|
-
apiHost: parsed.origin,
|
|
8640
|
-
requireGlobalPrincipal: !0
|
|
8641
|
-
});
|
|
8642
|
-
}
|
|
8643
|
-
|
|
8644
|
-
async function fetchGrantsCached(requestFn, resourcePath) {
|
|
8645
|
-
try {
|
|
8646
|
-
return await fetchGrants({
|
|
8647
|
-
client: {
|
|
8648
|
-
request: requestFn
|
|
8649
|
-
},
|
|
8650
|
-
resourcePath: resourcePath
|
|
8651
|
-
});
|
|
8652
|
-
} catch (err) {
|
|
8653
|
-
console.warn(`workflow: failed to fetch grants from "${resourcePath}"; advisory permission reads that depend on them are skipped — a rendered $can stays undefined (conditions referencing it fail closed) and the subject-write forecast omits this resource. The lake still enforces writes. Original error: ${invariants.errorMessage(err)}`);
|
|
8654
|
-
return;
|
|
8655
|
-
}
|
|
8656
9302
|
}
|
|
8657
9303
|
|
|
8658
9304
|
const REPLAY_SURFACE = {
|
|
@@ -8704,7 +9350,7 @@ async function whatIfFireAction(args) {
|
|
|
8704
9350
|
|
|
8705
9351
|
function replayable(args) {
|
|
8706
9352
|
const {instance: instance, stage: stage, action: action} = args;
|
|
8707
|
-
if (
|
|
9353
|
+
if (terminalState(instance) !== "in-flight" || (action.params ?? []).length > 0 || action.spawn !== void 0) return !1;
|
|
8708
9354
|
const primed = new Set((findOpenStageEntry(instance)?.activities ?? []).map(e => e.name));
|
|
8709
9355
|
return (stage.activities ?? []).every(declared => primed.has(declared.name)) ? !(stage.activities ?? []).flatMap(declared => declared.actions ?? []).some(sibling => invariants.isCascadeFired(sibling) && sibling.spawn !== void 0) : !1;
|
|
8710
9356
|
}
|
|
@@ -8836,7 +9482,7 @@ async function resourceActorId(client) {
|
|
|
8836
9482
|
async function evaluateInstance(args) {
|
|
8837
9483
|
const {client: client, tag: tag, workflowResource: workflowResource, instanceId: instanceId, resourceClients: resourceClients} = args, now = (args.clock ?? wallClock)();
|
|
8838
9484
|
invariants.validateTag(tag);
|
|
8839
|
-
const [access, instance] = await Promise.all([ resolveAccess(client, {
|
|
9485
|
+
const [access, instance, attributes] = await Promise.all([ resolveAccess(client, {
|
|
8840
9486
|
...args.grantsFromPath !== void 0 ? {
|
|
8841
9487
|
grantsFromPath: args.grantsFromPath
|
|
8842
9488
|
} : {}
|
|
@@ -8844,7 +9490,7 @@ async function evaluateInstance(args) {
|
|
|
8844
9490
|
client: client,
|
|
8845
9491
|
instanceId: instanceId,
|
|
8846
9492
|
tag: tag
|
|
8847
|
-
}) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition =
|
|
9493
|
+
}), resolveUserAttributes(client) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
|
|
8848
9494
|
client: client,
|
|
8849
9495
|
workflowResource: workflowResource,
|
|
8850
9496
|
resourceClients: resourceClients
|
|
@@ -8869,6 +9515,9 @@ async function evaluateInstance(args) {
|
|
|
8869
9515
|
} : {},
|
|
8870
9516
|
...grants !== void 0 ? {
|
|
8871
9517
|
grants: grants
|
|
9518
|
+
} : {},
|
|
9519
|
+
...attributes !== void 0 ? {
|
|
9520
|
+
attributes: attributes
|
|
8872
9521
|
} : {}
|
|
8873
9522
|
});
|
|
8874
9523
|
}
|
|
@@ -8883,6 +9532,33 @@ function memoizedByName(render) {
|
|
|
8883
9532
|
};
|
|
8884
9533
|
}
|
|
8885
9534
|
|
|
9535
|
+
async function callerBoundProjectionScopes(args) {
|
|
9536
|
+
const can = await advisoryCan({
|
|
9537
|
+
instance: args.instance,
|
|
9538
|
+
identity: args.identity,
|
|
9539
|
+
grants: args.grants
|
|
9540
|
+
}), vars = callerBoundVars({
|
|
9541
|
+
...can !== void 0 ? {
|
|
9542
|
+
can: can
|
|
9543
|
+
} : {},
|
|
9544
|
+
...args.attributes !== void 0 ? {
|
|
9545
|
+
attributes: args.attributes
|
|
9546
|
+
} : {}
|
|
9547
|
+
}), opts = {
|
|
9548
|
+
actor: args.actor,
|
|
9549
|
+
...vars !== void 0 ? {
|
|
9550
|
+
vars: vars
|
|
9551
|
+
} : {}
|
|
9552
|
+
};
|
|
9553
|
+
return {
|
|
9554
|
+
scope: await renderConditionScope(args.scopeSource, opts),
|
|
9555
|
+
scopeForActivity: memoizedByName(activityName => renderConditionScope(args.scopeSource, {
|
|
9556
|
+
activityName: activityName,
|
|
9557
|
+
...opts
|
|
9558
|
+
}))
|
|
9559
|
+
};
|
|
9560
|
+
}
|
|
9561
|
+
|
|
8886
9562
|
function currentStageOf(instance, definition) {
|
|
8887
9563
|
try {
|
|
8888
9564
|
return findStage(definition, instance.currentStage);
|
|
@@ -8908,7 +9584,7 @@ async function explainSite(args) {
|
|
|
8908
9584
|
}
|
|
8909
9585
|
|
|
8910
9586
|
async function evaluateFromSnapshot(args) {
|
|
8911
|
-
const {instance: instance, definition: definition, actor: actor, grants: grants, snapshot: snapshot} = args, now = args.now ?? wallClock(), stage = currentStageOf(instance, definition), autonomy = autonomyOf(definition), stageAutonomy2 = stageAutonomyOf(autonomy, stage.name), fireConsequence = (activity, action) => whatIfFireAction({
|
|
9587
|
+
const {instance: instance, definition: definition, actor: actor, grants: grants, attributes: attributes, snapshot: snapshot} = args, now = args.now ?? wallClock(), stage = currentStageOf(instance, definition), autonomy = autonomyOf(definition), stageAutonomy2 = stageAutonomyOf(autonomy, stage.name), fireConsequence = (activity, action) => whatIfFireAction({
|
|
8912
9588
|
instance: instance,
|
|
8913
9589
|
definition: definition,
|
|
8914
9590
|
snapshot: snapshot,
|
|
@@ -8925,22 +9601,14 @@ async function evaluateFromSnapshot(args) {
|
|
|
8925
9601
|
}, anchorIdentity = invariants.lakePrincipalId({
|
|
8926
9602
|
actor: actor,
|
|
8927
9603
|
localPrincipalId: args.localPrincipalId
|
|
8928
|
-
}),
|
|
8929
|
-
|
|
8930
|
-
identity: anchorIdentity,
|
|
8931
|
-
grants: grants
|
|
8932
|
-
}), scope = await renderConditionScope(scopeSource, {
|
|
8933
|
-
actor: actor,
|
|
8934
|
-
vars: {
|
|
8935
|
-
can: can
|
|
8936
|
-
}
|
|
8937
|
-
}), scopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
|
|
8938
|
-
activityName: activityName,
|
|
9604
|
+
}), {scope: scope, scopeForActivity: scopeForActivity} = await callerBoundProjectionScopes({
|
|
9605
|
+
scopeSource: scopeSource,
|
|
8939
9606
|
actor: actor,
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
9607
|
+
instance: instance,
|
|
9608
|
+
grants: grants,
|
|
9609
|
+
attributes: attributes,
|
|
9610
|
+
identity: anchorIdentity
|
|
9611
|
+
}), cascadeScopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
|
|
8944
9612
|
activityName: activityName
|
|
8945
9613
|
})), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
8946
9614
|
instance: instance,
|
|
@@ -8989,6 +9657,7 @@ async function evaluateFromSnapshot(args) {
|
|
|
8989
9657
|
}
|
|
8990
9658
|
const currentStage = {
|
|
8991
9659
|
stage: stage,
|
|
9660
|
+
...semanticsOf(stage),
|
|
8992
9661
|
activities: activityEvaluations,
|
|
8993
9662
|
transitions: transitionEvaluations,
|
|
8994
9663
|
autonomy: stageAutonomy2
|
|
@@ -9005,6 +9674,7 @@ async function evaluateFromSnapshot(args) {
|
|
|
9005
9674
|
return {
|
|
9006
9675
|
instance: instance,
|
|
9007
9676
|
definition: definition,
|
|
9677
|
+
...semanticsOf(definition),
|
|
9008
9678
|
actor: actor,
|
|
9009
9679
|
currentStage: currentStage,
|
|
9010
9680
|
pendingOnYou: pendingOnYou,
|
|
@@ -9160,6 +9830,7 @@ async function evaluateActivity(args) {
|
|
|
9160
9830
|
}));
|
|
9161
9831
|
return {
|
|
9162
9832
|
activity: activity,
|
|
9833
|
+
...semanticsOf(activity),
|
|
9163
9834
|
status: status,
|
|
9164
9835
|
kind: invariants.deriveActivityKind(activity),
|
|
9165
9836
|
classification: invariants.deriveExecutorClassification(activity),
|
|
@@ -9330,9 +10001,13 @@ function fireableActionVerdict({args: args, insights: insights}) {
|
|
|
9330
10001
|
function actionEvaluationIdentity(action) {
|
|
9331
10002
|
return {
|
|
9332
10003
|
action: action,
|
|
9333
|
-
...action
|
|
9334
|
-
|
|
9335
|
-
|
|
10004
|
+
...semanticsOf(action)
|
|
10005
|
+
};
|
|
10006
|
+
}
|
|
10007
|
+
|
|
10008
|
+
function semanticsOf(node) {
|
|
10009
|
+
return node.semantics === void 0 ? {} : {
|
|
10010
|
+
semantics: node.semantics
|
|
9336
10011
|
};
|
|
9337
10012
|
}
|
|
9338
10013
|
|
|
@@ -9404,7 +10079,7 @@ function idsArm(filter, params) {
|
|
|
9404
10079
|
function instancesQuery(args) {
|
|
9405
10080
|
const {tag: tag, filter: filter = {}} = args;
|
|
9406
10081
|
if (invariants.validateTag(tag), filter.limit !== void 0 && (!Number.isInteger(filter.limit) || filter.limit <= 0)) throw new invariants.ContractViolationError(`instancesQuery: limit must be a positive integer; got ${JSON.stringify(filter.limit)}`);
|
|
9407
|
-
const conditions = [ `_type == "${
|
|
10082
|
+
const conditions = [ `_type == "${WORKFLOW_INSTANCE_TYPE}"`, invariants.tagScopeFilter() ], params = {
|
|
9408
10083
|
tag: tag
|
|
9409
10084
|
};
|
|
9410
10085
|
filter.includeCompleted !== !0 && conditions.push(inFlightFilter()), filter.definition !== void 0 && (conditions.push("definition == $definition"),
|
|
@@ -9613,7 +10288,7 @@ function planDefinitionDeploy({def: def, latest: latest, target: target}) {
|
|
|
9613
10288
|
tag: target.tag,
|
|
9614
10289
|
version: version,
|
|
9615
10290
|
contentHash: contentHash,
|
|
9616
|
-
...
|
|
10291
|
+
...modelStampFor({
|
|
9617
10292
|
documentType: "definition",
|
|
9618
10293
|
document: expanded
|
|
9619
10294
|
})
|
|
@@ -9690,7 +10365,7 @@ async function loadDefinition({client: client, definition: definition, version:
|
|
|
9690
10365
|
definition: definition,
|
|
9691
10366
|
version: version
|
|
9692
10367
|
});
|
|
9693
|
-
return
|
|
10368
|
+
return assertReadableModel(doc);
|
|
9694
10369
|
}
|
|
9695
10370
|
const latest = await loadLatestDeployed({
|
|
9696
10371
|
client: client,
|
|
@@ -9708,14 +10383,14 @@ async function loadLatestDeployed({client: client, definition: definition, tag:
|
|
|
9708
10383
|
definition: definition,
|
|
9709
10384
|
tag: tag
|
|
9710
10385
|
});
|
|
9711
|
-
return doc ?
|
|
10386
|
+
return doc ? assertReadableModel(doc) : void 0;
|
|
9712
10387
|
}
|
|
9713
10388
|
|
|
9714
10389
|
async function loadDefinitionVersions({client: client, definition: definition, tag: tag}) {
|
|
9715
10390
|
return (await client.fetch(`*[_type == "${invariants.WORKFLOW_DEFINITION_TYPE}" && name == $definition && ${invariants.tagScopeFilter()}] | order(version desc)`, {
|
|
9716
10391
|
definition: definition,
|
|
9717
10392
|
tag: tag
|
|
9718
|
-
})).map(
|
|
10393
|
+
})).map(assertReadableModel);
|
|
9719
10394
|
}
|
|
9720
10395
|
|
|
9721
10396
|
async function loadDefinitionVersionsOrThrow({client: client, definition: definition, tag: tag}) {
|
|
@@ -9811,7 +10486,8 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
|
|
|
9811
10486
|
}
|
|
9812
10487
|
|
|
9813
10488
|
async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
|
|
9814
|
-
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site),
|
|
10489
|
+
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), vars = await callerBoundVarsForCall({
|
|
10490
|
+
client: ctx.client,
|
|
9815
10491
|
instance: ctx.instance,
|
|
9816
10492
|
options: options
|
|
9817
10493
|
}), predicateSatisfied = window.open && site.effective !== !0 && site.effective !== void 0 ? await ctxEvaluateCondition({
|
|
@@ -9824,10 +10500,8 @@ async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
|
|
|
9824
10500
|
...actor !== void 0 ? {
|
|
9825
10501
|
actor: actor
|
|
9826
10502
|
} : {},
|
|
9827
|
-
...
|
|
9828
|
-
vars:
|
|
9829
|
-
can: can
|
|
9830
|
-
}
|
|
10503
|
+
...vars !== void 0 ? {
|
|
10504
|
+
vars: vars
|
|
9831
10505
|
} : {}
|
|
9832
10506
|
}
|
|
9833
10507
|
}) : site.effective === !0, reason = editDisabledReason({
|
|
@@ -10103,8 +10777,8 @@ async function resumeStart(args) {
|
|
|
10103
10777
|
version: args.version
|
|
10104
10778
|
});
|
|
10105
10779
|
if (mismatch !== void 0) throw new invariants.ContractViolationError(`startInstance: instanceId "${existing._id}" already exists and ${mismatch}. A supplied instanceId is start's idempotency key — reuse one only to retry the same start.`);
|
|
10106
|
-
if (existing.stages.length === 0 &&
|
|
10107
|
-
const completesStart =
|
|
10780
|
+
if (existing.stages.length === 0 && terminalState(existing) !== "in-flight") throw new invariants.ContractViolationError(`startInstance: instanceId "${existing._id}" belongs to a start that was discarded (aborted before it finished starting) — mint a new id to start again.`);
|
|
10781
|
+
const completesStart = isUnprimed(existing), emitStarted = () => resolveTelemetry(args.telemetry).log(WorkflowInstanceStarted, instanceStartedDataFor({
|
|
10108
10782
|
instance: existing,
|
|
10109
10783
|
initialFieldCount: args.initialFieldCount,
|
|
10110
10784
|
viaSpawn: !1
|
|
@@ -10317,6 +10991,9 @@ function buildEngineCallOptions(args) {
|
|
|
10317
10991
|
...args.grants !== void 0 ? {
|
|
10318
10992
|
grants: args.grants
|
|
10319
10993
|
} : {},
|
|
10994
|
+
...args.attributes !== void 0 ? {
|
|
10995
|
+
attributes: args.attributes
|
|
10996
|
+
} : {},
|
|
10320
10997
|
...args.clock !== void 0 ? {
|
|
10321
10998
|
clock: args.clock
|
|
10322
10999
|
} : {},
|
|
@@ -10411,7 +11088,7 @@ async function deleteDefinition(args) {
|
|
|
10411
11088
|
async function assertNoSpawnReferrers({client: client, tag: tag, definition: definition, targets: targets, lastVersionGoes: lastVersionGoes}) {
|
|
10412
11089
|
const deployed = (await client.fetch(`*[_type == "${invariants.WORKFLOW_DEFINITION_TYPE}" && ${invariants.tagScopeFilter()}]`, {
|
|
10413
11090
|
tag: tag
|
|
10414
|
-
})).map(
|
|
11091
|
+
})).map(assertReadableModel), targetIds = new Set(targets.map(d => d._id)), targetVersions = new Set(targets.map(d => d.version)), referrers = deployed.filter(d => !targetIds.has(d._id)).filter(d => refsOf(d).some(ref => ref.name === definition && (typeof ref.version == "number" ? targetVersions.has(ref.version) : lastVersionGoes)));
|
|
10415
11092
|
if (referrers.length > 0) throw new invariants.DefinitionInUseError({
|
|
10416
11093
|
definition: definition,
|
|
10417
11094
|
blockedBy: {
|
|
@@ -10426,7 +11103,7 @@ async function assertNoSpawnReferrers({client: client, tag: tag, definition: def
|
|
|
10426
11103
|
|
|
10427
11104
|
async function nonTerminalInstanceIds({client: client, tag: tag, definition: definition, version: version}) {
|
|
10428
11105
|
const versionFilter = version === void 0 ? "" : " && pinnedVersion == $version";
|
|
10429
|
-
return (await client.fetch(`*[_type == "${
|
|
11106
|
+
return (await client.fetch(`*[_type == "${WORKFLOW_INSTANCE_TYPE}" && definition == $definition && ${invariants.tagScopeFilter()} && ${inFlightFilter()}${versionFilter}] | order(_id asc){_id}`, {
|
|
10430
11107
|
definition: definition,
|
|
10431
11108
|
tag: tag,
|
|
10432
11109
|
...version !== void 0 ? {
|
|
@@ -10471,12 +11148,12 @@ async function fetchStartSlice(args) {
|
|
|
10471
11148
|
includeCompleted: !0
|
|
10472
11149
|
}
|
|
10473
11150
|
});
|
|
10474
|
-
return (await client.fetch(query, params)).map(
|
|
11151
|
+
return (await client.fetch(query, params)).map(assertReadableModel).map(projectStartSliceRow);
|
|
10475
11152
|
}
|
|
10476
11153
|
|
|
10477
11154
|
const workflow = {
|
|
10478
11155
|
deployDefinitions: async rawArgs => {
|
|
10479
|
-
|
|
11156
|
+
assertReaderModelAcknowledgement(rawArgs.expectedMinReaderModel);
|
|
10480
11157
|
const args = taggedScope(rawArgs, REQUEST_TAG.deploy), {client: client, tag: tag, resourceAliases: resourceAliases} = args;
|
|
10481
11158
|
invariants.validateTag(tag);
|
|
10482
11159
|
const definitions = args.definitions.map(def => parseDefinitionInput(def, "workflow.deployDefinitions"));
|
|
@@ -11102,7 +11779,7 @@ const workflow = {
|
|
|
11102
11779
|
instance: instance
|
|
11103
11780
|
}), reserved = await renderConditionScope({
|
|
11104
11781
|
instance: instance,
|
|
11105
|
-
definition:
|
|
11782
|
+
definition: parseDefinitionSnapshot(instance),
|
|
11106
11783
|
snapshot: snapshot,
|
|
11107
11784
|
now: clock()
|
|
11108
11785
|
}), tree = groqJs.parse(groq, {
|
|
@@ -11181,7 +11858,7 @@ const workflow = {
|
|
|
11181
11858
|
invariants.validateTag(tag);
|
|
11182
11859
|
const clock = args.clock ?? wallClock, deployed = (await client.fetch(latestDefinitionsGroq(), {
|
|
11183
11860
|
tag: tag
|
|
11184
|
-
})).map(
|
|
11861
|
+
})).map(assertReadableModel);
|
|
11185
11862
|
let slice;
|
|
11186
11863
|
return applicableDefinitions({
|
|
11187
11864
|
definitions: deployed,
|
|
@@ -11563,7 +12240,7 @@ async function verifyDeployedDefinitionsInternal(args) {
|
|
|
11563
12240
|
invariants.validateTag(tag);
|
|
11564
12241
|
const log = logger("verifyDeployedDefinitions"), definitions = (await client.fetch(definitionsListGroq("asc"), {
|
|
11565
12242
|
tag: tag
|
|
11566
|
-
})).map(
|
|
12243
|
+
})).map(assertReadableModel), seen = [], missingByName = /* @__PURE__ */ new Map;
|
|
11567
12244
|
for (const def of definitions) seen.push({
|
|
11568
12245
|
name: def.name,
|
|
11569
12246
|
version: def.version,
|
|
@@ -12008,7 +12685,7 @@ function createInstanceSession(args) {
|
|
|
12008
12685
|
}, uri = invariants.gdrFromResource(owned.resource, owned.doc._id);
|
|
12009
12686
|
if (uri === selfUri()) {
|
|
12010
12687
|
const rawStamp = owned.doc._updatedAt;
|
|
12011
|
-
!invariants.isParseableInstant(rawStamp) || owned.doc._type !==
|
|
12688
|
+
!invariants.isParseableInstant(rawStamp) || owned.doc._type !== WORKFLOW_INSTANCE_TYPE ? asHeldInstance(owned.doc) : Date.parse(rawStamp) > Date.parse(instance._updatedAt) && (instance = asHeldInstance(owned.doc));
|
|
12012
12689
|
return;
|
|
12013
12690
|
}
|
|
12014
12691
|
target.set(uri, owned);
|
|
@@ -12031,7 +12708,7 @@ function createInstanceSession(args) {
|
|
|
12031
12708
|
let parsedDefinition;
|
|
12032
12709
|
const definitionOf = () => (parsedDefinition?.source !== instance && (parsedDefinition = {
|
|
12033
12710
|
source: instance,
|
|
12034
|
-
definition:
|
|
12711
|
+
definition: parseDefinitionSnapshot(instance)
|
|
12035
12712
|
}), parsedDefinition.definition), siteKey = site => JSON.stringify([ site.scope, site.activity ?? null, site.name ]), stagePreview = ({target: target, mode: mode, value: value}) => {
|
|
12036
12713
|
const site = previewSiteOf({
|
|
12037
12714
|
instance: instance,
|
|
@@ -12075,7 +12752,7 @@ function createInstanceSession(args) {
|
|
|
12075
12752
|
refSurface: evalScope.refSurface
|
|
12076
12753
|
});
|
|
12077
12754
|
}, evaluateWith = async ({held: held, guards: guards, self: self}) => {
|
|
12078
|
-
const {actor: actor, localPrincipalId: localPrincipalId, grants: grants} = await access(), resourceGrants = await subjectResourceGrants({
|
|
12755
|
+
const [{actor: actor, localPrincipalId: localPrincipalId, grants: grants}, attributes] = await Promise.all([ access(), resolveUserAttributes(client) ]), resourceGrants = await subjectResourceGrants({
|
|
12079
12756
|
clientForGdr: evalScope.clientForGdr,
|
|
12080
12757
|
instance: instance
|
|
12081
12758
|
}), normalizedSelf = await normalizeInstanceIdentities({
|
|
@@ -12097,6 +12774,9 @@ function createInstanceSession(args) {
|
|
|
12097
12774
|
} : {},
|
|
12098
12775
|
...grants !== void 0 ? {
|
|
12099
12776
|
grants: grants
|
|
12777
|
+
} : {},
|
|
12778
|
+
...attributes !== void 0 ? {
|
|
12779
|
+
attributes: attributes
|
|
12100
12780
|
} : {}
|
|
12101
12781
|
});
|
|
12102
12782
|
}, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope}) => {
|
|
@@ -12670,7 +13350,7 @@ function attributeMember({member: member, group: group, chain: chain}) {
|
|
|
12670
13350
|
}
|
|
12671
13351
|
|
|
12672
13352
|
function diffEntry({def: rawDef, latestRaw: latestRaw, target: target}) {
|
|
12673
|
-
|
|
13353
|
+
assertReaderModelAcknowledgement(target.expectedMinReaderModel);
|
|
12674
13354
|
const def = parseDefinitionInput(rawDef, "diffEntry"), plan = planDefinitionDeploy({
|
|
12675
13355
|
def: def,
|
|
12676
13356
|
latest: asLatest(latestRaw),
|
|
@@ -12702,7 +13382,7 @@ function asLatest(raw) {
|
|
|
12702
13382
|
}
|
|
12703
13383
|
|
|
12704
13384
|
async function computeDiffEntries({client: client, defs: defs, target: target}) {
|
|
12705
|
-
|
|
13385
|
+
assertReaderModelAcknowledgement(target.expectedMinReaderModel);
|
|
12706
13386
|
const entries = [];
|
|
12707
13387
|
for (const rawDef of defs) {
|
|
12708
13388
|
const def = parseDefinitionInput(rawDef, "computeDiffEntries"), latest = await loadLatestDeployed({
|
|
@@ -12792,7 +13472,7 @@ const HISTORY_DISPLAY = {
|
|
|
12792
13472
|
},
|
|
12793
13473
|
opApplied: {
|
|
12794
13474
|
title: "Op applied",
|
|
12795
|
-
description: "An
|
|
13475
|
+
description: "An action, direct edit, or effect completion executed an operation and recorded its audit payload."
|
|
12796
13476
|
},
|
|
12797
13477
|
fieldQueryDiscarded: {
|
|
12798
13478
|
title: "Query result discarded",
|
|
@@ -12897,6 +13577,10 @@ const HISTORY_DISPLAY = {
|
|
|
12897
13577
|
title: "Set field entry",
|
|
12898
13578
|
description: "Overwrite a field entry's value with a resolved value expression."
|
|
12899
13579
|
},
|
|
13580
|
+
"field.setIfMissing": {
|
|
13581
|
+
title: "Set field entry if missing",
|
|
13582
|
+
description: "Set a nullable field entry's value only when it is currently null or undefined; array, assignees, and doc.refs entries are always arrays and are not supported."
|
|
13583
|
+
},
|
|
12900
13584
|
"field.unset": {
|
|
12901
13585
|
title: "Unset field entry",
|
|
12902
13586
|
description: "Reset a field entry to its default (null for scalars, [] for array kinds)."
|
|
@@ -12905,6 +13589,14 @@ const HISTORY_DISPLAY = {
|
|
|
12905
13589
|
title: "Append to field entry",
|
|
12906
13590
|
description: "Push a resolved item onto an array-kind entry (array, assignees, doc.refs)."
|
|
12907
13591
|
},
|
|
13592
|
+
"field.inc": {
|
|
13593
|
+
title: "Increment field entry",
|
|
13594
|
+
description: "Add a resolved numeric delta, defaulting to 1, to a number entry that already holds a finite number."
|
|
13595
|
+
},
|
|
13596
|
+
"field.dec": {
|
|
13597
|
+
title: "Decrement field entry",
|
|
13598
|
+
description: "Subtract a resolved numeric delta, defaulting to 1, from a number entry that already holds a finite number."
|
|
13599
|
+
},
|
|
12908
13600
|
"field.updateWhere": {
|
|
12909
13601
|
title: "Update matching rows",
|
|
12910
13602
|
description: "Merge declared sub-fields into rows of an `array` entry that match the `where` condition (`array` only — `doc.refs`/`assignees` rows are engine-shaped)."
|
|
@@ -12951,7 +13643,7 @@ const HISTORY_DISPLAY = {
|
|
|
12951
13643
|
title: "Workflow definition",
|
|
12952
13644
|
description: "An immutable workflow blueprint, addressed by `name` + `version`."
|
|
12953
13645
|
},
|
|
12954
|
-
[
|
|
13646
|
+
[WORKFLOW_INSTANCE_TYPE]: {
|
|
12955
13647
|
title: "Workflow instance",
|
|
12956
13648
|
description: "A running (or finished) workflow against its declared fields."
|
|
12957
13649
|
}
|
|
@@ -13030,11 +13722,7 @@ exports.CONDITION_VARS = invariants.CONDITION_VARS;
|
|
|
13030
13722
|
|
|
13031
13723
|
exports.ContractViolationError = invariants.ContractViolationError;
|
|
13032
13724
|
|
|
13033
|
-
exports.
|
|
13034
|
-
|
|
13035
|
-
exports.DATA_MODEL_MIN_READER = invariants.DATA_MODEL_MIN_READER;
|
|
13036
|
-
|
|
13037
|
-
exports.DATA_MODEL_VERSION = invariants.DATA_MODEL_VERSION;
|
|
13725
|
+
exports.DECISION_SEMANTICS = invariants.DECISION_SEMANTICS;
|
|
13038
13726
|
|
|
13039
13727
|
exports.DEFAULT_TRANSITION_WHEN = invariants.DEFAULT_TRANSITION_WHEN;
|
|
13040
13728
|
|
|
@@ -13058,15 +13746,11 @@ exports.GUARD_PREDICATE_VARS = invariants.GUARD_PREDICATE_VARS;
|
|
|
13058
13746
|
|
|
13059
13747
|
exports.InstanceNotFoundError = invariants.InstanceNotFoundError;
|
|
13060
13748
|
|
|
13061
|
-
exports.ModelVersionAheadError = invariants.ModelVersionAheadError;
|
|
13062
|
-
|
|
13063
13749
|
exports.PersistedDocShapeError = invariants.PersistedDocShapeError;
|
|
13064
13750
|
|
|
13065
|
-
exports.READER_MODEL_ROLLOUT_URL = invariants.READER_MODEL_ROLLOUT_URL;
|
|
13066
|
-
|
|
13067
13751
|
exports.RESERVED_CONDITION_VARS = invariants.RESERVED_CONDITION_VARS;
|
|
13068
13752
|
|
|
13069
|
-
exports.
|
|
13753
|
+
exports.SIGNAL_SEMANTICS = invariants.SIGNAL_SEMANTICS;
|
|
13070
13754
|
|
|
13071
13755
|
exports.START_FILTER_VARS = invariants.START_FILTER_VARS;
|
|
13072
13756
|
|
|
@@ -13078,14 +13762,8 @@ exports.SpawnContractsInvalidError = invariants.SpawnContractsInvalidError;
|
|
|
13078
13762
|
|
|
13079
13763
|
exports.WORKFLOW_DEFINITION_TYPE = invariants.WORKFLOW_DEFINITION_TYPE;
|
|
13080
13764
|
|
|
13081
|
-
exports.WORKFLOW_INSTANCE_TYPE = invariants.WORKFLOW_INSTANCE_TYPE;
|
|
13082
|
-
|
|
13083
13765
|
exports.WorkflowError = invariants.WorkflowError;
|
|
13084
13766
|
|
|
13085
|
-
exports.assertReadableModel = invariants.assertReadableModel;
|
|
13086
|
-
|
|
13087
|
-
exports.assertReaderModelAcknowledgement = invariants.assertReaderModelAcknowledgement;
|
|
13088
|
-
|
|
13089
13767
|
exports.classifyPrincipalId = invariants.classifyPrincipalId;
|
|
13090
13768
|
|
|
13091
13769
|
exports.clientConfigFromResource = invariants.clientConfigFromResource;
|
|
@@ -13104,8 +13782,6 @@ exports.errorMessage = invariants.errorMessage;
|
|
|
13104
13782
|
|
|
13105
13783
|
exports.extractDocumentId = invariants.extractDocumentId;
|
|
13106
13784
|
|
|
13107
|
-
exports.fieldTreeShape = invariants.fieldTreeShape;
|
|
13108
|
-
|
|
13109
13785
|
exports.gdrFromResource = invariants.gdrFromResource;
|
|
13110
13786
|
|
|
13111
13787
|
exports.gdrRef = invariants.gdrRef;
|
|
@@ -13136,20 +13812,8 @@ exports.isTodoListEntry = invariants.isTodoListEntry;
|
|
|
13136
13812
|
|
|
13137
13813
|
exports.isTodoListItem = invariants.isTodoListItem;
|
|
13138
13814
|
|
|
13139
|
-
exports.isUnprimed = invariants.isUnprimed;
|
|
13140
|
-
|
|
13141
13815
|
exports.lakePrincipalId = invariants.lakePrincipalId;
|
|
13142
13816
|
|
|
13143
|
-
exports.minReaderModelOf = invariants.minReaderModelOf;
|
|
13144
|
-
|
|
13145
|
-
exports.modelVersionOf = invariants.modelVersionOf;
|
|
13146
|
-
|
|
13147
|
-
exports.parentRef = invariants.parentRef;
|
|
13148
|
-
|
|
13149
|
-
exports.parseDefinitionSnapshot = invariants.parseDefinitionSnapshot;
|
|
13150
|
-
|
|
13151
|
-
exports.parseDefinitionSnapshotValue = invariants.parseDefinitionSnapshotValue;
|
|
13152
|
-
|
|
13153
13817
|
exports.parseGdr = invariants.parseGdr;
|
|
13154
13818
|
|
|
13155
13819
|
exports.parseResourceGdr = invariants.parseResourceGdr;
|
|
@@ -13172,10 +13836,6 @@ exports.releaseDocId = invariants.releaseDocId;
|
|
|
13172
13836
|
|
|
13173
13837
|
exports.releaseRef = invariants.releaseRef;
|
|
13174
13838
|
|
|
13175
|
-
exports.requiredModelFeatures = invariants.requiredModelFeatures;
|
|
13176
|
-
|
|
13177
|
-
exports.requiredReaderModel = invariants.requiredReaderModel;
|
|
13178
|
-
|
|
13179
13839
|
exports.resourceAliasesToMap = invariants.resourceAliasesToMap;
|
|
13180
13840
|
|
|
13181
13841
|
exports.resourceFromParsed = invariants.resourceFromParsed;
|
|
@@ -13192,8 +13852,6 @@ exports.startKindOf = invariants.startKindOf;
|
|
|
13192
13852
|
|
|
13193
13853
|
exports.tagScopeFilter = invariants.tagScopeFilter;
|
|
13194
13854
|
|
|
13195
|
-
exports.terminalState = invariants.terminalState;
|
|
13196
|
-
|
|
13197
13855
|
exports.toBareId = invariants.toBareId;
|
|
13198
13856
|
|
|
13199
13857
|
exports.tryParseGdr = invariants.tryParseGdr;
|
|
@@ -13318,6 +13976,12 @@ exports.ConcurrentEditFieldError = ConcurrentEditFieldError;
|
|
|
13318
13976
|
|
|
13319
13977
|
exports.ConcurrentFireActionError = ConcurrentFireActionError;
|
|
13320
13978
|
|
|
13979
|
+
exports.DATA_MODEL_CHANGES = DATA_MODEL_CHANGES;
|
|
13980
|
+
|
|
13981
|
+
exports.DATA_MODEL_MIN_READER = DATA_MODEL_MIN_READER;
|
|
13982
|
+
|
|
13983
|
+
exports.DATA_MODEL_VERSION = DATA_MODEL_VERSION;
|
|
13984
|
+
|
|
13321
13985
|
exports.DEFAULT_CONTENT_PERSPECTIVE = DEFAULT_CONTENT_PERSPECTIVE;
|
|
13322
13986
|
|
|
13323
13987
|
exports.DEFAULT_EFFECT_LEASE_MS = DEFAULT_EFFECT_LEASE_MS;
|
|
@@ -13360,6 +14024,8 @@ exports.InitialFieldsInvalidError = InitialFieldsInvalidError;
|
|
|
13360
14024
|
|
|
13361
14025
|
exports.MissingHandlerError = MissingHandlerError;
|
|
13362
14026
|
|
|
14027
|
+
exports.ModelVersionAheadError = ModelVersionAheadError;
|
|
14028
|
+
|
|
13363
14029
|
exports.MutationGuardDeniedError = MutationGuardDeniedError;
|
|
13364
14030
|
|
|
13365
14031
|
exports.MutationGuardDocSchema = MutationGuardDocSchema;
|
|
@@ -13368,6 +14034,10 @@ exports.OP_DISPLAY = OP_DISPLAY;
|
|
|
13368
14034
|
|
|
13369
14035
|
exports.PartialGuardDeployError = PartialGuardDeployError;
|
|
13370
14036
|
|
|
14037
|
+
exports.READER_MODEL_ROLLOUT_URL = READER_MODEL_ROLLOUT_URL;
|
|
14038
|
+
|
|
14039
|
+
exports.ReaderModelAcknowledgementError = ReaderModelAcknowledgementError;
|
|
14040
|
+
|
|
13371
14041
|
exports.RefResourceUndeclaredError = RefResourceUndeclaredError;
|
|
13372
14042
|
|
|
13373
14043
|
exports.RequiredFieldNotProvidedError = RequiredFieldNotProvidedError;
|
|
@@ -13380,6 +14050,8 @@ exports.StartNotPrimedError = StartNotPrimedError;
|
|
|
13380
14050
|
|
|
13381
14051
|
exports.StartNotSettledError = StartNotSettledError;
|
|
13382
14052
|
|
|
14053
|
+
exports.WORKFLOW_INSTANCE_TYPE = WORKFLOW_INSTANCE_TYPE;
|
|
14054
|
+
|
|
13383
14055
|
exports.WorkflowActionFired = WorkflowActionFired;
|
|
13384
14056
|
|
|
13385
14057
|
exports.WorkflowActivityReset = WorkflowActivityReset;
|
|
@@ -13426,6 +14098,10 @@ exports.activityAutonomyOf = activityAutonomyOf;
|
|
|
13426
14098
|
|
|
13427
14099
|
exports.applicableDefinitions = applicableDefinitions;
|
|
13428
14100
|
|
|
14101
|
+
exports.assertReadableModel = assertReadableModel;
|
|
14102
|
+
|
|
14103
|
+
exports.assertReaderModelAcknowledgement = assertReaderModelAcknowledgement;
|
|
14104
|
+
|
|
13429
14105
|
exports.autonomySummary = autonomySummary;
|
|
13430
14106
|
|
|
13431
14107
|
exports.availableActions = availableActions;
|
|
@@ -13508,6 +14184,8 @@ exports.documentActionDenials = documentActionDenials;
|
|
|
13508
14184
|
|
|
13509
14185
|
exports.documentPrefilter = documentPrefilter;
|
|
13510
14186
|
|
|
14187
|
+
exports.documentStuckCause = documentStuckCause;
|
|
14188
|
+
|
|
13511
14189
|
exports.effectOutputsMap = effectOutputsMap;
|
|
13512
14190
|
|
|
13513
14191
|
exports.entryDocRefs = entryDocRefs;
|
|
@@ -13522,10 +14200,16 @@ exports.expandResourceAliases = expandResourceAliases;
|
|
|
13522
14200
|
|
|
13523
14201
|
exports.explainStartRequirement = explainStartRequirement;
|
|
13524
14202
|
|
|
14203
|
+
exports.fieldTreeShape = fieldTreeShape;
|
|
14204
|
+
|
|
14205
|
+
exports.findActivityNode = findActivityNode;
|
|
14206
|
+
|
|
13525
14207
|
exports.findCurrentActivityEntry = findCurrentActivityEntry;
|
|
13526
14208
|
|
|
13527
14209
|
exports.findOpenStageEntry = findOpenStageEntry;
|
|
13528
14210
|
|
|
14211
|
+
exports.findStageNode = findStageNode;
|
|
14212
|
+
|
|
13529
14213
|
exports.groupSitesOf = groupSitesOf;
|
|
13530
14214
|
|
|
13531
14215
|
exports.guardMatches = guardMatches;
|
|
@@ -13564,10 +14248,14 @@ exports.isFilterScopedOut = isFilterScopedOut;
|
|
|
13564
14248
|
|
|
13565
14249
|
exports.isProjectUserNotFoundError = isProjectUserNotFoundError;
|
|
13566
14250
|
|
|
14251
|
+
exports.isRevisionConflict = isRevisionConflict;
|
|
14252
|
+
|
|
13567
14253
|
exports.isTelemetryEnvDenied = isTelemetryEnvDenied;
|
|
13568
14254
|
|
|
13569
14255
|
exports.isTerminalStage = isTerminalStage;
|
|
13570
14256
|
|
|
14257
|
+
exports.isUnprimed = isUnprimed;
|
|
14258
|
+
|
|
13571
14259
|
exports.lakeGuardId = lakeGuardId;
|
|
13572
14260
|
|
|
13573
14261
|
exports.latestDefinitionsGroq = latestDefinitionsGroq;
|
|
@@ -13576,14 +14264,24 @@ exports.latestDeployedDefinitions = latestDeployedDefinitions;
|
|
|
13576
14264
|
|
|
13577
14265
|
exports.lintEffectOutputs = lintEffectOutputs;
|
|
13578
14266
|
|
|
14267
|
+
exports.minReaderModelOf = minReaderModelOf;
|
|
14268
|
+
|
|
13579
14269
|
exports.missingRequiredInputs = missingRequiredInputs;
|
|
13580
14270
|
|
|
14271
|
+
exports.modelVersionOf = modelVersionOf;
|
|
14272
|
+
|
|
13581
14273
|
exports.narrateAutonomyWaits = narrateAutonomyWaits;
|
|
13582
14274
|
|
|
13583
14275
|
exports.noopTelemetry = noopTelemetry;
|
|
13584
14276
|
|
|
14277
|
+
exports.parentRef = parentRef;
|
|
14278
|
+
|
|
13585
14279
|
exports.parseDefinitionInput = parseDefinitionInput;
|
|
13586
14280
|
|
|
14281
|
+
exports.parseDefinitionSnapshot = parseDefinitionSnapshot;
|
|
14282
|
+
|
|
14283
|
+
exports.parseDefinitionSnapshotValue = parseDefinitionSnapshotValue;
|
|
14284
|
+
|
|
13587
14285
|
exports.parseGuardDocument = parseGuardDocument;
|
|
13588
14286
|
|
|
13589
14287
|
exports.parseInstanceDocument = parseInstanceDocument;
|
|
@@ -13602,6 +14300,10 @@ exports.refsOf = refsOf;
|
|
|
13602
14300
|
|
|
13603
14301
|
exports.remediationsFor = remediationsFor;
|
|
13604
14302
|
|
|
14303
|
+
exports.requiredModelFeatures = requiredModelFeatures;
|
|
14304
|
+
|
|
14305
|
+
exports.requiredReaderModel = requiredReaderModel;
|
|
14306
|
+
|
|
13605
14307
|
exports.resolveAccess = resolveAccess;
|
|
13606
14308
|
|
|
13607
14309
|
exports.resolveActor = resolveActor;
|
|
@@ -13610,6 +14312,8 @@ exports.resolveClientActor = resolveClientActor;
|
|
|
13610
14312
|
|
|
13611
14313
|
exports.resolveFieldEntry = resolveFieldEntry$1;
|
|
13612
14314
|
|
|
14315
|
+
exports.resolveUserAttributes = resolveUserAttributes;
|
|
14316
|
+
|
|
13613
14317
|
exports.retractStageGuards = retractStageGuards;
|
|
13614
14318
|
|
|
13615
14319
|
exports.silentLogger = silentLogger;
|
|
@@ -13632,6 +14336,8 @@ exports.subscriptionDocumentsForInstance = subscriptionDocumentsForInstance;
|
|
|
13632
14336
|
|
|
13633
14337
|
exports.sweepStaleClaims = sweepStaleClaims;
|
|
13634
14338
|
|
|
14339
|
+
exports.terminalState = terminalState;
|
|
14340
|
+
|
|
13635
14341
|
exports.unboundRequirementReads = unboundRequirementReads;
|
|
13636
14342
|
|
|
13637
14343
|
exports.unsatisfiedTransitionSummaries = unsatisfiedTransitionSummaries;
|