@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.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rethrowWithContext, andConditions, deriveActivityKind, WorkflowError, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, actorFulfillsRole, toBareId, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, isAlwaysArrayFieldKind, evaluateCondition, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, parseGdr, isGdrUri, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, classifyPrincipalId, directoryBridgeId, InstanceNotFoundError, evaluateConditionOutcome, runGroq, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, lakePrincipalId, firstCarriedGlobalId, driverKind, EffectNotFoundError, deriveExecutorClassification, validateTag, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, DefinitionInUseError, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
|
|
2
2
|
|
|
3
|
-
import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY,
|
|
3
|
+
import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, SIGNAL_SEMANTICS, SYSTEM_IDENTITY, clientConfigFromResource, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
|
|
4
4
|
|
|
5
5
|
import { atomNode, dedupeBy, analyzeCondition, atomReadsDataset, checklistLines as checklistLines$1, phrase, quoted, listAnd, describeAtom as describeAtom$1, describeCondition as describeCondition$1, guillemets, formatValue, humanize, listOr, scopeReadOf, describeRead, explainCondition, dedupeReads, whatIfCondition, MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
|
|
6
6
|
|
|
@@ -41,6 +41,53 @@ function findCurrentActivityEntry(host, activityName) {
|
|
|
41
41
|
return findOpenStageEntry(host)?.activities.find(a => a.name === activityName);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
|
|
45
|
+
|
|
46
|
+
function terminalState(instance) {
|
|
47
|
+
return instance.abortedAt !== void 0 ? "aborted" : instance.completedAt !== void 0 ? "completed" : "in-flight";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isUnprimed(instance) {
|
|
51
|
+
return instance.stages.length === 0 && terminalState(instance) === "in-flight";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseDefinitionSnapshotValue(instance) {
|
|
55
|
+
try {
|
|
56
|
+
return normalizeLegacyActivityRequirements(JSON.parse(instance.definitionSnapshot));
|
|
57
|
+
} catch (err) {
|
|
58
|
+
rethrowWithContext(err, `Failed to parse definitionSnapshot on instance "${instance._id}"`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function normalizeLegacyActivityRequirements(value) {
|
|
63
|
+
for (const stage of arrayMember(value, "stages")) for (const activity of arrayMember(stage, "activities")) normalizeLegacyRequirementMap(activity);
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function arrayMember(value, key) {
|
|
68
|
+
if (typeof value != "object" || value === null) return [];
|
|
69
|
+
const member = value[key];
|
|
70
|
+
return Array.isArray(member) ? member : [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function normalizeLegacyRequirementMap(value) {
|
|
74
|
+
if (typeof value != "object" || value === null) return;
|
|
75
|
+
const activity = value, requirements = activity.requirements;
|
|
76
|
+
typeof requirements != "object" || requirements === null || Array.isArray(requirements) || (activity.requirements = Object.entries(requirements).map(([name, query]) => ({
|
|
77
|
+
type: "groq",
|
|
78
|
+
name: name,
|
|
79
|
+
query: query
|
|
80
|
+
})));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseDefinitionSnapshot(instance) {
|
|
84
|
+
return parseDefinitionSnapshotValue(instance);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function parentRef(instance) {
|
|
88
|
+
return instance.ancestors.at(-1);
|
|
89
|
+
}
|
|
90
|
+
|
|
44
91
|
function effectiveEditable(baseline, override) {
|
|
45
92
|
if (baseline === void 0) return;
|
|
46
93
|
if (override === void 0) return baseline;
|
|
@@ -388,6 +435,313 @@ function fieldEditedData(args) {
|
|
|
388
435
|
};
|
|
389
436
|
}
|
|
390
437
|
|
|
438
|
+
const DATA_MODEL_VERSION = 7, DATA_MODEL_MIN_READER = 4, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
|
|
439
|
+
|
|
440
|
+
class ReaderModelAcknowledgementError extends WorkflowError {
|
|
441
|
+
code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
|
|
442
|
+
expectedMinReaderModel;
|
|
443
|
+
engineMinReaderModel=DATA_MODEL_MIN_READER;
|
|
444
|
+
engineModelVersion=DATA_MODEL_VERSION;
|
|
445
|
+
documentationUrl=READER_MODEL_ROLLOUT_URL;
|
|
446
|
+
constructor(expectedMinReaderModel, context = "Deployment") {
|
|
447
|
+
const expected = expectedMinReaderModel === void 0 ? "missing" : String(expectedMinReaderModel);
|
|
448
|
+
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}`),
|
|
449
|
+
this.name = "ReaderModelAcknowledgementError", this.expectedMinReaderModel = expectedMinReaderModel;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function assertReaderModelAcknowledgement(expectedMinReaderModel, context) {
|
|
454
|
+
if (typeof expectedMinReaderModel != "number" || !Number.isFinite(expectedMinReaderModel) || !Number.isInteger(expectedMinReaderModel) || expectedMinReaderModel < 0 || expectedMinReaderModel !== DATA_MODEL_MIN_READER) throw new ReaderModelAcknowledgementError(expectedMinReaderModel, context);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
|
|
458
|
+
id: "governed-model-stamps",
|
|
459
|
+
introducedInModel: 1,
|
|
460
|
+
minReaderModel: 0,
|
|
461
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
462
|
+
compatibility: "additive",
|
|
463
|
+
applicability: "unconditional",
|
|
464
|
+
summary: "Definition and instance documents carry model provenance and reader-floor stamps."
|
|
465
|
+
}), Object.freeze({
|
|
466
|
+
id: "subject-field-kind",
|
|
467
|
+
introducedInModel: 2,
|
|
468
|
+
minReaderModel: 0,
|
|
469
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
470
|
+
compatibility: "additive",
|
|
471
|
+
applicability: "detectable",
|
|
472
|
+
summary: "A workflow-level subject field identifies the document a workflow is about."
|
|
473
|
+
}), Object.freeze({
|
|
474
|
+
id: "typed-scalar-choice-lists",
|
|
475
|
+
introducedInModel: 2,
|
|
476
|
+
minReaderModel: 2,
|
|
477
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
478
|
+
compatibility: "reader-floor",
|
|
479
|
+
applicability: "detectable",
|
|
480
|
+
summary: "Scalar fields may constrain writes to a persisted typed choice list."
|
|
481
|
+
}), Object.freeze({
|
|
482
|
+
id: "action-semantics",
|
|
483
|
+
introducedInModel: 2,
|
|
484
|
+
minReaderModel: 0,
|
|
485
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
486
|
+
compatibility: "additive",
|
|
487
|
+
applicability: "detectable",
|
|
488
|
+
summary: "Ordinary actions may carry advisory workflow semantics."
|
|
489
|
+
}), Object.freeze({
|
|
490
|
+
id: "inclusive-scalar-bounds",
|
|
491
|
+
introducedInModel: 2,
|
|
492
|
+
minReaderModel: 2,
|
|
493
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
494
|
+
compatibility: "reader-floor",
|
|
495
|
+
applicability: "detectable",
|
|
496
|
+
summary: "String, text, and number values may carry persisted inclusive bounds."
|
|
497
|
+
}), Object.freeze({
|
|
498
|
+
id: "progress-field-kind",
|
|
499
|
+
introducedInModel: 3,
|
|
500
|
+
minReaderModel: 0,
|
|
501
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
502
|
+
compatibility: "additive",
|
|
503
|
+
applicability: "detectable",
|
|
504
|
+
summary: "A progress field kind carries application-defined 0–100 completion."
|
|
505
|
+
}), Object.freeze({
|
|
506
|
+
id: "effect-claim-tokens",
|
|
507
|
+
introducedInModel: 3,
|
|
508
|
+
minReaderModel: 0,
|
|
509
|
+
documentTypes: Object.freeze([ "instance" ]),
|
|
510
|
+
compatibility: "additive",
|
|
511
|
+
applicability: "detectable",
|
|
512
|
+
summary: "Pending-effect claims carry an exact-claim token gating mid-dispatch state reports."
|
|
513
|
+
}), Object.freeze({
|
|
514
|
+
id: "classified-principal-ids",
|
|
515
|
+
introducedInModel: 4,
|
|
516
|
+
minReaderModel: 4,
|
|
517
|
+
documentTypes: Object.freeze([ "instance" ]),
|
|
518
|
+
compatibility: "reader-floor",
|
|
519
|
+
applicability: "unconditional",
|
|
520
|
+
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."
|
|
521
|
+
}), Object.freeze({
|
|
522
|
+
id: "readiness-requirements",
|
|
523
|
+
introducedInModel: 4,
|
|
524
|
+
minReaderModel: 4,
|
|
525
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
526
|
+
compatibility: "reader-floor",
|
|
527
|
+
applicability: "detectable",
|
|
528
|
+
summary: "Start and activity readiness use named polymorphic requirement arrays."
|
|
529
|
+
}), Object.freeze({
|
|
530
|
+
id: "due-date-field-kinds",
|
|
531
|
+
introducedInModel: 5,
|
|
532
|
+
minReaderModel: 0,
|
|
533
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
534
|
+
compatibility: "additive",
|
|
535
|
+
applicability: "detectable",
|
|
536
|
+
summary: "Due-date field kinds (dueDate, dueDatetime) mark a level deadline, elevated aliases of date/datetime carrying the same stored value."
|
|
537
|
+
}), Object.freeze({
|
|
538
|
+
id: "node-semantics",
|
|
539
|
+
introducedInModel: 6,
|
|
540
|
+
minReaderModel: 0,
|
|
541
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
542
|
+
compatibility: "additive",
|
|
543
|
+
applicability: "detectable",
|
|
544
|
+
summary: "Workflow, stage, activity, and action nodes may carry signal or custom advisory semantics."
|
|
545
|
+
}), Object.freeze({
|
|
546
|
+
id: "field-patch-ops",
|
|
547
|
+
introducedInModel: 6,
|
|
548
|
+
minReaderModel: 0,
|
|
549
|
+
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
550
|
+
compatibility: "additive",
|
|
551
|
+
applicability: "detectable",
|
|
552
|
+
summary: "Field ops may increment, decrement, or initialize a missing field value."
|
|
553
|
+
}), Object.freeze({
|
|
554
|
+
id: "attributes-condition-var",
|
|
555
|
+
introducedInModel: 7,
|
|
556
|
+
minReaderModel: 0,
|
|
557
|
+
documentTypes: Object.freeze([ "definition" ]),
|
|
558
|
+
compatibility: "additive",
|
|
559
|
+
applicability: "unconditional",
|
|
560
|
+
summary: "Caller-bound $attributes condition variable binds the acting token's org-level User Attributes (advisory; absent when unavailable)."
|
|
561
|
+
}) ]);
|
|
562
|
+
|
|
563
|
+
function recordOf(value) {
|
|
564
|
+
return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function recordsAt(record, key) {
|
|
568
|
+
const value = record[key];
|
|
569
|
+
return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
function nestedFieldEntries(entries) {
|
|
573
|
+
return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function parsedDefinitionSnapshot(root) {
|
|
577
|
+
if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
|
|
578
|
+
_id: typeof root._id == "string" ? root._id : "<unknown instance>",
|
|
579
|
+
definitionSnapshot: root.definitionSnapshot
|
|
580
|
+
}));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function persistedDefinitionTree(document) {
|
|
584
|
+
const root = recordOf(document);
|
|
585
|
+
if (root === void 0) return;
|
|
586
|
+
const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], {stages: stages, activities: activities, actions: actions} = definitionDescendants(roots);
|
|
587
|
+
return {
|
|
588
|
+
roots: roots,
|
|
589
|
+
stages: stages,
|
|
590
|
+
activities: activities,
|
|
591
|
+
actions: actions
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function persistedFieldEntries(document) {
|
|
596
|
+
const tree = persistedDefinitionTree(document);
|
|
597
|
+
if (tree === void 0) return [];
|
|
598
|
+
const {roots: roots, stages: stages, activities: activities, actions: actions} = tree, effects = actions.flatMap(action => recordsAt(action, "effects"));
|
|
599
|
+
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")) ]);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function definitionDescendants(roots) {
|
|
603
|
+
const stages = roots.flatMap(root => recordsAt(root, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions"));
|
|
604
|
+
return {
|
|
605
|
+
stages: stages,
|
|
606
|
+
activities: activities,
|
|
607
|
+
actions: actions
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function hasChoiceList(document) {
|
|
612
|
+
return persistedFieldEntries(document).some(entry => {
|
|
613
|
+
const options = recordOf(entry.options);
|
|
614
|
+
return options !== void 0 && Array.isArray(options.list);
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function hasFieldKind(document, kind) {
|
|
619
|
+
return persistedFieldEntries(document).some(entry => entry.type === kind || entry._type === kind);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function definitionNodes(document) {
|
|
623
|
+
const root = recordOf(document);
|
|
624
|
+
if (root !== void 0) return {
|
|
625
|
+
root: root,
|
|
626
|
+
...definitionDescendants([ root ])
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function hasActionSemantics(document) {
|
|
631
|
+
return definitionNodes(document)?.actions.some(hasSemantics) ?? !1;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function hasNodeSemantics(document) {
|
|
635
|
+
const nodes = definitionNodes(document);
|
|
636
|
+
return nodes === void 0 ? !1 : [ nodes.root, ...nodes.stages, ...nodes.activities ].some(hasSemantics) ? !0 : nodes.actions.some(action => hasSemantics(action) && action.semantics.some(isNodeSemanticValue));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function isNodeSemanticValue(semantic) {
|
|
640
|
+
return typeof semantic == "string" && (semantic.startsWith("signal.") || semantic.startsWith("custom."));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function hasSemantics(node) {
|
|
644
|
+
return Array.isArray(node.semantics);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function hasPersistedOpType(document, types) {
|
|
648
|
+
const tree = persistedDefinitionTree(document);
|
|
649
|
+
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)));
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function hasScalarValidation(document) {
|
|
653
|
+
return persistedFieldEntries(document).some(entry => {
|
|
654
|
+
const validation = recordOf(entry.validation);
|
|
655
|
+
return typeof validation?.min == "number" || typeof validation?.max == "number";
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function hasClaimTokens(document) {
|
|
660
|
+
const root = recordOf(document);
|
|
661
|
+
return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
|
|
662
|
+
const claim = recordOf(entry.claim);
|
|
663
|
+
return claim !== void 0 && typeof claim.claimToken == "string";
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function hasReadinessRequirements(document) {
|
|
668
|
+
const root = recordOf(document);
|
|
669
|
+
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)));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const featureDetectors = {
|
|
673
|
+
"governed-model-stamps": () => !0,
|
|
674
|
+
"subject-field-kind": document => hasFieldKind(document, "subject"),
|
|
675
|
+
"typed-scalar-choice-lists": hasChoiceList,
|
|
676
|
+
"action-semantics": hasActionSemantics,
|
|
677
|
+
"inclusive-scalar-bounds": hasScalarValidation,
|
|
678
|
+
"progress-field-kind": document => hasFieldKind(document, "progress"),
|
|
679
|
+
"effect-claim-tokens": hasClaimTokens,
|
|
680
|
+
"classified-principal-ids": () => !0,
|
|
681
|
+
"readiness-requirements": hasReadinessRequirements,
|
|
682
|
+
"due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime"),
|
|
683
|
+
"node-semantics": hasNodeSemantics,
|
|
684
|
+
"field-patch-ops": document => hasPersistedOpType(document, [ "field.inc", "field.dec", "field.setIfMissing" ]),
|
|
685
|
+
"attributes-condition-var": () => !0
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
function requiredModelFeatures(documentType, document) {
|
|
689
|
+
return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function requiredReaderModel(documentType, document) {
|
|
693
|
+
return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function modelStampFor(args) {
|
|
697
|
+
return {
|
|
698
|
+
modelVersion: DATA_MODEL_VERSION,
|
|
699
|
+
minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function fieldTreeShape(value) {
|
|
704
|
+
if (Array.isArray(value)) return value.map(fieldTreeShape);
|
|
705
|
+
if (value === null) return "null";
|
|
706
|
+
if (typeof value == "object") {
|
|
707
|
+
const record = value;
|
|
708
|
+
return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
|
|
709
|
+
}
|
|
710
|
+
return typeof value;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function modelVersionOf(doc) {
|
|
714
|
+
const stamp = doc.modelVersion;
|
|
715
|
+
return typeof stamp == "number" ? stamp : 0;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function minReaderModelOf(doc) {
|
|
719
|
+
const floor = doc.minReaderModel;
|
|
720
|
+
return typeof floor == "number" ? floor : modelVersionOf(doc);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
class ModelVersionAheadError extends WorkflowError {
|
|
724
|
+
documentId;
|
|
725
|
+
documentModelVersion;
|
|
726
|
+
requiredReaderModel;
|
|
727
|
+
engineModelVersion;
|
|
728
|
+
constructor(args) {
|
|
729
|
+
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.`),
|
|
730
|
+
this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
|
|
731
|
+
this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function assertReadableModel(doc) {
|
|
736
|
+
const documentReaderModel = minReaderModelOf(doc);
|
|
737
|
+
if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
|
|
738
|
+
documentId: doc._id,
|
|
739
|
+
documentModelVersion: modelVersionOf(doc),
|
|
740
|
+
requiredReaderModel: documentReaderModel
|
|
741
|
+
});
|
|
742
|
+
return doc;
|
|
743
|
+
}
|
|
744
|
+
|
|
391
745
|
function effectSites(def) {
|
|
392
746
|
const sites = [];
|
|
393
747
|
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({
|
|
@@ -862,12 +1216,8 @@ function renderWorkflowRead(read, ctx) {
|
|
|
862
1216
|
text: guillemets(title)
|
|
863
1217
|
});
|
|
864
1218
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
permission: read.path[0]
|
|
868
|
-
},
|
|
869
|
-
text: `your ${read.path[0]} permission`
|
|
870
|
-
});
|
|
1219
|
+
const keyed = keyedCallerRead(read);
|
|
1220
|
+
if (keyed !== void 0) return keyed;
|
|
871
1221
|
if (read.variable === "actor" && read.path.length === 1 && read.path[0] === "id") return phrase("read.actor-id", {
|
|
872
1222
|
params: {},
|
|
873
1223
|
text: "your id"
|
|
@@ -889,6 +1239,24 @@ function renderWorkflowRead(read, ctx) {
|
|
|
889
1239
|
});
|
|
890
1240
|
}
|
|
891
1241
|
|
|
1242
|
+
function keyedCallerRead(read) {
|
|
1243
|
+
const key = read.path[0];
|
|
1244
|
+
if (typeof key == "string") {
|
|
1245
|
+
if (read.variable === "can") return phrase("read.permission", {
|
|
1246
|
+
params: {
|
|
1247
|
+
permission: key
|
|
1248
|
+
},
|
|
1249
|
+
text: `your ${key} permission`
|
|
1250
|
+
});
|
|
1251
|
+
if (read.variable === "attributes") return phrase("read.attribute", {
|
|
1252
|
+
params: {
|
|
1253
|
+
attribute: key
|
|
1254
|
+
},
|
|
1255
|
+
text: `your ${guillemets(key)} attribute`
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
892
1260
|
function workflowRequirement(requirement, ctx) {
|
|
893
1261
|
const {target: target} = requirement, clause = clauseVarRequirement(requirement);
|
|
894
1262
|
if (clause !== void 0) return clause;
|
|
@@ -1789,6 +2157,10 @@ function derefBase(ref, snapshot) {
|
|
|
1789
2157
|
};
|
|
1790
2158
|
}
|
|
1791
2159
|
|
|
2160
|
+
function isRecord(value) {
|
|
2161
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
2162
|
+
}
|
|
2163
|
+
|
|
1792
2164
|
function buildParams(args) {
|
|
1793
2165
|
const {instance: instance, now: now, snapshot: snapshot, extra: extra} = args, currentActivities2 = findOpenStageEntry(instance)?.activities ?? [];
|
|
1794
2166
|
return {
|
|
@@ -2258,6 +2630,12 @@ function isRevisionConflict(error) {
|
|
|
2258
2630
|
return statusCode === 409 ? !0 : typeof message == "string" && message.includes("ifRevisionId check failed");
|
|
2259
2631
|
}
|
|
2260
2632
|
|
|
2633
|
+
function isCreateIdCollision(error) {
|
|
2634
|
+
if (typeof error != "object" || error === null) return !1;
|
|
2635
|
+
const {message: message, responseBody: responseBody} = error;
|
|
2636
|
+
return typeof message == "string" && message.includes("already exists") && (message.includes("Document by ID") || message.includes("create() failed")) ? !0 : typeof responseBody == "string" && responseBody.includes("documentAlreadyExistsError");
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2261
2639
|
class ConcurrentEditFieldError extends WorkflowError {
|
|
2262
2640
|
instanceId;
|
|
2263
2641
|
target;
|
|
@@ -2310,7 +2688,7 @@ class CascadeLimitError extends WorkflowError {
|
|
|
2310
2688
|
}
|
|
2311
2689
|
}
|
|
2312
2690
|
|
|
2313
|
-
const FIELD_OP_TYPES = [ "field.set", "field.unset", "field.append", "field.updateWhere", "field.removeWhere" ];
|
|
2691
|
+
const FIELD_OP_TYPES = [ "field.set", "field.setIfMissing", "field.unset", "field.append", "field.inc", "field.dec", "field.updateWhere", "field.removeWhere" ];
|
|
2314
2692
|
|
|
2315
2693
|
function isFieldOp(summary) {
|
|
2316
2694
|
return FIELD_OP_TYPES.includes(summary.opType);
|
|
@@ -2411,7 +2789,7 @@ async function runOps(args) {
|
|
|
2411
2789
|
refSurface: refSurface,
|
|
2412
2790
|
opsFromDefinition: opsFromDefinition
|
|
2413
2791
|
});
|
|
2414
|
-
summaries.push(summary), mutation.history.push(opAppliedEntry({
|
|
2792
|
+
summaries.push(summary), shouldRecordOpApplied(summary) && mutation.history.push(opAppliedEntry({
|
|
2415
2793
|
origin: origin,
|
|
2416
2794
|
summary: summary,
|
|
2417
2795
|
stage: stage,
|
|
@@ -2422,6 +2800,10 @@ async function runOps(args) {
|
|
|
2422
2800
|
return summaries;
|
|
2423
2801
|
}
|
|
2424
2802
|
|
|
2803
|
+
function shouldRecordOpApplied(summary) {
|
|
2804
|
+
return summary.opType !== "field.setIfMissing" || summary.resolved !== void 0;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2425
2807
|
function opAppliedEntry(args) {
|
|
2426
2808
|
const {origin: origin, summary: summary, stage: stage, actor: actor, now: now} = args;
|
|
2427
2809
|
return {
|
|
@@ -2493,12 +2875,19 @@ async function applyOp(op, ctx) {
|
|
|
2493
2875
|
case "field.set":
|
|
2494
2876
|
return applyFieldSet(op, ctx);
|
|
2495
2877
|
|
|
2878
|
+
case "field.setIfMissing":
|
|
2879
|
+
return applyFieldSetIfMissing(op, ctx);
|
|
2880
|
+
|
|
2496
2881
|
case "field.unset":
|
|
2497
2882
|
return applyFieldUnset(op, ctx);
|
|
2498
2883
|
|
|
2499
2884
|
case "field.append":
|
|
2500
2885
|
return applyFieldAppend(op, ctx);
|
|
2501
2886
|
|
|
2887
|
+
case "field.inc":
|
|
2888
|
+
case "field.dec":
|
|
2889
|
+
return applyFieldArithmetic(op, ctx);
|
|
2890
|
+
|
|
2502
2891
|
case "field.updateWhere":
|
|
2503
2892
|
return applyFieldUpdateWhere(op, ctx);
|
|
2504
2893
|
|
|
@@ -2537,6 +2926,78 @@ function applyFieldSet(op, ctx) {
|
|
|
2537
2926
|
};
|
|
2538
2927
|
}
|
|
2539
2928
|
|
|
2929
|
+
function applyFieldSetIfMissing(op, ctx) {
|
|
2930
|
+
const entry = locateEntry(ctx, op.target);
|
|
2931
|
+
return isAlwaysArrayFieldKind(entry._type) && rejectFieldOpTarget({
|
|
2932
|
+
entry: entry,
|
|
2933
|
+
op: op,
|
|
2934
|
+
issue: "is always array-valued — setIfMissing applies to nullable entries only; an empty array entry already holds []"
|
|
2935
|
+
}), entry.value !== null && entry.value !== void 0 ? {
|
|
2936
|
+
opType: op.type,
|
|
2937
|
+
target: op.target
|
|
2938
|
+
} : {
|
|
2939
|
+
...applyFieldSet({
|
|
2940
|
+
...op,
|
|
2941
|
+
type: "field.set"
|
|
2942
|
+
}, ctx),
|
|
2943
|
+
opType: op.type
|
|
2944
|
+
};
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
function applyFieldArithmetic(op, ctx) {
|
|
2948
|
+
const entry = locateEntry(ctx, op.target);
|
|
2949
|
+
entry._type !== "number" && rejectFieldOpTarget({
|
|
2950
|
+
entry: entry,
|
|
2951
|
+
op: op,
|
|
2952
|
+
issue: `is a ${entry._type} entry — arithmetic ops target \`number\` entries only`
|
|
2953
|
+
}), typeof entry.value != "number" && rejectFieldOpTarget({
|
|
2954
|
+
entry: entry,
|
|
2955
|
+
op: op,
|
|
2956
|
+
issue: "has no numeric value — initialize it before applying arithmetic"
|
|
2957
|
+
});
|
|
2958
|
+
const resolvedDelta = op.value === void 0 ? 1 : resolveOpValue({
|
|
2959
|
+
src: op.value,
|
|
2960
|
+
ctx: ctx,
|
|
2961
|
+
target: {
|
|
2962
|
+
kind: "number"
|
|
2963
|
+
}
|
|
2964
|
+
});
|
|
2965
|
+
(typeof resolvedDelta != "number" || !Number.isFinite(resolvedDelta)) && rejectFieldOpTarget({
|
|
2966
|
+
entry: entry,
|
|
2967
|
+
op: op,
|
|
2968
|
+
issue: "value must resolve to a finite number"
|
|
2969
|
+
});
|
|
2970
|
+
const nextValue = entry.value + (op.type === "field.inc" ? resolvedDelta : -resolvedDelta);
|
|
2971
|
+
Number.isFinite(nextValue) || rejectFieldOpTarget({
|
|
2972
|
+
entry: entry,
|
|
2973
|
+
op: op,
|
|
2974
|
+
issue: "result must be a finite number"
|
|
2975
|
+
});
|
|
2976
|
+
const value = validateFieldValue({
|
|
2977
|
+
entryType: entry._type,
|
|
2978
|
+
entryName: entry.name,
|
|
2979
|
+
value: nextValue,
|
|
2980
|
+
...entryShape(entry)
|
|
2981
|
+
});
|
|
2982
|
+
return setEntryValue(entry, value), {
|
|
2983
|
+
opType: op.type,
|
|
2984
|
+
target: op.target,
|
|
2985
|
+
resolved: {
|
|
2986
|
+
value: value
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
function rejectFieldOpTarget(args) {
|
|
2992
|
+
const {entry: entry, op: op, issue: issue} = args;
|
|
2993
|
+
throw new FieldValueShapeError({
|
|
2994
|
+
entryType: entry._type,
|
|
2995
|
+
entryName: entry.name,
|
|
2996
|
+
mode: "value",
|
|
2997
|
+
issues: [ `${op.type} target ${op.target.scope}:"${op.target.field}" ${issue}` ]
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3000
|
+
|
|
2540
3001
|
function entryShape(entry) {
|
|
2541
3002
|
return entry._type === "object" ? {
|
|
2542
3003
|
fields: entry.fields
|
|
@@ -2572,15 +3033,9 @@ function appendItemSlot(entry) {
|
|
|
2572
3033
|
};
|
|
2573
3034
|
}
|
|
2574
3035
|
|
|
2575
|
-
const EMPTY_BY_KIND = {
|
|
2576
|
-
"doc.refs": [],
|
|
2577
|
-
array: [],
|
|
2578
|
-
assignees: []
|
|
2579
|
-
};
|
|
2580
|
-
|
|
2581
3036
|
function applyFieldUnset(op, ctx) {
|
|
2582
3037
|
const entry = locateEntry(ctx, op.target);
|
|
2583
|
-
return setEntryValue(entry,
|
|
3038
|
+
return setEntryValue(entry, isAlwaysArrayFieldKind(entry._type) ? [] : null), {
|
|
2584
3039
|
opType: op.type,
|
|
2585
3040
|
target: op.target
|
|
2586
3041
|
};
|
|
@@ -2619,7 +3074,7 @@ function applyFieldAppend(op, ctx) {
|
|
|
2619
3074
|
}
|
|
2620
3075
|
|
|
2621
3076
|
function withRowKey(item) {
|
|
2622
|
-
return
|
|
3077
|
+
return isRecord(item) && !("_key" in item) ? {
|
|
2623
3078
|
_key: randomKey(),
|
|
2624
3079
|
...item
|
|
2625
3080
|
} : item;
|
|
@@ -3318,6 +3773,14 @@ function latestDeployedDefinitions(rows) {
|
|
|
3318
3773
|
return [ ...byName.values() ];
|
|
3319
3774
|
}
|
|
3320
3775
|
|
|
3776
|
+
function findStageNode(args) {
|
|
3777
|
+
return args.definition?.stages.find(entry => entry.name === args.stageName);
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3780
|
+
function findActivityNode(args) {
|
|
3781
|
+
return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3321
3784
|
function liveChildrenField(instance) {
|
|
3322
3785
|
const live = liveSubworkflows(instance).length;
|
|
3323
3786
|
return live > 0 ? {
|
|
@@ -3406,6 +3869,27 @@ function noTransitionFiresCause(input) {
|
|
|
3406
3869
|
};
|
|
3407
3870
|
}
|
|
3408
3871
|
|
|
3872
|
+
function stuckFromDocumentState(input) {
|
|
3873
|
+
return failedEffectCause(input) ?? failedActivityCause(input) ?? hungEffectCause(input);
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
function documentStuckCause(args) {
|
|
3877
|
+
const stage = findOpenStageEntry(args.instance);
|
|
3878
|
+
if (stage !== void 0) return stuckFromDocumentState({
|
|
3879
|
+
instance: args.instance,
|
|
3880
|
+
activities: stage.activities.map(entry => ({
|
|
3881
|
+
status: entry.status,
|
|
3882
|
+
activity: findActivityNode({
|
|
3883
|
+
activityName: entry.name,
|
|
3884
|
+
definition: args.definition,
|
|
3885
|
+
stageName: stage.name
|
|
3886
|
+
}) ?? {
|
|
3887
|
+
name: entry.name
|
|
3888
|
+
}
|
|
3889
|
+
}))
|
|
3890
|
+
});
|
|
3891
|
+
}
|
|
3892
|
+
|
|
3409
3893
|
function diagnoseInstance(input) {
|
|
3410
3894
|
const {instance: instance} = input, terminal = terminalState(instance);
|
|
3411
3895
|
if (terminal === "aborted" && instance.abortedAt !== void 0) {
|
|
@@ -3424,7 +3908,7 @@ function diagnoseInstance(input) {
|
|
|
3424
3908
|
at: instance.completedAt,
|
|
3425
3909
|
...liveChildrenField(instance)
|
|
3426
3910
|
};
|
|
3427
|
-
const cause =
|
|
3911
|
+
const cause = stuckFromDocumentState(input) ?? noTransitionFiresCause(input);
|
|
3428
3912
|
return cause !== void 0 ? {
|
|
3429
3913
|
state: "stuck",
|
|
3430
3914
|
cause: cause
|
|
@@ -3803,10 +4287,8 @@ function assertRequiredInputProvided({entryDefs: entryDefs, initialFields: initi
|
|
|
3803
4287
|
});
|
|
3804
4288
|
}
|
|
3805
4289
|
|
|
3806
|
-
const ARRAY_FIELD_TYPES = /* @__PURE__ */ new Set([ "doc.refs", "array", "assignees" ]);
|
|
3807
|
-
|
|
3808
4290
|
function defaultEntryValue(entryType) {
|
|
3809
|
-
return
|
|
4291
|
+
return isAlwaysArrayFieldKind(entryType) ? [] : null;
|
|
3810
4292
|
}
|
|
3811
4293
|
|
|
3812
4294
|
function resolveInputValue({entry: entry, initialFields: initialFields, defaultValue: defaultValue}) {
|
|
@@ -4407,7 +4889,9 @@ const SYNC_COMMIT = {
|
|
|
4407
4889
|
effect: "workflow.effect",
|
|
4408
4890
|
verifyDefinitions: "workflow.verify-definitions",
|
|
4409
4891
|
accessResolveActor: "workflow.access.resolve-actor",
|
|
4410
|
-
accessGrants: "workflow.access.grants"
|
|
4892
|
+
accessGrants: "workflow.access.grants",
|
|
4893
|
+
accessResolveOrg: "workflow.access.resolve-org",
|
|
4894
|
+
accessAttributes: "workflow.access.attributes"
|
|
4411
4895
|
}, RAW_PATCH = /* @__PURE__ */ Symbol("workflow-engine.raw-patch");
|
|
4412
4896
|
|
|
4413
4897
|
function unwrapPatch(patch) {
|
|
@@ -5375,10 +5859,6 @@ function userLoginProvider(user) {
|
|
|
5375
5859
|
return user?.provider ?? user?.loginProvider;
|
|
5376
5860
|
}
|
|
5377
5861
|
|
|
5378
|
-
function isRecord(value) {
|
|
5379
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
5380
|
-
}
|
|
5381
|
-
|
|
5382
5862
|
function optionalString(value) {
|
|
5383
5863
|
return value === void 0 || typeof value == "string";
|
|
5384
5864
|
}
|
|
@@ -5883,12 +6363,14 @@ function resolveGuard({guard: guard, instance: instance, stageName: stageName, n
|
|
|
5883
6363
|
|
|
5884
6364
|
async function upsertGuard(args) {
|
|
5885
6365
|
const {client: client, doc: doc, exists: exists} = args;
|
|
5886
|
-
if (!exists) {
|
|
6366
|
+
if (!exists) try {
|
|
5887
6367
|
await client.create(doc, {
|
|
5888
6368
|
...SYNC_COMMIT,
|
|
5889
6369
|
tag: REQUEST_TAG.guardDeploy
|
|
5890
6370
|
});
|
|
5891
6371
|
return;
|
|
6372
|
+
} catch (error) {
|
|
6373
|
+
if (!isCreateIdCollision(error)) throw error;
|
|
5892
6374
|
}
|
|
5893
6375
|
const {_id: _id, _type: _type, _rev: _rev, _createdAt: _createdAt, _updatedAt: _updatedAt, ...body} = doc;
|
|
5894
6376
|
await client.patch(doc._id).set(body).commit({
|
|
@@ -6913,54 +7395,461 @@ async function advisoryCan({instance: instance, identity: identity, grants: gran
|
|
|
6913
7395
|
return can;
|
|
6914
7396
|
}
|
|
6915
7397
|
|
|
6916
|
-
|
|
7398
|
+
const DANGEROUS_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([ "__proto__", "constructor", "prototype" ]);
|
|
7399
|
+
|
|
7400
|
+
function attributeEntry(row) {
|
|
7401
|
+
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 ];
|
|
7402
|
+
}
|
|
7403
|
+
|
|
7404
|
+
function normalizeUserAttributes(response) {
|
|
7405
|
+
if (!isRecord(response)) return;
|
|
7406
|
+
const rows = response.attributes;
|
|
7407
|
+
if (!Array.isArray(rows)) return;
|
|
7408
|
+
const out = {};
|
|
7409
|
+
for (const row of rows) {
|
|
7410
|
+
const entry = attributeEntry(row);
|
|
7411
|
+
entry !== void 0 && (out[entry[0]] = entry[1]);
|
|
7412
|
+
}
|
|
7413
|
+
return out;
|
|
7414
|
+
}
|
|
7415
|
+
|
|
7416
|
+
const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap, orgIdCache = /* @__PURE__ */ new WeakMap, attributesCache = /* @__PURE__ */ new WeakMap;
|
|
7417
|
+
|
|
7418
|
+
async function resolveAccess(taggedClient, args = {}) {
|
|
7419
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7420
|
+
if (requestFn === void 0) throw new 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).");
|
|
7421
|
+
const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
|
|
7422
|
+
client: client,
|
|
7423
|
+
requestFn: requestFn,
|
|
7424
|
+
resourcePath: args.grantsFromPath
|
|
7425
|
+
}) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
|
|
7426
|
+
if (identity === void 0) throw new ContractViolationError("workflow: failed to resolve actor from `/users/me`. The client is configured but the endpoint returned no usable identity — check the token.");
|
|
6917
7427
|
return {
|
|
6918
|
-
|
|
6919
|
-
...
|
|
6920
|
-
|
|
7428
|
+
actor: identity.actor,
|
|
7429
|
+
...identity.localPrincipalId !== void 0 ? {
|
|
7430
|
+
localPrincipalId: identity.localPrincipalId
|
|
6921
7431
|
} : {},
|
|
6922
|
-
...
|
|
6923
|
-
|
|
7432
|
+
...grants !== void 0 ? {
|
|
7433
|
+
grants: grants
|
|
6924
7434
|
} : {}
|
|
6925
7435
|
};
|
|
6926
7436
|
}
|
|
6927
7437
|
|
|
6928
|
-
function
|
|
6929
|
-
|
|
7438
|
+
async function resolveUserAttributes(taggedClient) {
|
|
7439
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7440
|
+
if (requestFn !== void 0) return cachedAttributes({
|
|
7441
|
+
client: client,
|
|
7442
|
+
requestFn: requestFn
|
|
7443
|
+
});
|
|
6930
7444
|
}
|
|
6931
7445
|
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
action: args.action,
|
|
6940
|
-
reason: args.reason
|
|
6941
|
-
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
6942
|
-
this.action = args.action;
|
|
6943
|
-
}
|
|
7446
|
+
function cachedActor(client, requestFn) {
|
|
7447
|
+
const cached = actorCache.get(client);
|
|
7448
|
+
if (cached !== void 0) return cached;
|
|
7449
|
+
const pending = fetchActor(client, requestFn).catch(err => {
|
|
7450
|
+
throw actorCache.get(client) === pending && actorCache.delete(client), err;
|
|
7451
|
+
});
|
|
7452
|
+
return actorCache.set(client, pending), pending;
|
|
6944
7453
|
}
|
|
6945
7454
|
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
}
|
|
7455
|
+
function grantsForClientPath(taggedClient, resourcePath) {
|
|
7456
|
+
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
7457
|
+
return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
|
|
7458
|
+
client: client,
|
|
7459
|
+
requestFn: requestFn,
|
|
7460
|
+
resourcePath: resourcePath
|
|
7461
|
+
});
|
|
6953
7462
|
}
|
|
6954
7463
|
|
|
6955
|
-
function
|
|
6956
|
-
|
|
6957
|
-
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
7464
|
+
function lazyRequest(client) {
|
|
7465
|
+
return client.request === void 0 ? void 0 : opts => client.request(opts);
|
|
6958
7466
|
}
|
|
6959
7467
|
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
7468
|
+
function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
|
|
7469
|
+
return cachedByKey({
|
|
7470
|
+
store: grantsCache,
|
|
7471
|
+
client: client,
|
|
7472
|
+
key: resourcePath,
|
|
7473
|
+
load: () => fetchGrantsCached(requestFn, resourcePath)
|
|
7474
|
+
});
|
|
7475
|
+
}
|
|
7476
|
+
|
|
7477
|
+
function cachedByKey(args) {
|
|
7478
|
+
let byKey = args.store.get(args.client);
|
|
7479
|
+
byKey === void 0 && (byKey = /* @__PURE__ */ new Map, args.store.set(args.client, byKey));
|
|
7480
|
+
const cached = byKey.get(args.key);
|
|
7481
|
+
if (cached !== void 0) return cached;
|
|
7482
|
+
const pending = args.evictOnRejection ? args.load().catch(err => {
|
|
7483
|
+
throw byKey.get(args.key) === pending && byKey.delete(args.key), err;
|
|
7484
|
+
}) : args.load();
|
|
7485
|
+
return byKey.set(args.key, pending), pending;
|
|
7486
|
+
}
|
|
7487
|
+
|
|
7488
|
+
async function fetchActor(client, requestFn) {
|
|
7489
|
+
const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalHostId = usableId(globalUser.user), carriedId = firstCarriedGlobalId([ globalHostId, resourceId ]), sessionId = carriedId ?? globalHostId ?? resourceId;
|
|
7490
|
+
if (sessionId === void 0) return;
|
|
7491
|
+
const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
|
|
7492
|
+
client: client,
|
|
7493
|
+
sessionId: sessionId,
|
|
7494
|
+
resourceId: resourceId
|
|
7495
|
+
}) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
|
|
7496
|
+
refuseProjectScopedActor({
|
|
7497
|
+
id: id,
|
|
7498
|
+
globalUser: globalUser,
|
|
7499
|
+
globalHostId: globalHostId,
|
|
7500
|
+
bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
|
|
7501
|
+
});
|
|
7502
|
+
const roleNames = roleNamesFor(resourceUser, globalUser);
|
|
7503
|
+
return {
|
|
7504
|
+
actor: {
|
|
7505
|
+
kind: "person",
|
|
7506
|
+
id: id,
|
|
7507
|
+
...roleNames.length > 0 ? {
|
|
7508
|
+
roles: roleNames
|
|
7509
|
+
} : {}
|
|
7510
|
+
},
|
|
7511
|
+
...resourceId !== void 0 && resourceId !== id ? {
|
|
7512
|
+
localPrincipalId: resourceId
|
|
7513
|
+
} : {}
|
|
7514
|
+
};
|
|
7515
|
+
}
|
|
7516
|
+
|
|
7517
|
+
function roleNamesFor(resourceUser, globalUser) {
|
|
7518
|
+
return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
|
|
7519
|
+
}
|
|
7520
|
+
|
|
7521
|
+
const NO_BRIDGE = {
|
|
7522
|
+
status: "not-applicable"
|
|
7523
|
+
};
|
|
7524
|
+
|
|
7525
|
+
function globalRouteReason(globalUser, globalHostId) {
|
|
7526
|
+
return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
|
|
7527
|
+
}
|
|
7528
|
+
|
|
7529
|
+
async function bridgeProjectPrincipal(args) {
|
|
7530
|
+
const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
|
|
7531
|
+
return classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project" ? {
|
|
7532
|
+
status: "unavailable",
|
|
7533
|
+
reason: "no project-scoped principal from the resource host to address the directory with"
|
|
7534
|
+
} : directoryGlobalId({
|
|
7535
|
+
client: client,
|
|
7536
|
+
principalId: resourceId
|
|
7537
|
+
});
|
|
7538
|
+
}
|
|
7539
|
+
|
|
7540
|
+
async function directoryGlobalId(args) {
|
|
7541
|
+
const {client: client, principalId: principalId} = args, projectId = projectIdOf(client);
|
|
7542
|
+
if (projectId === void 0) return {
|
|
7543
|
+
status: "unavailable",
|
|
7544
|
+
reason: "the client reports no projectId, so its user directory has no address"
|
|
7545
|
+
};
|
|
7546
|
+
const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
|
|
7547
|
+
if (lookup.status !== "resolved") return {
|
|
7548
|
+
status: "unavailable",
|
|
7549
|
+
reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
|
|
7550
|
+
...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
|
|
7551
|
+
cause: lookup.cause
|
|
7552
|
+
} : {}
|
|
7553
|
+
};
|
|
7554
|
+
const globalId = directoryBridgeId(lookup.user.sanityUserId);
|
|
7555
|
+
return globalId === void 0 ? {
|
|
7556
|
+
status: "unavailable",
|
|
7557
|
+
reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
|
|
7558
|
+
} : {
|
|
7559
|
+
status: "resolved",
|
|
7560
|
+
globalId: globalId
|
|
7561
|
+
};
|
|
7562
|
+
}
|
|
7563
|
+
|
|
7564
|
+
function refuseProjectScopedActor(args) {
|
|
7565
|
+
const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
|
|
7566
|
+
if (classifyPrincipalId(id).namespace !== "project") return;
|
|
7567
|
+
const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
|
|
7568
|
+
bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
|
|
7569
|
+
const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
|
|
7570
|
+
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 : {
|
|
7571
|
+
cause: cause
|
|
7572
|
+
});
|
|
7573
|
+
}
|
|
7574
|
+
|
|
7575
|
+
function usableId(user) {
|
|
7576
|
+
if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
|
|
7577
|
+
}
|
|
7578
|
+
|
|
7579
|
+
async function fetchCurrentUser(requestFn, hostDescription) {
|
|
7580
|
+
try {
|
|
7581
|
+
return await requestFn({
|
|
7582
|
+
uri: "/users/me",
|
|
7583
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
7584
|
+
});
|
|
7585
|
+
} catch (err) {
|
|
7586
|
+
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.`, {
|
|
7587
|
+
cause: err
|
|
7588
|
+
});
|
|
7589
|
+
}
|
|
7590
|
+
}
|
|
7591
|
+
|
|
7592
|
+
async function fetchGlobalUser(client) {
|
|
7593
|
+
const sibling = globalHostRequestOf(client);
|
|
7594
|
+
if ("reason" in sibling) return {
|
|
7595
|
+
user: void 0,
|
|
7596
|
+
reason: sibling.reason,
|
|
7597
|
+
...sibling.cause !== void 0 ? {
|
|
7598
|
+
cause: sibling.cause
|
|
7599
|
+
} : {}
|
|
7600
|
+
};
|
|
7601
|
+
try {
|
|
7602
|
+
const user = await sibling.request({
|
|
7603
|
+
uri: "/users/me",
|
|
7604
|
+
tag: REQUEST_TAG.accessResolveActor
|
|
7605
|
+
}), id = usableId(user);
|
|
7606
|
+
return sibling.requireGlobalPrincipal && id !== void 0 && classifyPrincipalId(id).namespace === "project" ? {
|
|
7607
|
+
user: void 0,
|
|
7608
|
+
reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
|
|
7609
|
+
} : {
|
|
7610
|
+
user: user
|
|
7611
|
+
};
|
|
7612
|
+
} catch (err) {
|
|
7613
|
+
return {
|
|
7614
|
+
user: void 0,
|
|
7615
|
+
reason: `global-host /users/me failed: ${errorMessage(err)}`,
|
|
7616
|
+
cause: err
|
|
7617
|
+
};
|
|
7618
|
+
}
|
|
7619
|
+
}
|
|
7620
|
+
|
|
7621
|
+
function globalHostRequestOf(client) {
|
|
7622
|
+
if (typeof client.withConfig != "function") return {
|
|
7623
|
+
reason: "the client cannot reach the global API host (no withConfig)"
|
|
7624
|
+
};
|
|
7625
|
+
const hostResolution = resolveGlobalApiHost(client);
|
|
7626
|
+
try {
|
|
7627
|
+
const globalClient = client.withConfig({
|
|
7628
|
+
useProjectHostname: !1,
|
|
7629
|
+
apiVersion: ENGINE_API_VERSION,
|
|
7630
|
+
...hostResolution.apiHost === void 0 ? {} : {
|
|
7631
|
+
apiHost: hostResolution.apiHost
|
|
7632
|
+
}
|
|
7633
|
+
}), request = lazyRequest(globalClient);
|
|
7634
|
+
return request === void 0 ? {
|
|
7635
|
+
reason: "the global-host sibling client cannot issue requests"
|
|
7636
|
+
} : {
|
|
7637
|
+
request: request,
|
|
7638
|
+
requireGlobalPrincipal: hostResolution.requireGlobalPrincipal
|
|
7639
|
+
};
|
|
7640
|
+
} catch (err) {
|
|
7641
|
+
return {
|
|
7642
|
+
reason: `building the global-host sibling client failed: ${errorMessage(err)}`,
|
|
7643
|
+
cause: err
|
|
7644
|
+
};
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7647
|
+
|
|
7648
|
+
function resolveGlobalApiHost(client) {
|
|
7649
|
+
if (typeof client.config != "function") return {
|
|
7650
|
+
requireGlobalPrincipal: !1
|
|
7651
|
+
};
|
|
7652
|
+
const apiHost = client.config().apiHost;
|
|
7653
|
+
if (apiHost === void 0) return {
|
|
7654
|
+
requireGlobalPrincipal: !1
|
|
7655
|
+
};
|
|
7656
|
+
let parsed;
|
|
7657
|
+
try {
|
|
7658
|
+
parsed = new URL(apiHost);
|
|
7659
|
+
} catch {
|
|
7660
|
+
return {
|
|
7661
|
+
requireGlobalPrincipal: !0
|
|
7662
|
+
};
|
|
7663
|
+
}
|
|
7664
|
+
if (/^api\.sanity\.(io|work)$/.test(parsed.hostname)) return {
|
|
7665
|
+
requireGlobalPrincipal: !1
|
|
7666
|
+
};
|
|
7667
|
+
const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
|
|
7668
|
+
return match === null ? {
|
|
7669
|
+
requireGlobalPrincipal: !0
|
|
7670
|
+
} : (parsed.hostname = `api.sanity.${match[1]}`, {
|
|
7671
|
+
apiHost: parsed.origin,
|
|
7672
|
+
requireGlobalPrincipal: !0
|
|
7673
|
+
});
|
|
7674
|
+
}
|
|
7675
|
+
|
|
7676
|
+
async function fetchGrantsCached(requestFn, resourcePath) {
|
|
7677
|
+
try {
|
|
7678
|
+
return await fetchGrants({
|
|
7679
|
+
client: {
|
|
7680
|
+
request: requestFn
|
|
7681
|
+
},
|
|
7682
|
+
resourcePath: resourcePath
|
|
7683
|
+
});
|
|
7684
|
+
} catch (err) {
|
|
7685
|
+
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: ${errorMessage(err)}`);
|
|
7686
|
+
return;
|
|
7687
|
+
}
|
|
7688
|
+
}
|
|
7689
|
+
|
|
7690
|
+
function projectIdOf(client) {
|
|
7691
|
+
if (typeof client.config != "function") return;
|
|
7692
|
+
const projectId = client.config().projectId;
|
|
7693
|
+
return typeof projectId == "string" && projectId.length > 0 ? projectId : void 0;
|
|
7694
|
+
}
|
|
7695
|
+
|
|
7696
|
+
function cachedAttributes(args) {
|
|
7697
|
+
const projectId = projectIdOf(args.client);
|
|
7698
|
+
return projectId === void 0 ? Promise.resolve(void 0) : resolveOrganizationId({
|
|
7699
|
+
client: args.client,
|
|
7700
|
+
requestFn: args.requestFn,
|
|
7701
|
+
projectId: projectId
|
|
7702
|
+
}).then(orgId => {
|
|
7703
|
+
if (orgId !== void 0) return cachedByKey({
|
|
7704
|
+
store: attributesCache,
|
|
7705
|
+
client: args.client,
|
|
7706
|
+
key: orgId,
|
|
7707
|
+
evictOnRejection: !0,
|
|
7708
|
+
load: () => fetchAttributesCached({
|
|
7709
|
+
client: args.client,
|
|
7710
|
+
orgId: orgId
|
|
7711
|
+
})
|
|
7712
|
+
});
|
|
7713
|
+
});
|
|
7714
|
+
}
|
|
7715
|
+
|
|
7716
|
+
async function resolveOrganizationId(args) {
|
|
7717
|
+
const {client: client, requestFn: requestFn, projectId: projectId} = args;
|
|
7718
|
+
return cachedByKey({
|
|
7719
|
+
store: orgIdCache,
|
|
7720
|
+
client: client,
|
|
7721
|
+
key: projectId,
|
|
7722
|
+
evictOnRejection: !0,
|
|
7723
|
+
load: async () => {
|
|
7724
|
+
try {
|
|
7725
|
+
const project = await requestFn({
|
|
7726
|
+
uri: `/projects/${encodeURIComponent(projectId)}`,
|
|
7727
|
+
tag: REQUEST_TAG.accessResolveOrg
|
|
7728
|
+
});
|
|
7729
|
+
if (!isRecord(project)) return;
|
|
7730
|
+
const orgId = project.organizationId;
|
|
7731
|
+
return typeof orgId == "string" && orgId.length > 0 ? orgId : void 0;
|
|
7732
|
+
} catch (err) {
|
|
7733
|
+
const status = httpStatusOf(err);
|
|
7734
|
+
if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
|
|
7735
|
+
throw new Error(`workflow: failed to resolve organizationId for project "${projectId}"; advisory $attributes cannot be bound. Original error: ${errorMessage(err)}`, {
|
|
7736
|
+
cause: err
|
|
7737
|
+
});
|
|
7738
|
+
}
|
|
7739
|
+
}
|
|
7740
|
+
});
|
|
7741
|
+
}
|
|
7742
|
+
|
|
7743
|
+
const ATTRIBUTES_FETCH_LIMIT = 100, EXPECTED_ATTRIBUTES_ABSENCE = /* @__PURE__ */ new Set([ 401, 402, 403, 404 ]);
|
|
7744
|
+
|
|
7745
|
+
function httpStatusOf(err) {
|
|
7746
|
+
if (!isRecord(err)) return;
|
|
7747
|
+
const status = err.statusCode;
|
|
7748
|
+
return typeof status == "number" ? status : void 0;
|
|
7749
|
+
}
|
|
7750
|
+
|
|
7751
|
+
async function fetchAttributesCached(args) {
|
|
7752
|
+
const {client: client, orgId: orgId} = args, sibling = globalHostRequestOf(client);
|
|
7753
|
+
if ("reason" in sibling) {
|
|
7754
|
+
console.warn(`workflow: skipped org attributes fetch (${sibling.reason}); advisory $attributes stays undefined (conditions referencing it fail closed).`);
|
|
7755
|
+
return;
|
|
7756
|
+
}
|
|
7757
|
+
try {
|
|
7758
|
+
const response = await sibling.request({
|
|
7759
|
+
uri: `/organizations/${encodeURIComponent(orgId)}/users/me/attributes?limit=${ATTRIBUTES_FETCH_LIMIT}`,
|
|
7760
|
+
tag: REQUEST_TAG.accessAttributes
|
|
7761
|
+
}), envelope = isRecord(response) ? response : void 0;
|
|
7762
|
+
if (envelope?.hasMore === !0) {
|
|
7763
|
+
const page = Array.isArray(envelope.attributes) ? envelope.attributes : [];
|
|
7764
|
+
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.`);
|
|
7765
|
+
}
|
|
7766
|
+
const normalized = normalizeUserAttributes(response);
|
|
7767
|
+
return normalized === void 0 && console.warn(`workflow: org attributes response for organization "${orgId}" was unusable; advisory $attributes stays undefined (conditions referencing it fail closed).`),
|
|
7768
|
+
normalized;
|
|
7769
|
+
} catch (err) {
|
|
7770
|
+
const status = httpStatusOf(err);
|
|
7771
|
+
if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
|
|
7772
|
+
throw new Error(`workflow: failed to fetch org attributes for organization "${orgId}". Original error: ${errorMessage(err)}`, {
|
|
7773
|
+
cause: err
|
|
7774
|
+
});
|
|
7775
|
+
}
|
|
7776
|
+
}
|
|
7777
|
+
|
|
7778
|
+
function callerBoundVars(args) {
|
|
7779
|
+
const vars = {
|
|
7780
|
+
...args.can !== void 0 ? {
|
|
7781
|
+
can: args.can
|
|
7782
|
+
} : {},
|
|
7783
|
+
...args.attributes !== void 0 ? {
|
|
7784
|
+
attributes: args.attributes
|
|
7785
|
+
} : {}
|
|
7786
|
+
};
|
|
7787
|
+
return Object.keys(vars).length > 0 ? vars : void 0;
|
|
7788
|
+
}
|
|
7789
|
+
|
|
7790
|
+
async function callerBoundVarsForCall(args) {
|
|
7791
|
+
const can = await advisoryCanForCall({
|
|
7792
|
+
instance: args.instance,
|
|
7793
|
+
options: args.options
|
|
7794
|
+
}), attributes = args.options?.attributes !== void 0 ? args.options.attributes : await resolveUserAttributes(args.client);
|
|
7795
|
+
return callerBoundVars({
|
|
7796
|
+
...can !== void 0 ? {
|
|
7797
|
+
can: can
|
|
7798
|
+
} : {},
|
|
7799
|
+
...attributes !== void 0 ? {
|
|
7800
|
+
attributes: attributes
|
|
7801
|
+
} : {}
|
|
7802
|
+
});
|
|
7803
|
+
}
|
|
7804
|
+
|
|
7805
|
+
function requirementDescriptor(requirement) {
|
|
7806
|
+
return {
|
|
7807
|
+
name: requirement.name,
|
|
7808
|
+
...requirement.title !== void 0 ? {
|
|
7809
|
+
title: requirement.title
|
|
7810
|
+
} : {},
|
|
7811
|
+
...requirement.description !== void 0 ? {
|
|
7812
|
+
description: requirement.description
|
|
7813
|
+
} : {}
|
|
7814
|
+
};
|
|
7815
|
+
}
|
|
7816
|
+
|
|
7817
|
+
function subjectDenialLabels(denied) {
|
|
7818
|
+
return denied.map(d => `${d.permission} on ${d.subject} (${d.resource})`);
|
|
7819
|
+
}
|
|
7820
|
+
|
|
7821
|
+
class ActionDisabledError extends WorkflowError {
|
|
7822
|
+
reason;
|
|
7823
|
+
activity;
|
|
7824
|
+
action;
|
|
7825
|
+
constructor(args) {
|
|
7826
|
+
super("action-disabled", formatDisabledReason({
|
|
7827
|
+
activity: args.activity,
|
|
7828
|
+
action: args.action,
|
|
7829
|
+
reason: args.reason
|
|
7830
|
+
})), this.name = "ActionDisabledError", this.reason = args.reason, this.activity = args.activity,
|
|
7831
|
+
this.action = args.action;
|
|
7832
|
+
}
|
|
7833
|
+
}
|
|
7834
|
+
|
|
7835
|
+
class StartNotAllowedError extends WorkflowError {
|
|
7836
|
+
definition;
|
|
7837
|
+
unmetRequirements;
|
|
7838
|
+
constructor(args) {
|
|
7839
|
+
super("start-not-allowed", `startInstance refused definition "${args.definition}": ${args.unmetRequirements.map(requirement => requirement.title ?? requirement.name).join(", ")}. Pre-flight the verdict with evaluateStart.`),
|
|
7840
|
+
this.name = "StartNotAllowedError", this.definition = args.definition, this.unmetRequirements = args.unmetRequirements;
|
|
7841
|
+
}
|
|
7842
|
+
}
|
|
7843
|
+
|
|
7844
|
+
function actionRendering(action) {
|
|
7845
|
+
const kind = action.disabledReason?.kind;
|
|
7846
|
+
return kind === "filter-failed" ? "absent" : action.triggered === !0 || kind === "cascade-fired" ? "automation" : "button";
|
|
7847
|
+
}
|
|
7848
|
+
|
|
7849
|
+
const disabledReasonDetail = {
|
|
7850
|
+
"filter-failed": r => `action filter returned false${r.detail ? ` (${r.detail})` : ""}`,
|
|
7851
|
+
"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`,
|
|
7852
|
+
"activity-not-active": r => `activity status is "${r.status}"`,
|
|
6964
7853
|
"stage-terminal": r => `stage "${r.stage}" is terminal`,
|
|
6965
7854
|
"instance-completed": r => `instance completed at ${r.completedAt}`,
|
|
6966
7855
|
"instance-aborted": r => `instance aborted at ${r.abortedAt}`,
|
|
@@ -7033,7 +7922,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
|
|
|
7033
7922
|
}
|
|
7034
7923
|
});
|
|
7035
7924
|
if (action.filter !== void 0) {
|
|
7036
|
-
const
|
|
7925
|
+
const vars = await callerBoundVarsForCall({
|
|
7926
|
+
client: ctx.client,
|
|
7037
7927
|
instance: ctx.instance,
|
|
7038
7928
|
options: options
|
|
7039
7929
|
});
|
|
@@ -7045,10 +7935,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
|
|
|
7045
7935
|
...actor !== void 0 ? {
|
|
7046
7936
|
actor: actor
|
|
7047
7937
|
} : {},
|
|
7048
|
-
...
|
|
7049
|
-
vars:
|
|
7050
|
-
can: can
|
|
7051
|
-
}
|
|
7938
|
+
...vars !== void 0 ? {
|
|
7939
|
+
vars: vars
|
|
7052
7940
|
} : {}
|
|
7053
7941
|
}
|
|
7054
7942
|
})) throw new ActionDisabledError({
|
|
@@ -8303,340 +9191,97 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
|
|
|
8303
9191
|
if (validatedOps.length === 0) throw new EffectOpsInvalidError({
|
|
8304
9192
|
effect: pending.name,
|
|
8305
9193
|
issues: [ "a mid-dispatch report must carry at least one field op — there is nothing to commit" ]
|
|
8306
|
-
});
|
|
8307
|
-
const mutation = startMutation(ctx.instance);
|
|
8308
|
-
return recordProcessedRequest({
|
|
8309
|
-
mutation: mutation,
|
|
8310
|
-
record: requestRecord,
|
|
8311
|
-
now: ctx.now
|
|
8312
|
-
}), renewClaimLease({
|
|
8313
|
-
mutation: mutation,
|
|
8314
|
-
effectKey: effectKey,
|
|
8315
|
-
now: ctx.now,
|
|
8316
|
-
leaseMs: leaseMs
|
|
8317
|
-
}), await runOps({
|
|
8318
|
-
ops: validatedOps,
|
|
8319
|
-
mutation: mutation,
|
|
8320
|
-
stage: ctx.instance.currentStage,
|
|
8321
|
-
origin: {
|
|
8322
|
-
effect: pending.name
|
|
8323
|
-
},
|
|
8324
|
-
params: pending.params,
|
|
8325
|
-
actor: ctx.actor,
|
|
8326
|
-
self: selfGdr(ctx.instance),
|
|
8327
|
-
now: ctx.now,
|
|
8328
|
-
snapshot: ctx.snapshot,
|
|
8329
|
-
refSurface: ctx.refSurface
|
|
8330
|
-
}), await persistThenMaybeRefresh({
|
|
8331
|
-
ctx: ctx,
|
|
8332
|
-
mutation: mutation,
|
|
8333
|
-
stageName: ctx.instance.currentStage,
|
|
8334
|
-
didChangeState: !0
|
|
8335
|
-
}), {
|
|
8336
|
-
effectKey: effectKey,
|
|
8337
|
-
effect: pending.name
|
|
8338
|
-
};
|
|
8339
|
-
}
|
|
8340
|
-
|
|
8341
|
-
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
8342
|
-
|
|
8343
|
-
function isResetActivityTarget(value) {
|
|
8344
|
-
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
8345
|
-
}
|
|
8346
|
-
|
|
8347
|
-
async function resetActivity(args) {
|
|
8348
|
-
const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
|
|
8349
|
-
client: client,
|
|
8350
|
-
instanceId: instanceId,
|
|
8351
|
-
options: options
|
|
8352
|
-
});
|
|
8353
|
-
return commitResetActivity({
|
|
8354
|
-
ctx: ctx,
|
|
8355
|
-
activity: activity,
|
|
8356
|
-
to: to,
|
|
8357
|
-
requestRecord: requestRecord,
|
|
8358
|
-
actor: options?.actor
|
|
8359
|
-
});
|
|
8360
|
-
}
|
|
8361
|
-
|
|
8362
|
-
async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
|
|
8363
|
-
if (assertRequestUnprocessed({
|
|
8364
|
-
instance: ctx.instance,
|
|
8365
|
-
record: requestRecord,
|
|
8366
|
-
now: ctx.now
|
|
8367
|
-
}), isTerminal(ctx)) return {
|
|
8368
|
-
fired: !1
|
|
8369
|
-
};
|
|
8370
|
-
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
8371
|
-
if (openStage2 === void 0 || entry === void 0) throw new ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
8372
|
-
const from = entry.status;
|
|
8373
|
-
if (from === to) return {
|
|
8374
|
-
fired: !1
|
|
8375
|
-
};
|
|
8376
|
-
if (!isTerminalActivityStatus(from)) throw new ContractViolationError(`resetActivity: activity "${activity}" is "${from}", not a terminal status — a reset only recovers a resolved (typically failed) activity. Use setStage to force past a live stage.`);
|
|
8377
|
-
return recordProcessedRequest({
|
|
8378
|
-
mutation: mutation,
|
|
8379
|
-
record: requestRecord,
|
|
8380
|
-
now: ctx.now
|
|
8381
|
-
}), applyActivityStatusChange({
|
|
8382
|
-
entry: entry,
|
|
8383
|
-
history: mutation.history,
|
|
8384
|
-
stage: openStage2.name,
|
|
8385
|
-
to: to,
|
|
8386
|
-
at: ctx.now,
|
|
8387
|
-
...actor !== void 0 ? {
|
|
8388
|
-
actor: actor
|
|
8389
|
-
} : {}
|
|
8390
|
-
}), await persist(ctx, mutation), {
|
|
8391
|
-
fired: !0,
|
|
8392
|
-
stage: openStage2.name,
|
|
8393
|
-
activity: activity,
|
|
8394
|
-
from: from,
|
|
8395
|
-
to: to
|
|
8396
|
-
};
|
|
8397
|
-
}
|
|
8398
|
-
|
|
8399
|
-
const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap;
|
|
8400
|
-
|
|
8401
|
-
async function resolveAccess(taggedClient, args = {}) {
|
|
8402
|
-
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
8403
|
-
if (requestFn === void 0) throw new 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).");
|
|
8404
|
-
const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
|
|
8405
|
-
client: client,
|
|
8406
|
-
requestFn: requestFn,
|
|
8407
|
-
resourcePath: args.grantsFromPath
|
|
8408
|
-
}) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
|
|
8409
|
-
if (identity === void 0) throw new ContractViolationError("workflow: failed to resolve actor from `/users/me`. The client is configured but the endpoint returned no usable identity — check the token.");
|
|
8410
|
-
return {
|
|
8411
|
-
actor: identity.actor,
|
|
8412
|
-
...identity.localPrincipalId !== void 0 ? {
|
|
8413
|
-
localPrincipalId: identity.localPrincipalId
|
|
8414
|
-
} : {},
|
|
8415
|
-
...grants !== void 0 ? {
|
|
8416
|
-
grants: grants
|
|
8417
|
-
} : {}
|
|
8418
|
-
};
|
|
8419
|
-
}
|
|
8420
|
-
|
|
8421
|
-
function cachedActor(client, requestFn) {
|
|
8422
|
-
const cached = actorCache.get(client);
|
|
8423
|
-
if (cached !== void 0) return cached;
|
|
8424
|
-
const pending = fetchActor(client, requestFn).catch(err => {
|
|
8425
|
-
throw actorCache.get(client) === pending && actorCache.delete(client), err;
|
|
8426
|
-
});
|
|
8427
|
-
return actorCache.set(client, pending), pending;
|
|
8428
|
-
}
|
|
8429
|
-
|
|
8430
|
-
function grantsForClientPath(taggedClient, resourcePath) {
|
|
8431
|
-
const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
|
|
8432
|
-
return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
|
|
8433
|
-
client: client,
|
|
8434
|
-
requestFn: requestFn,
|
|
8435
|
-
resourcePath: resourcePath
|
|
8436
|
-
});
|
|
8437
|
-
}
|
|
8438
|
-
|
|
8439
|
-
function lazyRequest(client) {
|
|
8440
|
-
return client.request === void 0 ? void 0 : opts => client.request(opts);
|
|
8441
|
-
}
|
|
8442
|
-
|
|
8443
|
-
function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
|
|
8444
|
-
let byPath = grantsCache.get(client);
|
|
8445
|
-
byPath === void 0 && (byPath = /* @__PURE__ */ new Map, grantsCache.set(client, byPath));
|
|
8446
|
-
let cached = byPath.get(resourcePath);
|
|
8447
|
-
return cached === void 0 && (cached = fetchGrantsCached(requestFn, resourcePath),
|
|
8448
|
-
byPath.set(resourcePath, cached)), cached;
|
|
8449
|
-
}
|
|
8450
|
-
|
|
8451
|
-
async function fetchActor(client, requestFn) {
|
|
8452
|
-
const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalHostId = usableId(globalUser.user), carriedId = firstCarriedGlobalId([ globalHostId, resourceId ]), sessionId = carriedId ?? globalHostId ?? resourceId;
|
|
8453
|
-
if (sessionId === void 0) return;
|
|
8454
|
-
const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
|
|
8455
|
-
client: client,
|
|
8456
|
-
sessionId: sessionId,
|
|
8457
|
-
resourceId: resourceId
|
|
8458
|
-
}) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
|
|
8459
|
-
refuseProjectScopedActor({
|
|
8460
|
-
id: id,
|
|
8461
|
-
globalUser: globalUser,
|
|
8462
|
-
globalHostId: globalHostId,
|
|
8463
|
-
bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
|
|
8464
|
-
});
|
|
8465
|
-
const roleNames = roleNamesFor(resourceUser, globalUser);
|
|
8466
|
-
return {
|
|
8467
|
-
actor: {
|
|
8468
|
-
kind: "person",
|
|
8469
|
-
id: id,
|
|
8470
|
-
...roleNames.length > 0 ? {
|
|
8471
|
-
roles: roleNames
|
|
8472
|
-
} : {}
|
|
9194
|
+
});
|
|
9195
|
+
const mutation = startMutation(ctx.instance);
|
|
9196
|
+
return recordProcessedRequest({
|
|
9197
|
+
mutation: mutation,
|
|
9198
|
+
record: requestRecord,
|
|
9199
|
+
now: ctx.now
|
|
9200
|
+
}), renewClaimLease({
|
|
9201
|
+
mutation: mutation,
|
|
9202
|
+
effectKey: effectKey,
|
|
9203
|
+
now: ctx.now,
|
|
9204
|
+
leaseMs: leaseMs
|
|
9205
|
+
}), await runOps({
|
|
9206
|
+
ops: validatedOps,
|
|
9207
|
+
mutation: mutation,
|
|
9208
|
+
stage: ctx.instance.currentStage,
|
|
9209
|
+
origin: {
|
|
9210
|
+
effect: pending.name
|
|
8473
9211
|
},
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
9212
|
+
params: pending.params,
|
|
9213
|
+
actor: ctx.actor,
|
|
9214
|
+
self: selfGdr(ctx.instance),
|
|
9215
|
+
now: ctx.now,
|
|
9216
|
+
snapshot: ctx.snapshot,
|
|
9217
|
+
refSurface: ctx.refSurface
|
|
9218
|
+
}), await persistThenMaybeRefresh({
|
|
9219
|
+
ctx: ctx,
|
|
9220
|
+
mutation: mutation,
|
|
9221
|
+
stageName: ctx.instance.currentStage,
|
|
9222
|
+
didChangeState: !0
|
|
9223
|
+
}), {
|
|
9224
|
+
effectKey: effectKey,
|
|
9225
|
+
effect: pending.name
|
|
8477
9226
|
};
|
|
8478
9227
|
}
|
|
8479
9228
|
|
|
8480
|
-
|
|
8481
|
-
return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
|
|
8482
|
-
}
|
|
8483
|
-
|
|
8484
|
-
const NO_BRIDGE = {
|
|
8485
|
-
status: "not-applicable"
|
|
8486
|
-
};
|
|
9229
|
+
const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
|
|
8487
9230
|
|
|
8488
|
-
function
|
|
8489
|
-
return
|
|
9231
|
+
function isResetActivityTarget(value) {
|
|
9232
|
+
return RESET_ACTIVITY_TARGETS.includes(value);
|
|
8490
9233
|
}
|
|
8491
9234
|
|
|
8492
|
-
async function
|
|
8493
|
-
const {client: client,
|
|
8494
|
-
return classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project" ? {
|
|
8495
|
-
status: "unavailable",
|
|
8496
|
-
reason: "no project-scoped principal from the resource host to address the directory with"
|
|
8497
|
-
} : directoryGlobalId({
|
|
9235
|
+
async function resetActivity(args) {
|
|
9236
|
+
const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
|
|
8498
9237
|
client: client,
|
|
8499
|
-
|
|
9238
|
+
instanceId: instanceId,
|
|
9239
|
+
options: options
|
|
8500
9240
|
});
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
reason: "the client reports no projectId, so its user directory has no address"
|
|
8508
|
-
};
|
|
8509
|
-
const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
|
|
8510
|
-
if (lookup.status !== "resolved") return {
|
|
8511
|
-
status: "unavailable",
|
|
8512
|
-
reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
|
|
8513
|
-
...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
|
|
8514
|
-
cause: lookup.cause
|
|
8515
|
-
} : {}
|
|
8516
|
-
};
|
|
8517
|
-
const globalId = directoryBridgeId(lookup.user.sanityUserId);
|
|
8518
|
-
return globalId === void 0 ? {
|
|
8519
|
-
status: "unavailable",
|
|
8520
|
-
reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
|
|
8521
|
-
} : {
|
|
8522
|
-
status: "resolved",
|
|
8523
|
-
globalId: globalId
|
|
8524
|
-
};
|
|
8525
|
-
}
|
|
8526
|
-
|
|
8527
|
-
function refuseProjectScopedActor(args) {
|
|
8528
|
-
const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
|
|
8529
|
-
if (classifyPrincipalId(id).namespace !== "project") return;
|
|
8530
|
-
const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
|
|
8531
|
-
bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
|
|
8532
|
-
const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
|
|
8533
|
-
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 : {
|
|
8534
|
-
cause: cause
|
|
9241
|
+
return commitResetActivity({
|
|
9242
|
+
ctx: ctx,
|
|
9243
|
+
activity: activity,
|
|
9244
|
+
to: to,
|
|
9245
|
+
requestRecord: requestRecord,
|
|
9246
|
+
actor: options?.actor
|
|
8535
9247
|
});
|
|
8536
9248
|
}
|
|
8537
9249
|
|
|
8538
|
-
function
|
|
8539
|
-
if (
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
uri: "/users/me",
|
|
8546
|
-
tag: REQUEST_TAG.accessResolveActor
|
|
8547
|
-
});
|
|
8548
|
-
} catch (err) {
|
|
8549
|
-
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.`, {
|
|
8550
|
-
cause: err
|
|
8551
|
-
});
|
|
8552
|
-
}
|
|
8553
|
-
}
|
|
8554
|
-
|
|
8555
|
-
async function fetchGlobalUser(client) {
|
|
8556
|
-
if (typeof client.withConfig != "function") return {
|
|
8557
|
-
user: void 0,
|
|
8558
|
-
reason: "the client cannot reach the global API host (no withConfig)"
|
|
8559
|
-
};
|
|
8560
|
-
let globalRequest, globalClient;
|
|
8561
|
-
const hostResolution = resolveGlobalApiHost(client);
|
|
8562
|
-
try {
|
|
8563
|
-
globalClient = client.withConfig({
|
|
8564
|
-
useProjectHostname: !1,
|
|
8565
|
-
...hostResolution.apiHost === void 0 ? {} : {
|
|
8566
|
-
apiHost: hostResolution.apiHost
|
|
8567
|
-
}
|
|
8568
|
-
}), globalRequest = lazyRequest(globalClient);
|
|
8569
|
-
} catch (err) {
|
|
8570
|
-
return {
|
|
8571
|
-
user: void 0,
|
|
8572
|
-
reason: `building the global-host sibling client failed: ${errorMessage(err)}`,
|
|
8573
|
-
cause: err
|
|
8574
|
-
};
|
|
8575
|
-
}
|
|
8576
|
-
if (globalRequest === void 0) return {
|
|
8577
|
-
user: void 0,
|
|
8578
|
-
reason: "the global-host sibling client cannot issue requests"
|
|
8579
|
-
};
|
|
8580
|
-
try {
|
|
8581
|
-
const user = await globalRequest({
|
|
8582
|
-
uri: "/users/me",
|
|
8583
|
-
tag: REQUEST_TAG.accessResolveActor
|
|
8584
|
-
}), id = usableId(user);
|
|
8585
|
-
return hostResolution.requireGlobalPrincipal && id !== void 0 && classifyPrincipalId(id).namespace === "project" ? {
|
|
8586
|
-
user: void 0,
|
|
8587
|
-
reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
|
|
8588
|
-
} : {
|
|
8589
|
-
user: user
|
|
8590
|
-
};
|
|
8591
|
-
} catch (err) {
|
|
8592
|
-
return {
|
|
8593
|
-
user: void 0,
|
|
8594
|
-
reason: `global-host /users/me failed: ${errorMessage(err)}`,
|
|
8595
|
-
cause: err
|
|
8596
|
-
};
|
|
8597
|
-
}
|
|
8598
|
-
}
|
|
8599
|
-
|
|
8600
|
-
function resolveGlobalApiHost(client) {
|
|
8601
|
-
if (typeof client.config != "function") return {
|
|
8602
|
-
requireGlobalPrincipal: !1
|
|
9250
|
+
async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
|
|
9251
|
+
if (assertRequestUnprocessed({
|
|
9252
|
+
instance: ctx.instance,
|
|
9253
|
+
record: requestRecord,
|
|
9254
|
+
now: ctx.now
|
|
9255
|
+
}), isTerminal(ctx)) return {
|
|
9256
|
+
fired: !1
|
|
8603
9257
|
};
|
|
8604
|
-
const
|
|
8605
|
-
if (
|
|
8606
|
-
|
|
9258
|
+
const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
|
|
9259
|
+
if (openStage2 === void 0 || entry === void 0) throw new ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
|
|
9260
|
+
const from = entry.status;
|
|
9261
|
+
if (from === to) return {
|
|
9262
|
+
fired: !1
|
|
8607
9263
|
};
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
9264
|
+
if (!isTerminalActivityStatus(from)) throw new ContractViolationError(`resetActivity: activity "${activity}" is "${from}", not a terminal status — a reset only recovers a resolved (typically failed) activity. Use setStage to force past a live stage.`);
|
|
9265
|
+
return recordProcessedRequest({
|
|
9266
|
+
mutation: mutation,
|
|
9267
|
+
record: requestRecord,
|
|
9268
|
+
now: ctx.now
|
|
9269
|
+
}), applyActivityStatusChange({
|
|
9270
|
+
entry: entry,
|
|
9271
|
+
history: mutation.history,
|
|
9272
|
+
stage: openStage2.name,
|
|
9273
|
+
to: to,
|
|
9274
|
+
at: ctx.now,
|
|
9275
|
+
...actor !== void 0 ? {
|
|
9276
|
+
actor: actor
|
|
9277
|
+
} : {}
|
|
9278
|
+
}), await persist(ctx, mutation), {
|
|
9279
|
+
fired: !0,
|
|
9280
|
+
stage: openStage2.name,
|
|
9281
|
+
activity: activity,
|
|
9282
|
+
from: from,
|
|
9283
|
+
to: to
|
|
8618
9284
|
};
|
|
8619
|
-
const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
|
|
8620
|
-
return match === null ? {
|
|
8621
|
-
requireGlobalPrincipal: !0
|
|
8622
|
-
} : (parsed.hostname = `api.sanity.${match[1]}`, {
|
|
8623
|
-
apiHost: parsed.origin,
|
|
8624
|
-
requireGlobalPrincipal: !0
|
|
8625
|
-
});
|
|
8626
|
-
}
|
|
8627
|
-
|
|
8628
|
-
async function fetchGrantsCached(requestFn, resourcePath) {
|
|
8629
|
-
try {
|
|
8630
|
-
return await fetchGrants({
|
|
8631
|
-
client: {
|
|
8632
|
-
request: requestFn
|
|
8633
|
-
},
|
|
8634
|
-
resourcePath: resourcePath
|
|
8635
|
-
});
|
|
8636
|
-
} catch (err) {
|
|
8637
|
-
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: ${errorMessage(err)}`);
|
|
8638
|
-
return;
|
|
8639
|
-
}
|
|
8640
9285
|
}
|
|
8641
9286
|
|
|
8642
9287
|
const REPLAY_SURFACE = {
|
|
@@ -8820,7 +9465,7 @@ async function resourceActorId(client) {
|
|
|
8820
9465
|
async function evaluateInstance(args) {
|
|
8821
9466
|
const {client: client, tag: tag, workflowResource: workflowResource, instanceId: instanceId, resourceClients: resourceClients} = args, now = (args.clock ?? wallClock)();
|
|
8822
9467
|
validateTag(tag);
|
|
8823
|
-
const [access, instance] = await Promise.all([ resolveAccess(client, {
|
|
9468
|
+
const [access, instance, attributes] = await Promise.all([ resolveAccess(client, {
|
|
8824
9469
|
...args.grantsFromPath !== void 0 ? {
|
|
8825
9470
|
grantsFromPath: args.grantsFromPath
|
|
8826
9471
|
} : {}
|
|
@@ -8828,7 +9473,7 @@ async function evaluateInstance(args) {
|
|
|
8828
9473
|
client: client,
|
|
8829
9474
|
instanceId: instanceId,
|
|
8830
9475
|
tag: tag
|
|
8831
|
-
}) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
|
|
9476
|
+
}), resolveUserAttributes(client) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
|
|
8832
9477
|
client: client,
|
|
8833
9478
|
workflowResource: workflowResource,
|
|
8834
9479
|
resourceClients: resourceClients
|
|
@@ -8853,6 +9498,9 @@ async function evaluateInstance(args) {
|
|
|
8853
9498
|
} : {},
|
|
8854
9499
|
...grants !== void 0 ? {
|
|
8855
9500
|
grants: grants
|
|
9501
|
+
} : {},
|
|
9502
|
+
...attributes !== void 0 ? {
|
|
9503
|
+
attributes: attributes
|
|
8856
9504
|
} : {}
|
|
8857
9505
|
});
|
|
8858
9506
|
}
|
|
@@ -8867,6 +9515,33 @@ function memoizedByName(render) {
|
|
|
8867
9515
|
};
|
|
8868
9516
|
}
|
|
8869
9517
|
|
|
9518
|
+
async function callerBoundProjectionScopes(args) {
|
|
9519
|
+
const can = await advisoryCan({
|
|
9520
|
+
instance: args.instance,
|
|
9521
|
+
identity: args.identity,
|
|
9522
|
+
grants: args.grants
|
|
9523
|
+
}), vars = callerBoundVars({
|
|
9524
|
+
...can !== void 0 ? {
|
|
9525
|
+
can: can
|
|
9526
|
+
} : {},
|
|
9527
|
+
...args.attributes !== void 0 ? {
|
|
9528
|
+
attributes: args.attributes
|
|
9529
|
+
} : {}
|
|
9530
|
+
}), opts = {
|
|
9531
|
+
actor: args.actor,
|
|
9532
|
+
...vars !== void 0 ? {
|
|
9533
|
+
vars: vars
|
|
9534
|
+
} : {}
|
|
9535
|
+
};
|
|
9536
|
+
return {
|
|
9537
|
+
scope: await renderConditionScope(args.scopeSource, opts),
|
|
9538
|
+
scopeForActivity: memoizedByName(activityName => renderConditionScope(args.scopeSource, {
|
|
9539
|
+
activityName: activityName,
|
|
9540
|
+
...opts
|
|
9541
|
+
}))
|
|
9542
|
+
};
|
|
9543
|
+
}
|
|
9544
|
+
|
|
8870
9545
|
function currentStageOf(instance, definition) {
|
|
8871
9546
|
try {
|
|
8872
9547
|
return findStage(definition, instance.currentStage);
|
|
@@ -8892,7 +9567,7 @@ async function explainSite(args) {
|
|
|
8892
9567
|
}
|
|
8893
9568
|
|
|
8894
9569
|
async function evaluateFromSnapshot(args) {
|
|
8895
|
-
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({
|
|
9570
|
+
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({
|
|
8896
9571
|
instance: instance,
|
|
8897
9572
|
definition: definition,
|
|
8898
9573
|
snapshot: snapshot,
|
|
@@ -8909,22 +9584,14 @@ async function evaluateFromSnapshot(args) {
|
|
|
8909
9584
|
}, anchorIdentity = lakePrincipalId({
|
|
8910
9585
|
actor: actor,
|
|
8911
9586
|
localPrincipalId: args.localPrincipalId
|
|
8912
|
-
}),
|
|
8913
|
-
|
|
8914
|
-
identity: anchorIdentity,
|
|
8915
|
-
grants: grants
|
|
8916
|
-
}), scope = await renderConditionScope(scopeSource, {
|
|
8917
|
-
actor: actor,
|
|
8918
|
-
vars: {
|
|
8919
|
-
can: can
|
|
8920
|
-
}
|
|
8921
|
-
}), scopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
|
|
8922
|
-
activityName: activityName,
|
|
9587
|
+
}), {scope: scope, scopeForActivity: scopeForActivity} = await callerBoundProjectionScopes({
|
|
9588
|
+
scopeSource: scopeSource,
|
|
8923
9589
|
actor: actor,
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
9590
|
+
instance: instance,
|
|
9591
|
+
grants: grants,
|
|
9592
|
+
attributes: attributes,
|
|
9593
|
+
identity: anchorIdentity
|
|
9594
|
+
}), cascadeScopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
|
|
8928
9595
|
activityName: activityName
|
|
8929
9596
|
})), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
|
|
8930
9597
|
instance: instance,
|
|
@@ -8973,6 +9640,7 @@ async function evaluateFromSnapshot(args) {
|
|
|
8973
9640
|
}
|
|
8974
9641
|
const currentStage = {
|
|
8975
9642
|
stage: stage,
|
|
9643
|
+
...semanticsOf(stage),
|
|
8976
9644
|
activities: activityEvaluations,
|
|
8977
9645
|
transitions: transitionEvaluations,
|
|
8978
9646
|
autonomy: stageAutonomy2
|
|
@@ -8989,6 +9657,7 @@ async function evaluateFromSnapshot(args) {
|
|
|
8989
9657
|
return {
|
|
8990
9658
|
instance: instance,
|
|
8991
9659
|
definition: definition,
|
|
9660
|
+
...semanticsOf(definition),
|
|
8992
9661
|
actor: actor,
|
|
8993
9662
|
currentStage: currentStage,
|
|
8994
9663
|
pendingOnYou: pendingOnYou,
|
|
@@ -9144,6 +9813,7 @@ async function evaluateActivity(args) {
|
|
|
9144
9813
|
}));
|
|
9145
9814
|
return {
|
|
9146
9815
|
activity: activity,
|
|
9816
|
+
...semanticsOf(activity),
|
|
9147
9817
|
status: status,
|
|
9148
9818
|
kind: deriveActivityKind(activity),
|
|
9149
9819
|
classification: deriveExecutorClassification(activity),
|
|
@@ -9314,9 +9984,13 @@ function fireableActionVerdict({args: args, insights: insights}) {
|
|
|
9314
9984
|
function actionEvaluationIdentity(action) {
|
|
9315
9985
|
return {
|
|
9316
9986
|
action: action,
|
|
9317
|
-
...action
|
|
9318
|
-
|
|
9319
|
-
|
|
9987
|
+
...semanticsOf(action)
|
|
9988
|
+
};
|
|
9989
|
+
}
|
|
9990
|
+
|
|
9991
|
+
function semanticsOf(node) {
|
|
9992
|
+
return node.semantics === void 0 ? {} : {
|
|
9993
|
+
semantics: node.semantics
|
|
9320
9994
|
};
|
|
9321
9995
|
}
|
|
9322
9996
|
|
|
@@ -9795,7 +10469,8 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
|
|
|
9795
10469
|
}
|
|
9796
10470
|
|
|
9797
10471
|
async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
|
|
9798
|
-
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site),
|
|
10472
|
+
const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), vars = await callerBoundVarsForCall({
|
|
10473
|
+
client: ctx.client,
|
|
9799
10474
|
instance: ctx.instance,
|
|
9800
10475
|
options: options
|
|
9801
10476
|
}), predicateSatisfied = window.open && site.effective !== !0 && site.effective !== void 0 ? await ctxEvaluateCondition({
|
|
@@ -9808,10 +10483,8 @@ async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
|
|
|
9808
10483
|
...actor !== void 0 ? {
|
|
9809
10484
|
actor: actor
|
|
9810
10485
|
} : {},
|
|
9811
|
-
...
|
|
9812
|
-
vars:
|
|
9813
|
-
can: can
|
|
9814
|
-
}
|
|
10486
|
+
...vars !== void 0 ? {
|
|
10487
|
+
vars: vars
|
|
9815
10488
|
} : {}
|
|
9816
10489
|
}
|
|
9817
10490
|
}) : site.effective === !0, reason = editDisabledReason({
|
|
@@ -10301,6 +10974,9 @@ function buildEngineCallOptions(args) {
|
|
|
10301
10974
|
...args.grants !== void 0 ? {
|
|
10302
10975
|
grants: args.grants
|
|
10303
10976
|
} : {},
|
|
10977
|
+
...args.attributes !== void 0 ? {
|
|
10978
|
+
attributes: args.attributes
|
|
10979
|
+
} : {},
|
|
10304
10980
|
...args.clock !== void 0 ? {
|
|
10305
10981
|
clock: args.clock
|
|
10306
10982
|
} : {},
|
|
@@ -12059,7 +12735,7 @@ function createInstanceSession(args) {
|
|
|
12059
12735
|
refSurface: evalScope.refSurface
|
|
12060
12736
|
});
|
|
12061
12737
|
}, evaluateWith = async ({held: held, guards: guards, self: self}) => {
|
|
12062
|
-
const {actor: actor, localPrincipalId: localPrincipalId, grants: grants} = await access(), resourceGrants = await subjectResourceGrants({
|
|
12738
|
+
const [{actor: actor, localPrincipalId: localPrincipalId, grants: grants}, attributes] = await Promise.all([ access(), resolveUserAttributes(client) ]), resourceGrants = await subjectResourceGrants({
|
|
12063
12739
|
clientForGdr: evalScope.clientForGdr,
|
|
12064
12740
|
instance: instance
|
|
12065
12741
|
}), normalizedSelf = await normalizeInstanceIdentities({
|
|
@@ -12081,6 +12757,9 @@ function createInstanceSession(args) {
|
|
|
12081
12757
|
} : {},
|
|
12082
12758
|
...grants !== void 0 ? {
|
|
12083
12759
|
grants: grants
|
|
12760
|
+
} : {},
|
|
12761
|
+
...attributes !== void 0 ? {
|
|
12762
|
+
attributes: attributes
|
|
12084
12763
|
} : {}
|
|
12085
12764
|
});
|
|
12086
12765
|
}, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope}) => {
|
|
@@ -12776,7 +13455,7 @@ const HISTORY_DISPLAY = {
|
|
|
12776
13455
|
},
|
|
12777
13456
|
opApplied: {
|
|
12778
13457
|
title: "Op applied",
|
|
12779
|
-
description: "An
|
|
13458
|
+
description: "An action, direct edit, or effect completion executed an operation and recorded its audit payload."
|
|
12780
13459
|
},
|
|
12781
13460
|
fieldQueryDiscarded: {
|
|
12782
13461
|
title: "Query result discarded",
|
|
@@ -12881,6 +13560,10 @@ const HISTORY_DISPLAY = {
|
|
|
12881
13560
|
title: "Set field entry",
|
|
12882
13561
|
description: "Overwrite a field entry's value with a resolved value expression."
|
|
12883
13562
|
},
|
|
13563
|
+
"field.setIfMissing": {
|
|
13564
|
+
title: "Set field entry if missing",
|
|
13565
|
+
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."
|
|
13566
|
+
},
|
|
12884
13567
|
"field.unset": {
|
|
12885
13568
|
title: "Unset field entry",
|
|
12886
13569
|
description: "Reset a field entry to its default (null for scalars, [] for array kinds)."
|
|
@@ -12889,6 +13572,14 @@ const HISTORY_DISPLAY = {
|
|
|
12889
13572
|
title: "Append to field entry",
|
|
12890
13573
|
description: "Push a resolved item onto an array-kind entry (array, assignees, doc.refs)."
|
|
12891
13574
|
},
|
|
13575
|
+
"field.inc": {
|
|
13576
|
+
title: "Increment field entry",
|
|
13577
|
+
description: "Add a resolved numeric delta, defaulting to 1, to a number entry that already holds a finite number."
|
|
13578
|
+
},
|
|
13579
|
+
"field.dec": {
|
|
13580
|
+
title: "Decrement field entry",
|
|
13581
|
+
description: "Subtract a resolved numeric delta, defaulting to 1, from a number entry that already holds a finite number."
|
|
13582
|
+
},
|
|
12892
13583
|
"field.updateWhere": {
|
|
12893
13584
|
title: "Update matching rows",
|
|
12894
13585
|
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)."
|
|
@@ -13002,4 +13693,4 @@ function displayDescription(typeKey) {
|
|
|
13002
13693
|
if (typeKey) return DISPLAY[typeKey]?.description;
|
|
13003
13694
|
}
|
|
13004
13695
|
|
|
13005
|
-
export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionTagsGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deployedTagsGroq, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, userLoginProvider, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
|
|
13696
|
+
export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DECISION_SEMANTICS, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionTagsGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deployedTagsGroq, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, documentStuckCause, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findActivityNode, findCurrentActivityEntry, findOpenStageEntry, findStageNode, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isRevisionConflict, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resolveUserAttributes, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, userLoginProvider, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
|