@sanity/workflow-engine 0.28.0 → 0.30.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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
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, 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, driverKind, EffectNotFoundError, firstCarriedGlobalId, deriveExecutorClassification, validateTag, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, DefinitionInUseError, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
1
+ import { rethrowWithContext, andConditions, deriveActivityKind, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, isAlwaysArrayFieldKind, evaluateCondition, isRecord, isSingleDocRefEntry, isAssignmentFieldEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, assignmentKindAcceptsRoles, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, classifyPrincipalId, directoryBridgeId, parseGdr, isGdrUri, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, NonEmptyString, tolerantEntries, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, 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, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, SYSTEM_IDENTITY, clientConfigFromResource, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
3
+ import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DECISION_SEMANTICS, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, PersistedDocShapeError, RESERVED_CONDITION_VARS, SIGNAL_SEMANTICS, SYSTEM_IDENTITY, 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
 
@@ -130,6 +130,9 @@ function resolveFieldSite(site, stage) {
130
130
  ...site.entry.validation !== void 0 ? {
131
131
  validation: site.entry.validation
132
132
  } : {},
133
+ ...site.entry.roles !== void 0 ? {
134
+ roles: site.entry.roles
135
+ } : {},
133
136
  ref: {
134
137
  scope: site.scope,
135
138
  field: site.entry.name
@@ -266,58 +269,58 @@ function resolveTelemetry(telemetry) {
266
269
  }
267
270
 
268
271
  const HIGH_FREQUENCY_SAMPLE_MS = 6e4, WorkflowDefinitionDeployed = defineWorkflowEvent({
269
- name: "Editorial Workflows Definition Deployed",
272
+ name: "Workflows Definition Deployed",
270
273
  version: 1,
271
274
  description: "A definition went through a deploy — status distinguishes a newly minted version from an unchanged redeploy"
272
275
  }), WorkflowInstanceStarted = defineWorkflowEvent({
273
- name: "Editorial Workflows Instance Started",
276
+ name: "Workflows Instance Started",
274
277
  version: 1,
275
278
  description: "A workflow instance was started from a deployed definition"
276
279
  }), WorkflowStageTransitioned = defineWorkflowEvent({
277
- name: "Editorial Workflows Stage Transitioned",
280
+ name: "Workflows Stage Transitioned",
278
281
  version: 1,
279
282
  description: "A committed stage move — one event per hop, cascades included, whichever verb drove it. Unsampled: funnel and dwell reads need complete counts, and volume is bounded by actual movement"
280
283
  }), WorkflowActionFired = defineWorkflowEvent({
281
- name: "Editorial Workflows Action Fired",
284
+ name: "Workflows Action Fired",
282
285
  version: 1,
283
286
  description: "An action was fired against an activity"
284
287
  }), WorkflowFieldEdited = defineWorkflowEvent({
285
- name: "Editorial Workflows Field Edited",
288
+ name: "Workflows Field Edited",
286
289
  version: 1,
287
290
  description: "A declared-editable field was edited through the generic edit seam",
288
291
  maxSampleRate: HIGH_FREQUENCY_SAMPLE_MS
289
292
  }), WorkflowInstanceTicked = defineWorkflowEvent({
290
- name: "Editorial Workflows Instance Ticked",
293
+ name: "Workflows Instance Ticked",
291
294
  version: 1,
292
295
  description: "An instance was re-evaluated for auto-transitions and due waits",
293
296
  maxSampleRate: HIGH_FREQUENCY_SAMPLE_MS
294
297
  }), WorkflowEffectsDrained = defineWorkflowEvent({
295
- name: "Editorial Workflows Effects Drained",
298
+ name: "Workflows Effects Drained",
296
299
  version: 1,
297
300
  description: "A drain pass ran — drainedCount/drainedEffects report the successful dispatches. Unsampled when non-empty (outcome counts must be complete; volume is bounded by real effect work); empty polls are machine-cadence noise, throttled engine-side to at most one per minute"
298
301
  }), WorkflowEffectStateReported = defineWorkflowEvent({
299
- name: "Editorial Workflows Effect State Reported",
302
+ name: "Workflows Effect State Reported",
300
303
  version: 1,
301
304
  description: "A running effect handler committed mid-dispatch field state through commitEffectOps. Sampled (high-frequency by design — a dispatch may report many times): an adoption and usage signal, not an exact per-run report count",
302
305
  maxSampleRate: HIGH_FREQUENCY_SAMPLE_MS
303
306
  }), WorkflowEffectCompleted = defineWorkflowEvent({
304
- name: "Editorial Workflows Effect Completed",
307
+ name: "Workflows Effect Completed",
305
308
  version: 1,
306
- description: "An effect outcome was recorded — reported directly through completeEffect, or cancelled by the abort verb (external runtimes; engine-drained effects surface via Editorial Workflows Effects Drained instead — each outcome counts once)"
309
+ description: "An effect outcome was recorded — reported directly through completeEffect, or cancelled by the abort verb (external runtimes; engine-drained effects surface via Workflows Effects Drained instead — each outcome counts once)"
307
310
  }), WorkflowInstanceAborted = defineWorkflowEvent({
308
- name: "Editorial Workflows Instance Aborted",
311
+ name: "Workflows Instance Aborted",
309
312
  version: 1,
310
313
  description: "The abort admin override was invoked (changed: false = instance already terminal)"
311
314
  }), WorkflowStageSet = defineWorkflowEvent({
312
- name: "Editorial Workflows Stage Set",
315
+ name: "Workflows Stage Set",
313
316
  version: 1,
314
317
  description: "The set-stage admin override was invoked (changed: false = already at the target stage)"
315
318
  }), WorkflowActivityReset = defineWorkflowEvent({
316
- name: "Editorial Workflows Activity Reset",
319
+ name: "Workflows Activity Reset",
317
320
  version: 1,
318
321
  description: "The reset-activity admin override was invoked (changed: false = already at the target status, or the instance was terminal)"
319
322
  }), WorkflowDefinitionDeleted = defineWorkflowEvent({
320
- name: "Editorial Workflows Definition Deleted",
323
+ name: "Workflows Definition Deleted",
321
324
  version: 1,
322
325
  description: "A deployed definition (or one version of it) was removed via the admin verb"
323
326
  });
@@ -435,240 +438,6 @@ function fieldEditedData(args) {
435
438
  };
436
439
  }
437
440
 
438
- const DATA_MODEL_VERSION = 5, 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 a closed bag of 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
- }) ]);
538
-
539
- function recordOf(value) {
540
- return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
541
- }
542
-
543
- function recordsAt(record, key) {
544
- const value = record[key];
545
- return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
546
- }
547
-
548
- function nestedFieldEntries(entries) {
549
- return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
550
- }
551
-
552
- function parsedDefinitionSnapshot(root) {
553
- if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
554
- _id: typeof root._id == "string" ? root._id : "<unknown instance>",
555
- definitionSnapshot: root.definitionSnapshot
556
- }));
557
- }
558
-
559
- function persistedFieldEntries(document) {
560
- const root = recordOf(document);
561
- if (root === void 0) return [];
562
- const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], stages = roots.flatMap(candidate => recordsAt(candidate, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions")), effects = actions.flatMap(action => recordsAt(action, "effects"));
563
- 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")) ]);
564
- }
565
-
566
- function hasChoiceList(document) {
567
- return persistedFieldEntries(document).some(entry => {
568
- const options = recordOf(entry.options);
569
- return options !== void 0 && Array.isArray(options.list);
570
- });
571
- }
572
-
573
- function hasFieldKind(document, kind) {
574
- return persistedFieldEntries(document).some(entry => entry.type === kind || entry._type === kind);
575
- }
576
-
577
- function hasActionSemantics(document) {
578
- const root = recordOf(document);
579
- return root === void 0 ? !1 : recordsAt(root, "stages").flatMap(stage => recordsAt(stage, "activities")).flatMap(activity => recordsAt(activity, "actions")).some(action => Array.isArray(action.semantics));
580
- }
581
-
582
- function hasScalarValidation(document) {
583
- return persistedFieldEntries(document).some(entry => {
584
- const validation = recordOf(entry.validation);
585
- return typeof validation?.min == "number" || typeof validation?.max == "number";
586
- });
587
- }
588
-
589
- function hasClaimTokens(document) {
590
- const root = recordOf(document);
591
- return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
592
- const claim = recordOf(entry.claim);
593
- return claim !== void 0 && typeof claim.claimToken == "string";
594
- });
595
- }
596
-
597
- function hasReadinessRequirements(document) {
598
- const root = recordOf(document);
599
- 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)));
600
- }
601
-
602
- const featureDetectors = {
603
- "governed-model-stamps": () => !0,
604
- "subject-field-kind": document => hasFieldKind(document, "subject"),
605
- "typed-scalar-choice-lists": hasChoiceList,
606
- "action-semantics": hasActionSemantics,
607
- "inclusive-scalar-bounds": hasScalarValidation,
608
- "progress-field-kind": document => hasFieldKind(document, "progress"),
609
- "effect-claim-tokens": hasClaimTokens,
610
- "classified-principal-ids": () => !0,
611
- "readiness-requirements": hasReadinessRequirements,
612
- "due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime")
613
- };
614
-
615
- function requiredModelFeatures(documentType, document) {
616
- return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
617
- }
618
-
619
- function requiredReaderModel(documentType, document) {
620
- return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
621
- }
622
-
623
- function modelStampFor(args) {
624
- return {
625
- modelVersion: DATA_MODEL_VERSION,
626
- minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
627
- };
628
- }
629
-
630
- function fieldTreeShape(value) {
631
- if (Array.isArray(value)) return value.map(fieldTreeShape);
632
- if (value === null) return "null";
633
- if (typeof value == "object") {
634
- const record = value;
635
- return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
636
- }
637
- return typeof value;
638
- }
639
-
640
- function modelVersionOf(doc) {
641
- const stamp = doc.modelVersion;
642
- return typeof stamp == "number" ? stamp : 0;
643
- }
644
-
645
- function minReaderModelOf(doc) {
646
- const floor = doc.minReaderModel;
647
- return typeof floor == "number" ? floor : modelVersionOf(doc);
648
- }
649
-
650
- class ModelVersionAheadError extends WorkflowError {
651
- documentId;
652
- documentModelVersion;
653
- requiredReaderModel;
654
- engineModelVersion;
655
- constructor(args) {
656
- 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.`),
657
- this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
658
- this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
659
- }
660
- }
661
-
662
- function assertReadableModel(doc) {
663
- const documentReaderModel = minReaderModelOf(doc);
664
- if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
665
- documentId: doc._id,
666
- documentModelVersion: modelVersionOf(doc),
667
- requiredReaderModel: documentReaderModel
668
- });
669
- return doc;
670
- }
671
-
672
441
  function effectSites(def) {
673
442
  const sites = [];
674
443
  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({
@@ -1143,12 +912,8 @@ function renderWorkflowRead(read, ctx) {
1143
912
  text: guillemets(title)
1144
913
  });
1145
914
  }
1146
- if (read.variable === "can" && typeof read.path[0] == "string") return phrase("read.permission", {
1147
- params: {
1148
- permission: read.path[0]
1149
- },
1150
- text: `your ${read.path[0]} permission`
1151
- });
915
+ const keyed = keyedCallerRead(read);
916
+ if (keyed !== void 0) return keyed;
1152
917
  if (read.variable === "actor" && read.path.length === 1 && read.path[0] === "id") return phrase("read.actor-id", {
1153
918
  params: {},
1154
919
  text: "your id"
@@ -1170,6 +935,24 @@ function renderWorkflowRead(read, ctx) {
1170
935
  });
1171
936
  }
1172
937
 
938
+ function keyedCallerRead(read) {
939
+ const key = read.path[0];
940
+ if (typeof key == "string") {
941
+ if (read.variable === "can") return phrase("read.permission", {
942
+ params: {
943
+ permission: key
944
+ },
945
+ text: `your ${key} permission`
946
+ });
947
+ if (read.variable === "attributes") return phrase("read.attribute", {
948
+ params: {
949
+ attribute: key
950
+ },
951
+ text: `your ${guillemets(key)} attribute`
952
+ });
953
+ }
954
+ }
955
+
1173
956
  function workflowRequirement(requirement, ctx) {
1174
957
  const {target: target} = requirement, clause = clauseVarRequirement(requirement);
1175
958
  if (clause !== void 0) return clause;
@@ -2597,7 +2380,7 @@ class CascadeLimitError extends WorkflowError {
2597
2380
  }
2598
2381
  }
2599
2382
 
2600
- const FIELD_OP_TYPES = [ "field.set", "field.unset", "field.append", "field.updateWhere", "field.removeWhere" ];
2383
+ const FIELD_OP_TYPES = [ "field.set", "field.setIfMissing", "field.unset", "field.append", "field.inc", "field.dec", "field.updateWhere", "field.removeWhere" ];
2601
2384
 
2602
2385
  function isFieldOp(summary) {
2603
2386
  return FIELD_OP_TYPES.includes(summary.opType);
@@ -2605,38 +2388,7 @@ function isFieldOp(summary) {
2605
2388
 
2606
2389
  function validateActionParams({action: action, activityName: activityName, callerParams: callerParams}) {
2607
2390
  const declared = action.params ?? [], params = callerParams ?? {}, issues = [];
2608
- for (const decl of declared) {
2609
- const value = params[decl.name], present = decl.name in params && value !== void 0 && value !== null;
2610
- if (decl.required === !0 && !present) {
2611
- issues.push({
2612
- param: decl.name,
2613
- reason: "required but missing"
2614
- });
2615
- continue;
2616
- }
2617
- if (!present) continue;
2618
- if (!checkParamType(value, decl)) {
2619
- issues.push({
2620
- param: decl.name,
2621
- reason: `expected type=${decl.type}, got ${typeof value}`
2622
- });
2623
- continue;
2624
- }
2625
- const choiceIssues = choiceValueIssues(decl.options, value);
2626
- choiceIssues !== void 0 && issues.push({
2627
- param: decl.name,
2628
- reason: choiceIssues.join("; ")
2629
- });
2630
- const validationIssues = scalarValidationIssues({
2631
- entryType: decl.type,
2632
- validation: decl.validation,
2633
- value: value
2634
- });
2635
- validationIssues !== void 0 && issues.push({
2636
- param: decl.name,
2637
- reason: validationIssues.join("; ")
2638
- });
2639
- }
2391
+ for (const decl of declared) issues.push(...declaredParamIssues(decl, params));
2640
2392
  if (issues.length > 0) throw new ActionParamsInvalidError({
2641
2393
  action: action.name,
2642
2394
  activity: activityName,
@@ -2645,6 +2397,30 @@ function validateActionParams({action: action, activityName: activityName, calle
2645
2397
  return params;
2646
2398
  }
2647
2399
 
2400
+ function declaredParamIssues(decl, params) {
2401
+ const value = params[decl.name];
2402
+ if (!(decl.name in params && value !== void 0 && value !== null)) return decl.required === !0 ? [ {
2403
+ param: decl.name,
2404
+ reason: "required but missing"
2405
+ } ] : [];
2406
+ if (!checkParamType(value, decl)) return [ {
2407
+ param: decl.name,
2408
+ reason: `expected type=${decl.type}, got ${typeof value}`
2409
+ } ];
2410
+ const choiceIssues = choiceValueIssues(decl.options, value), validationIssues = scalarValidationIssues({
2411
+ entryType: decl.type,
2412
+ validation: decl.validation,
2413
+ value: value
2414
+ });
2415
+ return [ ...choiceIssues === void 0 ? [] : [ {
2416
+ param: decl.name,
2417
+ reason: choiceIssues.join("; ")
2418
+ } ], ...validationIssues === void 0 ? [] : [ {
2419
+ param: decl.name,
2420
+ reason: validationIssues.join("; ")
2421
+ } ] ];
2422
+ }
2423
+
2648
2424
  function hasStringField(value, field) {
2649
2425
  return typeof value == "object" && value !== null && field in value && typeof value[field] == "string";
2650
2426
  }
@@ -2696,9 +2472,11 @@ async function runOps(args) {
2696
2472
  now: now,
2697
2473
  snapshot: snapshot,
2698
2474
  refSurface: refSurface,
2699
- opsFromDefinition: opsFromDefinition
2475
+ opsFromDefinition: opsFromDefinition,
2476
+ memberRoles: args.memberRoles,
2477
+ roleAliases: args.roleAliases
2700
2478
  });
2701
- summaries.push(summary), mutation.history.push(opAppliedEntry({
2479
+ summaries.push(summary), shouldRecordOpApplied(summary) && mutation.history.push(opAppliedEntry({
2702
2480
  origin: origin,
2703
2481
  summary: summary,
2704
2482
  stage: stage,
@@ -2709,6 +2487,10 @@ async function runOps(args) {
2709
2487
  return summaries;
2710
2488
  }
2711
2489
 
2490
+ function shouldRecordOpApplied(summary) {
2491
+ return summary.opType !== "field.setIfMissing" || summary.resolved !== void 0;
2492
+ }
2493
+
2712
2494
  function opAppliedEntry(args) {
2713
2495
  const {origin: origin, summary: summary, stage: stage, actor: actor, now: now} = args;
2714
2496
  return {
@@ -2780,12 +2562,19 @@ async function applyOp(op, ctx) {
2780
2562
  case "field.set":
2781
2563
  return applyFieldSet(op, ctx);
2782
2564
 
2565
+ case "field.setIfMissing":
2566
+ return applyFieldSetIfMissing(op, ctx);
2567
+
2783
2568
  case "field.unset":
2784
2569
  return applyFieldUnset(op, ctx);
2785
2570
 
2786
2571
  case "field.append":
2787
2572
  return applyFieldAppend(op, ctx);
2788
2573
 
2574
+ case "field.inc":
2575
+ case "field.dec":
2576
+ return applyFieldArithmetic(op, ctx);
2577
+
2789
2578
  case "field.updateWhere":
2790
2579
  return applyFieldUpdateWhere(op, ctx);
2791
2580
 
@@ -2806,7 +2595,12 @@ function applyFieldSet(op, ctx) {
2806
2595
  entryType: entry._type,
2807
2596
  entryName: entry.name,
2808
2597
  value: value,
2809
- ...entryShape(entry)
2598
+ ...entryShape(entry),
2599
+ memberRoles: ctx.memberRoles,
2600
+ roleAliases: ctx.roleAliases,
2601
+ ...entry._type === "assignees" || entry._type === "object" || entry._type === "array" ? {
2602
+ previousValue: entry.value
2603
+ } : {}
2810
2604
  });
2811
2605
  return assertRuntimeRefsWithinSurface({
2812
2606
  entryType: entry._type,
@@ -2824,6 +2618,78 @@ function applyFieldSet(op, ctx) {
2824
2618
  };
2825
2619
  }
2826
2620
 
2621
+ function applyFieldSetIfMissing(op, ctx) {
2622
+ const entry = locateEntry(ctx, op.target);
2623
+ return isAlwaysArrayFieldKind(entry._type) && rejectFieldOpTarget({
2624
+ entry: entry,
2625
+ op: op,
2626
+ issue: "is always array-valued — setIfMissing applies to nullable entries only; an empty array entry already holds []"
2627
+ }), entry.value !== null && entry.value !== void 0 ? {
2628
+ opType: op.type,
2629
+ target: op.target
2630
+ } : {
2631
+ ...applyFieldSet({
2632
+ ...op,
2633
+ type: "field.set"
2634
+ }, ctx),
2635
+ opType: op.type
2636
+ };
2637
+ }
2638
+
2639
+ function applyFieldArithmetic(op, ctx) {
2640
+ const entry = locateEntry(ctx, op.target);
2641
+ entry._type !== "number" && rejectFieldOpTarget({
2642
+ entry: entry,
2643
+ op: op,
2644
+ issue: `is a ${entry._type} entry — arithmetic ops target \`number\` entries only`
2645
+ }), typeof entry.value != "number" && rejectFieldOpTarget({
2646
+ entry: entry,
2647
+ op: op,
2648
+ issue: "has no numeric value — initialize it before applying arithmetic"
2649
+ });
2650
+ const resolvedDelta = op.value === void 0 ? 1 : resolveOpValue({
2651
+ src: op.value,
2652
+ ctx: ctx,
2653
+ target: {
2654
+ kind: "number"
2655
+ }
2656
+ });
2657
+ (typeof resolvedDelta != "number" || !Number.isFinite(resolvedDelta)) && rejectFieldOpTarget({
2658
+ entry: entry,
2659
+ op: op,
2660
+ issue: "value must resolve to a finite number"
2661
+ });
2662
+ const nextValue = entry.value + (op.type === "field.inc" ? resolvedDelta : -resolvedDelta);
2663
+ Number.isFinite(nextValue) || rejectFieldOpTarget({
2664
+ entry: entry,
2665
+ op: op,
2666
+ issue: "result must be a finite number"
2667
+ });
2668
+ const value = validateFieldValue({
2669
+ entryType: entry._type,
2670
+ entryName: entry.name,
2671
+ value: nextValue,
2672
+ ...entryShape(entry)
2673
+ });
2674
+ return setEntryValue(entry, value), {
2675
+ opType: op.type,
2676
+ target: op.target,
2677
+ resolved: {
2678
+ value: value
2679
+ }
2680
+ };
2681
+ }
2682
+
2683
+ function rejectFieldOpTarget(args) {
2684
+ const {entry: entry, op: op, issue: issue} = args;
2685
+ throw new FieldValueShapeError({
2686
+ entryType: entry._type,
2687
+ entryName: entry.name,
2688
+ mode: "value",
2689
+ issues: [ `${op.type} target ${op.target.scope}:"${op.target.field}" ${issue}` ]
2690
+ });
2691
+ }
2692
+
2827
2693
  function entryShape(entry) {
2828
2694
  return entry._type === "object" ? {
2829
2695
  fields: entry.fields
@@ -2831,7 +2697,17 @@ function entryShape(entry) {
2831
2697
  of: entry.of
2832
2698
  } : isSingleDocRefEntry(entry) || entry._type === "doc.refs" ? entry.types !== void 0 ? {
2833
2699
  types: entry.types
2834
- } : {} : {
2700
+ } : {} : isAssignmentFieldEntry(entry) ? assignmentEntryShape(entry) : scalarEntryShape(entry);
2701
+ }
2702
+
2703
+ function assignmentEntryShape(entry) {
2704
+ return entry.roles !== void 0 ? {
2705
+ roles: entry.roles
2706
+ } : {};
2707
+ }
2708
+
2709
+ function scalarEntryShape(entry) {
2710
+ return {
2835
2711
  ...entry.options !== void 0 ? {
2836
2712
  options: entry.options
2837
2713
  } : {},
@@ -2859,15 +2735,9 @@ function appendItemSlot(entry) {
2859
2735
  };
2860
2736
  }
2861
2737
 
2862
- const EMPTY_BY_KIND = {
2863
- "doc.refs": [],
2864
- array: [],
2865
- assignees: []
2866
- };
2867
-
2868
2738
  function applyFieldUnset(op, ctx) {
2869
2739
  const entry = locateEntry(ctx, op.target);
2870
- return setEntryValue(entry, EMPTY_BY_KIND[entry._type] ?? null), {
2740
+ return setEntryValue(entry, isAlwaysArrayFieldKind(entry._type) ? [] : null), {
2871
2741
  opType: op.type,
2872
2742
  target: op.target
2873
2743
  };
@@ -2885,7 +2755,10 @@ function applyFieldAppend(op, ctx) {
2885
2755
  entryName: entry.name,
2886
2756
  item: item,
2887
2757
  types: entry._type === "doc.refs" ? entry.types : void 0,
2888
- of: entry._type === "array" ? entry.of : void 0
2758
+ of: entry._type === "array" ? entry.of : void 0,
2759
+ roles: entry._type === "assignees" ? entry.roles : void 0,
2760
+ memberRoles: ctx.memberRoles,
2761
+ roleAliases: ctx.roleAliases
2889
2762
  });
2890
2763
  assertRuntimeRefsWithinSurface({
2891
2764
  entryType: entry._type === "doc.refs" ? "doc.ref" : "object",
@@ -2906,7 +2779,7 @@ function applyFieldAppend(op, ctx) {
2906
2779
  }
2907
2780
 
2908
2781
  function withRowKey(item) {
2909
- return typeof item == "object" && item !== null && !Array.isArray(item) && !("_key" in item) ? {
2782
+ return isRecord(item) && !("_key" in item) ? {
2910
2783
  _key: randomKey(),
2911
2784
  ...item
2912
2785
  } : item;
@@ -2933,6 +2806,13 @@ async function applyFieldUpdateWhere(op, ctx) {
2933
2806
  merge: mergeRecord,
2934
2807
  entry: entry,
2935
2808
  op: op
2809
+ }), validateFieldValue({
2810
+ entryType: "array",
2811
+ entryName: entry.name,
2812
+ value: [ mergeRecord ],
2813
+ of: entry.of,
2814
+ memberRoles: ctx.memberRoles,
2815
+ roleAliases: ctx.roleAliases
2936
2816
  });
2937
2817
  const matches = await rowMatches({
2938
2818
  where: op.where,
@@ -3049,18 +2929,6 @@ function subSlot(target, field) {
3049
2929
  function resolveOpValue(args) {
3050
2930
  const {src: src, ctx: ctx, target: target} = args;
3051
2931
  switch (src.type) {
3052
- case "literal":
3053
- case "param":
3054
- case "actor":
3055
- case "now":
3056
- return resolveStaticValueExpr(src, ctx);
3057
-
3058
- case "self":
3059
- return ctx.self;
3060
-
3061
- case "stage":
3062
- return ctx.stage;
3063
-
3064
2932
  case "fieldRead":
3065
2933
  {
3066
2934
  const entry = readEntryFromMutation(ctx, src);
@@ -3090,6 +2958,25 @@ function resolveOpValue(args) {
3090
2958
  }
3091
2959
  return out;
3092
2960
  }
2961
+
2962
+ default:
2963
+ return resolveAtomicOpValue(src, ctx);
2964
+ }
2965
+ }
2966
+
2967
+ function resolveAtomicOpValue(src, ctx) {
2968
+ switch (src.type) {
2969
+ case "literal":
2970
+ case "param":
2971
+ case "actor":
2972
+ case "now":
2973
+ return resolveStaticValueExpr(src, ctx);
2974
+
2975
+ case "self":
2976
+ return ctx.self;
2977
+
2978
+ case "stage":
2979
+ return ctx.stage;
3093
2980
  }
3094
2981
  }
3095
2982
 
@@ -3540,69 +3427,418 @@ async function assertInstanceWriteAllowed(args) {
3540
3427
  });
3541
3428
  }
3542
3429
 
3543
- async function renderConditionScope(source, opts) {
3544
- const {instance: instance, definition: definition, snapshot: snapshot, now: now} = source, base = buildParams({
3545
- instance: instance,
3546
- now: now,
3547
- snapshot: snapshot
3548
- }), fields = {
3549
- ...base.fields,
3550
- ...scopedFieldOverlay({
3551
- instance: instance,
3552
- snapshot: snapshot,
3553
- activityName: opts?.activityName
3554
- })
3555
- }, params = {
3556
- ...base,
3557
- fields: fields,
3558
- actor: opts?.actor,
3559
- assigned: opts?.activityName !== void 0 ? assignedFor({
3560
- instance: instance,
3561
- activityName: opts.activityName,
3562
- actor: opts?.actor,
3563
- roleAliases: definition.roleAliases
3564
- }) : !1,
3565
- ...opts?.vars
3566
- };
3567
- return {
3568
- ...await evaluatePredicates({
3569
- predicates: definition.predicates,
3570
- snapshot: snapshot,
3571
- params: params
3572
- }),
3573
- ...params
3574
- };
3575
- }
3430
+ const DATA_MODEL_VERSION = 8, DATA_MODEL_MIN_READER = 4, DATA_MODEL_MAX_READER = 8, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
3576
3431
 
3577
- function definitionLookupGroq(explicit) {
3578
- const scoped = `_type == "${WORKFLOW_DEFINITION_TYPE}" && name == $definition && ${tagScopeFilter()}`;
3579
- return explicit ? `*[${scoped} && version == $version][0]` : `*[${scoped}] | order(version desc)[0]`;
3432
+ class ReaderModelAcknowledgementError extends WorkflowError {
3433
+ code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
3434
+ expectedMinReaderModel;
3435
+ requiredMinReaderModel;
3436
+ engineMinReaderModel=DATA_MODEL_MIN_READER;
3437
+ engineMaxReaderModel=DATA_MODEL_MAX_READER;
3438
+ engineModelVersion=DATA_MODEL_VERSION;
3439
+ documentationUrl=READER_MODEL_ROLLOUT_URL;
3440
+ constructor(expectedMinReaderModel, options = {}) {
3441
+ const {context: context = "Deployment", requiredMinReaderModel: requiredMinReaderModel = DATA_MODEL_MIN_READER} = options, expected = expectedMinReaderModel === void 0 ? "missing" : String(expectedMinReaderModel);
3442
+ super("reader-model-acknowledgement", `${context} acknowledges reader model ${expected}; the submitted definitions require at least ${requiredMinReaderModel}, and this writer supports acknowledgements through ${DATA_MODEL_MAX_READER}.\nUse a reviewed numeric literal in that range. Before raising it, ensure every runtime sharing the workflow resource can read the required model.\nRollout guide: ${READER_MODEL_ROLLOUT_URL}`),
3443
+ this.name = "ReaderModelAcknowledgementError", this.expectedMinReaderModel = expectedMinReaderModel,
3444
+ this.requiredMinReaderModel = requiredMinReaderModel;
3445
+ }
3580
3446
  }
3581
3447
 
3582
- function definitionsListGroq(versionOrder) {
3583
- return `*[_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}] | order(name asc, version ${versionOrder})`;
3448
+ function assertReaderModelAcknowledgement(expectedMinReaderModel, options) {
3449
+ const {context: context, requiredMinReaderModel: requiredMinReaderModel} = options;
3450
+ if (typeof expectedMinReaderModel != "number" || !Number.isFinite(expectedMinReaderModel) || !Number.isInteger(expectedMinReaderModel) || expectedMinReaderModel < 0 || expectedMinReaderModel < requiredMinReaderModel || expectedMinReaderModel > DATA_MODEL_MAX_READER) throw new ReaderModelAcknowledgementError(expectedMinReaderModel, {
3451
+ requiredMinReaderModel: requiredMinReaderModel,
3452
+ ...context !== void 0 ? {
3453
+ context: context
3454
+ } : {}
3455
+ });
3584
3456
  }
3585
3457
 
3586
- function latestDefinitionsGroq() {
3587
- const scoped = `_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}`;
3588
- return `*[${scoped} && version == math::max(*[${scoped} && name == ^.name].version)] | order(name asc)`;
3458
+ const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
3459
+ id: "governed-model-stamps",
3460
+ introducedInModel: 1,
3461
+ minReaderModel: 0,
3462
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3463
+ compatibility: "additive",
3464
+ applicability: "unconditional",
3465
+ summary: "Definition and instance documents carry model provenance and reader-floor stamps."
3466
+ }), Object.freeze({
3467
+ id: "subject-field-kind",
3468
+ introducedInModel: 2,
3469
+ minReaderModel: 0,
3470
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3471
+ compatibility: "additive",
3472
+ applicability: "detectable",
3473
+ summary: "A workflow-level subject field identifies the document a workflow is about."
3474
+ }), Object.freeze({
3475
+ id: "typed-scalar-choice-lists",
3476
+ introducedInModel: 2,
3477
+ minReaderModel: 2,
3478
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3479
+ compatibility: "reader-floor",
3480
+ applicability: "detectable",
3481
+ summary: "Scalar fields may constrain writes to a persisted typed choice list."
3482
+ }), Object.freeze({
3483
+ id: "action-semantics",
3484
+ introducedInModel: 2,
3485
+ minReaderModel: 0,
3486
+ documentTypes: Object.freeze([ "definition" ]),
3487
+ compatibility: "additive",
3488
+ applicability: "detectable",
3489
+ summary: "Ordinary actions may carry advisory workflow semantics."
3490
+ }), Object.freeze({
3491
+ id: "inclusive-scalar-bounds",
3492
+ introducedInModel: 2,
3493
+ minReaderModel: 2,
3494
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3495
+ compatibility: "reader-floor",
3496
+ applicability: "detectable",
3497
+ summary: "String, text, and number values may carry persisted inclusive bounds."
3498
+ }), Object.freeze({
3499
+ id: "progress-field-kind",
3500
+ introducedInModel: 3,
3501
+ minReaderModel: 0,
3502
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3503
+ compatibility: "additive",
3504
+ applicability: "detectable",
3505
+ summary: "A progress field kind carries application-defined 0–100 completion."
3506
+ }), Object.freeze({
3507
+ id: "effect-claim-tokens",
3508
+ introducedInModel: 3,
3509
+ minReaderModel: 0,
3510
+ documentTypes: Object.freeze([ "instance" ]),
3511
+ compatibility: "additive",
3512
+ applicability: "detectable",
3513
+ summary: "Pending-effect claims carry an exact-claim token gating mid-dispatch state reports."
3514
+ }), Object.freeze({
3515
+ id: "classified-principal-ids",
3516
+ introducedInModel: 4,
3517
+ minReaderModel: 4,
3518
+ documentTypes: Object.freeze([ "instance" ]),
3519
+ compatibility: "reader-floor",
3520
+ applicability: "unconditional",
3521
+ 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."
3522
+ }), Object.freeze({
3523
+ id: "readiness-requirements",
3524
+ introducedInModel: 4,
3525
+ minReaderModel: 4,
3526
+ documentTypes: Object.freeze([ "definition" ]),
3527
+ compatibility: "reader-floor",
3528
+ applicability: "detectable",
3529
+ summary: "Start and activity readiness use named polymorphic requirement arrays."
3530
+ }), Object.freeze({
3531
+ id: "due-date-field-kinds",
3532
+ introducedInModel: 5,
3533
+ minReaderModel: 0,
3534
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3535
+ compatibility: "additive",
3536
+ applicability: "detectable",
3537
+ summary: "Due-date field kinds (dueDate, dueDatetime) mark a level deadline, elevated aliases of date/datetime carrying the same stored value."
3538
+ }), Object.freeze({
3539
+ id: "node-semantics",
3540
+ introducedInModel: 6,
3541
+ minReaderModel: 0,
3542
+ documentTypes: Object.freeze([ "definition" ]),
3543
+ compatibility: "additive",
3544
+ applicability: "detectable",
3545
+ summary: "Workflow, stage, activity, and action nodes may carry signal or custom advisory semantics."
3546
+ }), Object.freeze({
3547
+ id: "field-patch-ops",
3548
+ introducedInModel: 6,
3549
+ minReaderModel: 0,
3550
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3551
+ compatibility: "additive",
3552
+ applicability: "detectable",
3553
+ summary: "Field ops may increment, decrement, or initialize a missing field value."
3554
+ }), Object.freeze({
3555
+ id: "attributes-condition-var",
3556
+ introducedInModel: 7,
3557
+ minReaderModel: 0,
3558
+ documentTypes: Object.freeze([ "definition" ]),
3559
+ compatibility: "additive",
3560
+ applicability: "unconditional",
3561
+ summary: "Caller-bound $attributes condition variable binds the acting token's org-level User Attributes (advisory; absent when unavailable)."
3562
+ }), Object.freeze({
3563
+ id: "role-constrained-assignment-fields",
3564
+ introducedInModel: 8,
3565
+ minReaderModel: 8,
3566
+ documentTypes: Object.freeze([ "definition", "instance" ]),
3567
+ compatibility: "reader-floor",
3568
+ applicability: "detectable",
3569
+ summary: "Assignee fields may restrict newly assigned users and collective roles by role."
3570
+ }) ]);
3571
+
3572
+ function recordOf(value) {
3573
+ return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
3589
3574
  }
3590
3575
 
3591
- function deployedTagsGroq() {
3592
- return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}"].tag) | order(@ asc)`;
3576
+ function recordsAt(record, key) {
3577
+ const value = record[key];
3578
+ return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
3593
3579
  }
3594
3580
 
3595
- function definitionTagsGroq() {
3596
- return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}" && name == $definition].tag) | order(@ asc)`;
3581
+ function nestedFieldEntries(entries) {
3582
+ return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
3597
3583
  }
3598
3584
 
3599
- function latestDeployedDefinitions(rows) {
3600
- const byName = /* @__PURE__ */ new Map;
3601
- for (const row of rows) {
3602
- const held = byName.get(row.name);
3603
- (held === void 0 || row.version > held.version) && byName.set(row.name, row);
3604
- }
3605
- return [ ...byName.values() ];
3585
+ function parsedDefinitionSnapshot(root) {
3586
+ if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
3587
+ _id: typeof root._id == "string" ? root._id : "<unknown instance>",
3588
+ definitionSnapshot: root.definitionSnapshot
3589
+ }));
3590
+ }
3591
+
3592
+ function persistedDefinitionTree(document) {
3593
+ const root = recordOf(document);
3594
+ if (root === void 0) return;
3595
+ const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], {stages: stages, activities: activities, actions: actions} = definitionDescendants(roots);
3596
+ return {
3597
+ roots: roots,
3598
+ stages: stages,
3599
+ activities: activities,
3600
+ actions: actions
3601
+ };
3602
+ }
3603
+
3604
+ function persistedFieldEntries(document) {
3605
+ const tree = persistedDefinitionTree(document);
3606
+ if (tree === void 0) return [];
3607
+ const {roots: roots, stages: stages, activities: activities, actions: actions} = tree, effects = actions.flatMap(action => recordsAt(action, "effects"));
3608
+ 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")) ]);
3609
+ }
3610
+
3611
+ function definitionDescendants(roots) {
3612
+ const stages = roots.flatMap(root => recordsAt(root, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions"));
3613
+ return {
3614
+ stages: stages,
3615
+ activities: activities,
3616
+ actions: actions
3617
+ };
3618
+ }
3619
+
3620
+ function hasChoiceList(document) {
3621
+ return persistedFieldEntries(document).some(entry => {
3622
+ const options = recordOf(entry.options);
3623
+ return options !== void 0 && Array.isArray(options.list);
3624
+ });
3625
+ }
3626
+
3627
+ function entryHasKind(entry, kind) {
3628
+ return entryKindMatches(entry, candidate => candidate === kind);
3629
+ }
3630
+
3631
+ function entryKindMatches(entry, accepts) {
3632
+ return [ entry.type, entry._type ].some(kind => typeof kind == "string" && accepts(kind));
3633
+ }
3634
+
3635
+ function hasFieldKind(document, kind) {
3636
+ return persistedFieldEntries(document).some(entry => entryHasKind(entry, kind));
3637
+ }
3638
+
3639
+ function definitionNodes(document) {
3640
+ const root = recordOf(document);
3641
+ if (root !== void 0) return {
3642
+ root: root,
3643
+ ...definitionDescendants([ root ])
3644
+ };
3645
+ }
3646
+
3647
+ function hasActionSemantics(document) {
3648
+ return definitionNodes(document)?.actions.some(hasSemantics) ?? !1;
3649
+ }
3650
+
3651
+ function hasNodeSemantics(document) {
3652
+ const nodes = definitionNodes(document);
3653
+ return nodes === void 0 ? !1 : [ nodes.root, ...nodes.stages, ...nodes.activities ].some(hasSemantics) ? !0 : nodes.actions.some(action => hasSemantics(action) && action.semantics.some(isNodeSemanticValue));
3654
+ }
3655
+
3656
+ function isNodeSemanticValue(semantic) {
3657
+ return typeof semantic == "string" && (semantic.startsWith("signal.") || semantic.startsWith("custom."));
3658
+ }
3659
+
3660
+ function hasSemantics(node) {
3661
+ return Array.isArray(node.semantics);
3662
+ }
3663
+
3664
+ function hasPersistedOpType(document, types) {
3665
+ const tree = persistedDefinitionTree(document);
3666
+ 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)));
3667
+ }
3668
+
3669
+ function hasScalarValidation(document) {
3670
+ return persistedFieldEntries(document).some(entry => {
3671
+ const validation = recordOf(entry.validation);
3672
+ return typeof validation?.min == "number" || typeof validation?.max == "number";
3673
+ });
3674
+ }
3675
+
3676
+ function hasClaimTokens(document) {
3677
+ const root = recordOf(document);
3678
+ return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
3679
+ const claim = recordOf(entry.claim);
3680
+ return claim !== void 0 && typeof claim.claimToken == "string";
3681
+ });
3682
+ }
3683
+
3684
+ function hasReadinessRequirements(document) {
3685
+ const root = recordOf(document);
3686
+ 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)));
3687
+ }
3688
+
3689
+ function hasRoleConstrainedAssignments(document) {
3690
+ return persistedFieldEntries(document).some(entry => entryKindMatches(entry, assignmentKindAcceptsRoles) && Array.isArray(entry.roles) && entry.roles.length > 0);
3691
+ }
3692
+
3693
+ const featureDetectors = {
3694
+ "governed-model-stamps": () => !0,
3695
+ "subject-field-kind": document => hasFieldKind(document, "subject"),
3696
+ "typed-scalar-choice-lists": hasChoiceList,
3697
+ "action-semantics": hasActionSemantics,
3698
+ "inclusive-scalar-bounds": hasScalarValidation,
3699
+ "progress-field-kind": document => hasFieldKind(document, "progress"),
3700
+ "effect-claim-tokens": hasClaimTokens,
3701
+ "classified-principal-ids": () => !0,
3702
+ "readiness-requirements": hasReadinessRequirements,
3703
+ "due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime"),
3704
+ "role-constrained-assignment-fields": hasRoleConstrainedAssignments,
3705
+ "node-semantics": hasNodeSemantics,
3706
+ "field-patch-ops": document => hasPersistedOpType(document, [ "field.inc", "field.dec", "field.setIfMissing" ]),
3707
+ "attributes-condition-var": () => !0
3708
+ };
3709
+
3710
+ function requiredModelFeatures(documentType, document) {
3711
+ return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
3712
+ }
3713
+
3714
+ function requiredReaderModel(documentType, document) {
3715
+ return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
3716
+ }
3717
+
3718
+ function requiredDefinitionReaderModel(definitions) {
3719
+ return Math.max(DATA_MODEL_MIN_READER, ...definitions.map(definition => requiredReaderModel("definition", definition)));
3720
+ }
3721
+
3722
+ function modelStampFor(args) {
3723
+ return {
3724
+ modelVersion: DATA_MODEL_VERSION,
3725
+ minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
3726
+ };
3727
+ }
3728
+
3729
+ function fieldTreeShape(value) {
3730
+ if (Array.isArray(value)) return value.map(fieldTreeShape);
3731
+ if (value === null) return "null";
3732
+ if (typeof value == "object") {
3733
+ const record = value;
3734
+ return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
3735
+ }
3736
+ return typeof value;
3737
+ }
3738
+
3739
+ function modelVersionOf(doc) {
3740
+ const stamp = doc.modelVersion;
3741
+ return typeof stamp == "number" ? stamp : 0;
3742
+ }
3743
+
3744
+ function minReaderModelOf(doc) {
3745
+ const floor = doc.minReaderModel;
3746
+ return typeof floor == "number" ? floor : modelVersionOf(doc);
3747
+ }
3748
+
3749
+ class ModelVersionAheadError extends WorkflowError {
3750
+ documentId;
3751
+ documentModelVersion;
3752
+ requiredReaderModel;
3753
+ engineModelVersion;
3754
+ constructor(args) {
3755
+ 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.`),
3756
+ this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
3757
+ this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
3758
+ }
3759
+ }
3760
+
3761
+ function assertReadableModel(doc) {
3762
+ const documentReaderModel = minReaderModelOf(doc);
3763
+ if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
3764
+ documentId: doc._id,
3765
+ documentModelVersion: modelVersionOf(doc),
3766
+ requiredReaderModel: documentReaderModel
3767
+ });
3768
+ return doc;
3769
+ }
3770
+
3771
+ async function renderConditionScope(source, opts) {
3772
+ const {instance: instance, definition: definition, snapshot: snapshot, now: now} = source, base = buildParams({
3773
+ instance: instance,
3774
+ now: now,
3775
+ snapshot: snapshot
3776
+ }), fields = {
3777
+ ...base.fields,
3778
+ ...scopedFieldOverlay({
3779
+ instance: instance,
3780
+ snapshot: snapshot,
3781
+ activityName: opts?.activityName
3782
+ })
3783
+ }, params = {
3784
+ ...base,
3785
+ fields: fields,
3786
+ actor: opts?.actor,
3787
+ assigned: opts?.activityName !== void 0 ? assignedFor({
3788
+ instance: instance,
3789
+ activityName: opts.activityName,
3790
+ actor: opts?.actor,
3791
+ roleAliases: definition.roleAliases
3792
+ }) : !1,
3793
+ ...opts?.vars
3794
+ };
3795
+ return {
3796
+ ...await evaluatePredicates({
3797
+ predicates: definition.predicates,
3798
+ snapshot: snapshot,
3799
+ params: params
3800
+ }),
3801
+ ...params
3802
+ };
3803
+ }
3804
+
3805
+ function definitionLookupGroq(explicit) {
3806
+ const scoped = `_type == "${WORKFLOW_DEFINITION_TYPE}" && name == $definition && ${tagScopeFilter()}`;
3807
+ return explicit ? `*[${scoped} && version == $version][0]` : `*[${scoped}] | order(version desc)[0]`;
3808
+ }
3809
+
3810
+ function definitionsListGroq(versionOrder) {
3811
+ return `*[_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}] | order(name asc, version ${versionOrder})`;
3812
+ }
3813
+
3814
+ function latestDefinitionsGroq() {
3815
+ const scoped = `_type == "${WORKFLOW_DEFINITION_TYPE}" && ${tagScopeFilter()}`;
3816
+ return `*[${scoped} && version == math::max(*[${scoped} && name == ^.name].version)] | order(name asc)`;
3817
+ }
3818
+
3819
+ function deployedTagsGroq() {
3820
+ return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}"].tag) | order(@ asc)`;
3821
+ }
3822
+
3823
+ function definitionTagsGroq() {
3824
+ return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}" && name == $definition].tag) | order(@ asc)`;
3825
+ }
3826
+
3827
+ function latestDeployedDefinitions(rows) {
3828
+ const byName = /* @__PURE__ */ new Map;
3829
+ for (const row of rows) {
3830
+ const held = byName.get(row.name);
3831
+ (held === void 0 || row.version > held.version) && byName.set(row.name, row);
3832
+ }
3833
+ return [ ...byName.values() ];
3834
+ }
3835
+
3836
+ function findStageNode(args) {
3837
+ return args.definition?.stages.find(entry => entry.name === args.stageName);
3838
+ }
3839
+
3840
+ function findActivityNode(args) {
3841
+ return findStageNode(args)?.activities?.find(entry => entry.name === args.activityName);
3606
3842
  }
3607
3843
 
3608
3844
  function liveChildrenField(instance) {
@@ -3693,6 +3929,27 @@ function noTransitionFiresCause(input) {
3693
3929
  };
3694
3930
  }
3695
3931
 
3932
+ function stuckFromDocumentState(input) {
3933
+ return failedEffectCause(input) ?? failedActivityCause(input) ?? hungEffectCause(input);
3934
+ }
3935
+
3936
+ function documentStuckCause(args) {
3937
+ const stage = findOpenStageEntry(args.instance);
3938
+ if (stage !== void 0) return stuckFromDocumentState({
3939
+ instance: args.instance,
3940
+ activities: stage.activities.map(entry => ({
3941
+ status: entry.status,
3942
+ activity: findActivityNode({
3943
+ activityName: entry.name,
3944
+ definition: args.definition,
3945
+ stageName: stage.name
3946
+ }) ?? {
3947
+ name: entry.name
3948
+ }
3949
+ }))
3950
+ });
3951
+ }
3952
+
3696
3953
  function diagnoseInstance(input) {
3697
3954
  const {instance: instance} = input, terminal = terminalState(instance);
3698
3955
  if (terminal === "aborted" && instance.abortedAt !== void 0) {
@@ -3711,7 +3968,7 @@ function diagnoseInstance(input) {
3711
3968
  at: instance.completedAt,
3712
3969
  ...liveChildrenField(instance)
3713
3970
  };
3714
- const cause = failedEffectCause(input) ?? failedActivityCause(input) ?? hungEffectCause(input) ?? noTransitionFiresCause(input);
3971
+ const cause = stuckFromDocumentState(input) ?? noTransitionFiresCause(input);
3715
3972
  return cause !== void 0 ? {
3716
3973
  state: "stuck",
3717
3974
  cause: cause
@@ -3773,46 +4030,246 @@ function isClaimExpired(claim, now) {
3773
4030
  return claim.leaseExpiresAt === void 0 || hasPassed(claim.leaseExpiresAt, now);
3774
4031
  }
3775
4032
 
3776
- const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ], EXECUTION_KINDS = {
3777
- interactive: "interactive",
3778
- server: "server",
3779
- cli: "cli",
3780
- mcp: "mcp",
3781
- drainer: "drainer",
3782
- script: "script",
3783
- test: "test",
3784
- studio: "studio",
3785
- sdkApp: "sdk-app"
3786
- };
4033
+ const EFFECT_RUN_STATUSES = [ "done", "failed", "cancelled" ];
3787
4034
 
3788
- function detectRuntime() {
3789
- const g = globalThis;
3790
- if (g.Deno !== void 0) return "deno";
3791
- if (g.Bun !== void 0) return "bun";
3792
- if (g.EdgeRuntime !== void 0) return "edge";
3793
- if (g.window !== void 0 && g.document !== void 0) return "browser";
3794
- if (g.WorkerGlobalScope !== void 0 && g.self !== void 0) return "worker";
3795
- const proc = g.process;
3796
- return typeof proc == "object" && proc !== null && typeof proc.versions?.node == "string" ? "node" : "unknown";
4035
+ function userLoginProvider(user) {
4036
+ return user?.provider ?? user?.loginProvider;
3797
4037
  }
3798
4038
 
3799
- let inferredRuntime;
4039
+ function optionalString(value) {
4040
+ return value === void 0 || typeof value == "string";
4041
+ }
3800
4042
 
3801
- function resolveExecutionContext(declared) {
3802
- return inferredRuntime ??= detectRuntime(), {
3803
- runtime: inferredRuntime,
3804
- ...declared?.kind !== void 0 ? {
3805
- kind: declared.kind
3806
- } : {},
3807
- ...declared?.id !== void 0 ? {
3808
- id: declared.id
3809
- } : {}
3810
- };
4043
+ function isClientProjectUser(value) {
4044
+ return isRecord(value) && typeof value.id == "string" && optionalString(value.sanityUserId) && optionalString(value.displayName) && optionalString(value.email) && (value.imageUrl === null || optionalString(value.imageUrl)) && optionalString(value.provider) && optionalString(value.loginProvider);
3811
4045
  }
3812
4046
 
3813
- function stampHistoryEntries(entries, stamp) {
3814
- return entries.map(entry => ({
3815
- ...entry,
4047
+ function objectProperty(value, property) {
4048
+ if (!isRecord(value)) return;
4049
+ const propertyValue = value[property];
4050
+ return typeof propertyValue == "object" && propertyValue !== null ? propertyValue : void 0;
4051
+ }
4052
+
4053
+ function stringProperty(value, property) {
4054
+ const propertyValue = Reflect.get(value, property);
4055
+ return typeof propertyValue == "string" ? propertyValue : void 0;
4056
+ }
4057
+
4058
+ function apiErrorType(error) {
4059
+ const response = objectProperty(error, "response"), body = objectProperty(response, "body");
4060
+ if (!body) return;
4061
+ const nestedError = objectProperty(body, "error");
4062
+ return (nestedError ? stringProperty(nestedError, "type") : void 0) ?? stringProperty(body, "type");
4063
+ }
4064
+
4065
+ function isProjectUserNotFoundError(error) {
4066
+ return apiErrorType(error) === "projectUserNotFoundError";
4067
+ }
4068
+
4069
+ const memberJoinCache = /* @__PURE__ */ new WeakMap;
4070
+
4071
+ function joinCacheFor(client) {
4072
+ let cache = memberJoinCache.get(client);
4073
+ return cache === void 0 && (cache = /* @__PURE__ */ new Map, memberJoinCache.set(client, cache)),
4074
+ cache;
4075
+ }
4076
+
4077
+ function isClientProjectMember(value) {
4078
+ return isRecord(value) && typeof value.id == "string";
4079
+ }
4080
+
4081
+ async function requestProjectMembers(request, projectId) {
4082
+ const project = await request({
4083
+ uri: `/projects/${encodeURIComponent(projectId)}`
4084
+ }), members = isRecord(project) ? project.members : void 0;
4085
+ if (!Array.isArray(members) || !members.every(isClientProjectMember)) throw new Error(`Project member directory response is invalid for project "${projectId}"`);
4086
+ return members;
4087
+ }
4088
+
4089
+ async function requestProjectUsers(args) {
4090
+ const {request: request, projectId: projectId, memberIds: memberIds} = args, response = await request({
4091
+ uri: `/projects/${encodeURIComponent(projectId)}/users/${memberIds.map(encodeURIComponent).join(",")}`
4092
+ }), rows = Array.isArray(response) ? response : [ response ];
4093
+ if (!rows.every(isClientProjectUser)) throw new Error(`Project user directory response is invalid for project "${projectId}"`);
4094
+ const requested = new Set(memberIds);
4095
+ return rows.filter(row => requested.has(row.id));
4096
+ }
4097
+
4098
+ async function requestProjectMemberDirectory(args) {
4099
+ const {request: request, projectId: projectId} = args, members = await requestProjectMembers(request, projectId), memberIds = members.map(member => member.id).filter(id => classifyPrincipalId(id).namespace === "project");
4100
+ if (memberIds.length === 0) return {
4101
+ members: members,
4102
+ globalUsers: []
4103
+ };
4104
+ const users = await requestProjectUsers({
4105
+ request: request,
4106
+ projectId: projectId,
4107
+ memberIds: memberIds
4108
+ });
4109
+ return {
4110
+ members: members,
4111
+ globalUsers: users.flatMap(user => {
4112
+ const globalId = directoryBridgeId(user.sanityUserId);
4113
+ return globalId === void 0 ? [] : [ {
4114
+ memberId: user.id,
4115
+ globalId: globalId,
4116
+ user: user
4117
+ } ];
4118
+ })
4119
+ };
4120
+ }
4121
+
4122
+ async function resolveGlobalProjectUser(args) {
4123
+ const {client: client, request: request, projectId: projectId, id: id} = args, cache = joinCacheFor(client), key = `${projectId}:${id}`, hit = cache.get(key);
4124
+ if (hit !== void 0) return hit === null ? {
4125
+ status: "missing"
4126
+ } : {
4127
+ status: "resolved",
4128
+ user: hit
4129
+ };
4130
+ try {
4131
+ await ingestMemberJoin({
4132
+ request: request,
4133
+ projectId: projectId,
4134
+ cache: cache
4135
+ });
4136
+ const found = cache.get(key);
4137
+ return found != null ? {
4138
+ status: "resolved",
4139
+ user: found
4140
+ } : (cache.set(key, null), {
4141
+ status: "missing"
4142
+ });
4143
+ } catch (cause) {
4144
+ return {
4145
+ status: "inaccessible",
4146
+ cause: cause
4147
+ };
4148
+ }
4149
+ }
4150
+
4151
+ async function ingestMemberJoin(args) {
4152
+ const {request: request, projectId: projectId, cache: cache} = args, snapshot = await requestProjectMemberDirectory({
4153
+ request: request,
4154
+ projectId: projectId
4155
+ });
4156
+ for (const {globalId: globalId, user: user} of snapshot.globalUsers) cache.set(`${projectId}:${globalId}`, user);
4157
+ }
4158
+
4159
+ function clientProjectUserDirectory(client, projectId) {
4160
+ return {
4161
+ findById: async id => {
4162
+ if (!client.request) return {
4163
+ status: "inaccessible",
4164
+ cause: new Error("Project-user resolution requires WorkflowClient.request")
4165
+ };
4166
+ if (classifyPrincipalId(id).namespace === "global") return resolveGlobalProjectUser({
4167
+ client: client,
4168
+ request: client.request,
4169
+ projectId: projectId,
4170
+ id: id
4171
+ });
4172
+ try {
4173
+ const response = await client.request({
4174
+ uri: `/projects/${encodeURIComponent(projectId)}/users/${encodeURIComponent(id)}`
4175
+ }), candidate = Array.isArray(response) ? response[0] : response;
4176
+ return candidate == null ? {
4177
+ status: "missing"
4178
+ } : isClientProjectUser(candidate) ? candidate.id !== id ? {
4179
+ status: "inaccessible",
4180
+ cause: new Error(`Project-user response answered id "${candidate.id}", not the requested "${id}"`)
4181
+ } : {
4182
+ status: "resolved",
4183
+ user: candidate
4184
+ } : {
4185
+ status: "inaccessible",
4186
+ cause: new Error("Project-user response had an invalid shape")
4187
+ };
4188
+ } catch (cause) {
4189
+ return isProjectUserNotFoundError(cause) ? {
4190
+ status: "missing"
4191
+ } : {
4192
+ status: "inaccessible",
4193
+ cause: cause
4194
+ };
4195
+ }
4196
+ }
4197
+ };
4198
+ }
4199
+
4200
+ function resolveClientActor(client, args) {
4201
+ return resolveActor(clientProjectUserDirectory(client, args.projectId), args.actor);
4202
+ }
4203
+
4204
+ async function resolveActor(directory, actor) {
4205
+ if (actor.kind !== "person") return {
4206
+ status: "not-person",
4207
+ actor: actor
4208
+ };
4209
+ const personActor = {
4210
+ ...actor,
4211
+ kind: "person"
4212
+ }, lookup = await directory.findById(personActor.id);
4213
+ return lookup.status === "resolved" ? {
4214
+ status: "resolved",
4215
+ actor: personActor,
4216
+ user: lookup.user
4217
+ } : lookup.status === "inaccessible" ? {
4218
+ status: "inaccessible",
4219
+ actor: personActor,
4220
+ ...lookup.cause === void 0 ? {} : {
4221
+ cause: lookup.cause
4222
+ }
4223
+ } : {
4224
+ status: "missing",
4225
+ actor: personActor
4226
+ };
4227
+ }
4228
+
4229
+ function assertRoleConstrainedAssignmentResource(args) {
4230
+ if (hasRoleConstrainedAssignments(args.definition) && args.workflowResource.type !== "dataset") throw new Error(`${args.context}: definition "${args.definition.name}" uses role-constrained assignment fields, which require a dataset workflow resource; received resource type "${args.workflowResource.type}"`);
4231
+ }
4232
+
4233
+ const EXECUTION_KINDS = {
4234
+ interactive: "interactive",
4235
+ server: "server",
4236
+ cli: "cli",
4237
+ mcp: "mcp",
4238
+ drainer: "drainer",
4239
+ script: "script",
4240
+ test: "test",
4241
+ studio: "studio",
4242
+ sdkApp: "sdk-app"
4243
+ };
4244
+
4245
+ function detectRuntime() {
4246
+ const g = globalThis;
4247
+ if (g.Deno !== void 0) return "deno";
4248
+ if (g.Bun !== void 0) return "bun";
4249
+ if (g.EdgeRuntime !== void 0) return "edge";
4250
+ if (g.window !== void 0 && g.document !== void 0) return "browser";
4251
+ if (g.WorkerGlobalScope !== void 0 && g.self !== void 0) return "worker";
4252
+ const proc = g.process;
4253
+ return typeof proc == "object" && proc !== null && typeof proc.versions?.node == "string" ? "node" : "unknown";
4254
+ }
4255
+
4256
+ let inferredRuntime;
4257
+
4258
+ function resolveExecutionContext(declared) {
4259
+ return inferredRuntime ??= detectRuntime(), {
4260
+ runtime: inferredRuntime,
4261
+ ...declared?.kind !== void 0 ? {
4262
+ kind: declared.kind
4263
+ } : {},
4264
+ ...declared?.id !== void 0 ? {
4265
+ id: declared.id
4266
+ } : {}
4267
+ };
4268
+ }
4269
+
4270
+ function stampHistoryEntries(entries, stamp) {
4271
+ return entries.map(entry => ({
4272
+ ...entry,
3816
4273
  executionContext: stamp
3817
4274
  }));
3818
4275
  }
@@ -4090,10 +4547,8 @@ function assertRequiredInputProvided({entryDefs: entryDefs, initialFields: initi
4090
4547
  });
4091
4548
  }
4092
4549
 
4093
- const ARRAY_FIELD_TYPES = /* @__PURE__ */ new Set([ "doc.refs", "array", "assignees" ]);
4094
-
4095
4550
  function defaultEntryValue(entryType) {
4096
- return ARRAY_FIELD_TYPES.has(entryType) ? [] : null;
4551
+ return isAlwaysArrayFieldKind(entryType) ? [] : null;
4097
4552
  }
4098
4553
 
4099
4554
  function resolveInputValue({entry: entry, initialFields: initialFields, defaultValue: defaultValue}) {
@@ -4198,6 +4653,9 @@ function buildResolvedEntry({entry: entry, value: value, _key: _key, now: now})
4198
4653
  ...entry.validation !== void 0 ? {
4199
4654
  validation: entry.validation
4200
4655
  } : {},
4656
+ ...entry.roles !== void 0 ? {
4657
+ roles: entry.roles
4658
+ } : {},
4201
4659
  value: value,
4202
4660
  ...entry.initialValue?.type === "query" ? {
4203
4661
  resolvedAt: now
@@ -4229,7 +4687,10 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
4229
4687
  fields: entry.fields,
4230
4688
  of: entry.of,
4231
4689
  options: entry.options,
4232
- validation: entry.validation
4690
+ validation: entry.validation,
4691
+ roles: entry.roles,
4692
+ memberRoles: ctx.memberRoles,
4693
+ roleAliases: ctx.roleAliases
4233
4694
  });
4234
4695
  return "issues" in check ? (ctx.recordDiscard?.({
4235
4696
  field: entry.name,
@@ -4254,7 +4715,10 @@ async function resolveOneEntry({entry: entry, initialFields: initialFields, ctx:
4254
4715
  fields: entry.fields,
4255
4716
  of: entry.of,
4256
4717
  options: entry.options,
4257
- validation: entry.validation
4718
+ validation: entry.validation,
4719
+ roles: entry.roles,
4720
+ memberRoles: ctx.memberRoles,
4721
+ roleAliases: ctx.roleAliases
4258
4722
  });
4259
4723
  return entry.initialValue?.type === "input" && ctx.inputProvenance !== "definition" && assertRefsWithinSurface({
4260
4724
  entryType: entry.type,
@@ -4348,7 +4812,7 @@ function coerceToGdr(raw, workflowResource) {
4348
4812
  } : null;
4349
4813
  }
4350
4814
 
4351
- const NonEmpty = NonEmptyString, UnknownRecord = v.record(v.string(), v.unknown()), PersistedChoiceOptionsSchema = v.looseObject({
4815
+ const NonEmpty = NonEmptyString, PersistedAssignmentRolesSchema = v.pipe(v.array(NonEmptyString), v.minLength(1, "assignment roles must not be empty")), UnknownRecord = v.record(v.string(), v.unknown()), PersistedChoiceOptionsSchema = v.looseObject({
4352
4816
  list: v.array(v.looseObject({
4353
4817
  title: v.string(),
4354
4818
  value: v.union([ v.string(), v.number() ])
@@ -4363,6 +4827,7 @@ const NonEmpty = NonEmptyString, UnknownRecord = v.record(v.string(), v.unknown(
4363
4827
  description: v.optional(v.string()),
4364
4828
  options: v.optional(PersistedChoiceOptionsSchema),
4365
4829
  validation: v.optional(PersistedScalarValidationSchema),
4830
+ roles: v.optional(PersistedAssignmentRolesSchema),
4366
4831
  fields: v.optional(v.array(PersistedFieldShapeSchema)),
4367
4832
  of: v.optional(v.array(PersistedFieldShapeSchema))
4368
4833
  }))), ExecutionContextSchema = tolerantObject()({
@@ -4408,7 +4873,13 @@ const OptionalRefTypes = v.exactOptional(v.array(v.string())), ResolvedFieldEntr
4408
4873
  })), v.looseObject(tolerantEntries()({
4409
4874
  ...fieldArm("subject", fieldValueSchemas.subject),
4410
4875
  types: OptionalRefTypes
4411
- })), v.looseObject(tolerantEntries()(fieldArm("release.ref", fieldValueSchemas["release.ref"]))), v.looseObject(tolerantEntries()(fieldArm("string", fieldValueSchemas.string))), v.looseObject(tolerantEntries()(fieldArm("text", fieldValueSchemas.text))), v.looseObject(tolerantEntries()(fieldArm("number", fieldValueSchemas.number))), v.looseObject(tolerantEntries()(fieldArm("progress", fieldValueSchemas.progress))), v.looseObject(tolerantEntries()(fieldArm("boolean", fieldValueSchemas.boolean))), v.looseObject(tolerantEntries()(fieldArm("date", fieldValueSchemas.date))), v.looseObject(tolerantEntries()(fieldArm("dueDate", fieldValueSchemas.dueDate))), v.looseObject(tolerantEntries()(fieldArm("datetime", fieldValueSchemas.datetime))), v.looseObject(tolerantEntries()(fieldArm("dueDatetime", fieldValueSchemas.dueDatetime))), v.looseObject(tolerantEntries()(fieldArm("url", fieldValueSchemas.url))), v.looseObject(tolerantEntries()(fieldArm("actor", fieldValueSchemas.actor))), v.looseObject(tolerantEntries()(fieldArm("assignee", fieldValueSchemas.assignee))), v.looseObject(tolerantEntries()(fieldArm("assignees", fieldValueSchemas.assignees))), v.looseObject(tolerantEntries()({
4876
+ })), v.looseObject(tolerantEntries()(fieldArm("release.ref", fieldValueSchemas["release.ref"]))), v.looseObject(tolerantEntries()(fieldArm("string", fieldValueSchemas.string))), v.looseObject(tolerantEntries()(fieldArm("text", fieldValueSchemas.text))), v.looseObject(tolerantEntries()(fieldArm("number", fieldValueSchemas.number))), v.looseObject(tolerantEntries()(fieldArm("progress", fieldValueSchemas.progress))), v.looseObject(tolerantEntries()(fieldArm("boolean", fieldValueSchemas.boolean))), v.looseObject(tolerantEntries()(fieldArm("date", fieldValueSchemas.date))), v.looseObject(tolerantEntries()(fieldArm("dueDate", fieldValueSchemas.dueDate))), v.looseObject(tolerantEntries()(fieldArm("datetime", fieldValueSchemas.datetime))), v.looseObject(tolerantEntries()(fieldArm("dueDatetime", fieldValueSchemas.dueDatetime))), v.looseObject(tolerantEntries()(fieldArm("url", fieldValueSchemas.url))), v.looseObject(tolerantEntries()(fieldArm("actor", fieldValueSchemas.actor))), v.looseObject(tolerantEntries()({
4877
+ ...fieldArm("assignee", fieldValueSchemas.assignee),
4878
+ roles: v.exactOptional(PersistedAssignmentRolesSchema)
4879
+ })), v.looseObject(tolerantEntries()({
4880
+ ...fieldArm("assignees", fieldValueSchemas.assignees),
4881
+ roles: v.exactOptional(PersistedAssignmentRolesSchema)
4882
+ })), v.looseObject(tolerantEntries()({
4412
4883
  ...fieldArm("object", v.union([ v.null(), UnknownRecord ])),
4413
4884
  fields: v.array(PersistedFieldShapeSchema)
4414
4885
  })), v.looseObject(tolerantEntries()({
@@ -4659,6 +5130,37 @@ function parseInstanceDocument(doc) {
4659
5130
  });
4660
5131
  }
4661
5132
 
5133
+ const WorkflowInstancePreviewEffectSchema = tolerantObject()({
5134
+ name: NonEmpty,
5135
+ title: v.exactOptional(v.string())
5136
+ }), WorkflowInstancePreviewSchema = v.looseObject(tolerantEntries()({
5137
+ _id: NonEmpty,
5138
+ _type: v.literal(WORKFLOW_INSTANCE_TYPE),
5139
+ modelVersion: v.exactOptional(v.number()),
5140
+ minReaderModel: v.exactOptional(v.number()),
5141
+ workflowResource: WorkflowResourceSchema,
5142
+ definition: NonEmpty,
5143
+ pinnedVersion: v.number(),
5144
+ fields: v.array(ResolvedFieldEntrySchema),
5145
+ ancestors: v.array(GdrShape),
5146
+ perspective: v.exactOptional(WorkflowPerspectiveSchema),
5147
+ currentStage: NonEmpty,
5148
+ stages: v.array(StageEntrySchema),
5149
+ claimedEffects: v.array(WorkflowInstancePreviewEffectSchema),
5150
+ failedEffects: v.array(WorkflowInstancePreviewEffectSchema),
5151
+ startedAt: IsoTimestamp,
5152
+ completedAt: v.exactOptional(IsoTimestamp),
5153
+ abortedAt: v.exactOptional(IsoTimestamp)
5154
+ }));
5155
+
5156
+ function parseInstancePreviewDocument(doc) {
5157
+ return parsePersistedDoc({
5158
+ schema: WorkflowInstancePreviewSchema,
5159
+ doc: doc,
5160
+ docType: WORKFLOW_INSTANCE_TYPE
5161
+ });
5162
+ }
5163
+
4662
5164
  const SYNC_COMMIT = {
4663
5165
  visibility: "sync"
4664
5166
  }, ENGINE_API_VERSION = "2026-04-29", REQUEST_TAG = {
@@ -4694,7 +5196,9 @@ const SYNC_COMMIT = {
4694
5196
  effect: "workflow.effect",
4695
5197
  verifyDefinitions: "workflow.verify-definitions",
4696
5198
  accessResolveActor: "workflow.access.resolve-actor",
4697
- accessGrants: "workflow.access.grants"
5199
+ accessGrants: "workflow.access.grants",
5200
+ accessResolveOrg: "workflow.access.resolve-org",
5201
+ accessAttributes: "workflow.access.attributes"
4698
5202
  }, RAW_PATCH = /* @__PURE__ */ Symbol("workflow-engine.raw-patch");
4699
5203
 
4700
5204
  function unwrapPatch(patch) {
@@ -5104,6 +5608,40 @@ function readInstanceDoc(doc) {
5104
5608
  return parseInstanceDocument(assertReadableModel(doc));
5105
5609
  }
5106
5610
 
5611
+ function readInstancePreviewDoc(doc) {
5612
+ return hasDocumentId(doc) ? parseInstancePreviewDocument(withoutProjectedNulls(assertReadableModel(doc))) : parseInstancePreviewDocument(doc);
5613
+ }
5614
+
5615
+ function hasDocumentId(doc) {
5616
+ return typeof doc == "object" && doc !== null && typeof doc._id == "string";
5617
+ }
5618
+
5619
+ function withoutProjectedNulls(doc) {
5620
+ const row = withoutNullMembers(doc);
5621
+ if (typeof row != "object" || row === null) return row;
5622
+ const out = {
5623
+ ...row
5624
+ };
5625
+ return Array.isArray(out.stages) && (out.stages = out.stages.map(withoutStageEntryNulls)),
5626
+ Array.isArray(out.claimedEffects) && (out.claimedEffects = out.claimedEffects.map(withoutNullMembers)),
5627
+ Array.isArray(out.failedEffects) && (out.failedEffects = out.failedEffects.map(withoutNullMembers)),
5628
+ out;
5629
+ }
5630
+
5631
+ function withoutStageEntryNulls(entry) {
5632
+ const stage = withoutNullMembers(entry);
5633
+ if (typeof stage != "object" || stage === null) return stage;
5634
+ const out = {
5635
+ ...stage
5636
+ };
5637
+ return Array.isArray(out.activities) && (out.activities = out.activities.map(withoutNullMembers)),
5638
+ out;
5639
+ }
5640
+
5641
+ function withoutNullMembers(value) {
5642
+ return value === null || typeof value != "object" || Array.isArray(value) ? value : Object.fromEntries(Object.entries(value).filter(([, member]) => member !== null));
5643
+ }
5644
+
5107
5645
  async function reload({client: client, instanceId: instanceId, tag: tag}) {
5108
5646
  const doc = await getInstanceDocument(client, instanceId);
5109
5647
  if (!doc) throw new InstanceNotFoundError({
@@ -5350,7 +5888,8 @@ function loadCallContext({client: client, instanceId: instanceId, options: optio
5350
5888
  } : {},
5351
5889
  ...options.telemetry ? {
5352
5890
  telemetry: options.telemetry
5353
- } : {}
5891
+ } : {},
5892
+ memberRolesLoader: options.memberRolesLoader
5354
5893
  }
5355
5894
  });
5356
5895
  }
@@ -5395,6 +5934,7 @@ async function loadContext({client: client, instanceId: instanceId, options: opt
5395
5934
  ...options.telemetry !== void 0 ? {
5396
5935
  telemetry: options.telemetry
5397
5936
  } : {},
5937
+ memberRolesLoader: options.memberRolesLoader,
5398
5938
  ...options.overlay !== void 0 ? {
5399
5939
  overlay: options.overlay
5400
5940
  } : {},
@@ -5430,7 +5970,10 @@ async function ctxEvaluateCondition({ctx: ctx, condition: condition, opts: opts}
5430
5970
  }
5431
5971
 
5432
5972
  async function buildEngineContext(args) {
5433
- const {client: client, clientForGdr: clientForGdr, refSurface: refSurface, instance: instance, definition: definition} = args, clock = args.clock ?? wallClock;
5973
+ const {client: client, clientForGdr: clientForGdr, refSurface: refSurface, instance: instance, definition: definition} = args, clock = args.clock ?? wallClock, memberRolesLoader = args.memberRolesLoader, memberRoles = await memberRolesLoader({
5974
+ workflowResource: instance.workflowResource,
5975
+ definition: definition
5976
+ });
5434
5977
  return {
5435
5978
  client: client,
5436
5979
  clientForGdr: clientForGdr,
@@ -5447,6 +5990,10 @@ async function buildEngineContext(args) {
5447
5990
  } : {},
5448
5991
  instance: instance,
5449
5992
  definition: definition,
5993
+ memberRolesLoader: memberRolesLoader,
5994
+ ...memberRoles !== void 0 ? {
5995
+ memberRoles: memberRoles
5996
+ } : {},
5450
5997
  snapshot: await hydrateSnapshot({
5451
5998
  client: client,
5452
5999
  clientForGdr: clientForGdr,
@@ -5458,25 +6005,83 @@ async function buildEngineContext(args) {
5458
6005
  };
5459
6006
  }
5460
6007
 
5461
- function findStage(definition, stageName) {
5462
- const stage = definition.stages.find(s => s.name === stageName);
5463
- if (stage === void 0) throw new Error(`Stage "${stageName}" not found in definition ${definition.name}`);
5464
- return stage;
6008
+ function createAssignmentMemberRolesLoader(client) {
6009
+ const byProjectId = /* @__PURE__ */ new Map;
6010
+ return async ({workflowResource: workflowResource, definition: definition}) => {
6011
+ if (!hasRoleConstrainedAssignments(definition)) return;
6012
+ assertRoleConstrainedAssignmentResource({
6013
+ context: "workflow",
6014
+ definition: definition,
6015
+ workflowResource: workflowResource
6016
+ });
6017
+ const projectId = datasetResourceParts(workflowResource.id).projectId;
6018
+ let pending = byProjectId.get(projectId);
6019
+ return pending === void 0 && (pending = client.request === void 0 ? Promise.reject(new Error(`Definition "${definition.name}" has role-constrained assignments, which require project-directory access for project "${projectId}"; the client cannot issue requests`)) : loadProjectMemberRoles({
6020
+ request: client.request,
6021
+ projectId: projectId
6022
+ }), byProjectId.set(projectId, pending)), pending;
6023
+ };
5465
6024
  }
5466
6025
 
5467
- async function resolveStageFieldEntries(args) {
5468
- const {client: client, instance: instance, stage: stage, now: now, refSurface: refSurface, initialFields: initialFields, recordDiscard: recordDiscard} = args;
5469
- return resolveDeclaredFields({
5470
- entryDefs: stage.fields,
5471
- initialFields: initialFields ?? [],
5472
- ctx: {
5473
- client: client,
5474
- now: now,
5475
- refSurface: refSurface,
6026
+ async function loadProjectMemberRoles(args) {
6027
+ const {request: request, projectId: projectId} = args, snapshot = await requestProjectMemberDirectory({
6028
+ request: request,
6029
+ projectId: projectId
6030
+ }), rolesByProjectId = projectMemberRoles({
6031
+ members: snapshot.members,
6032
+ projectId: projectId
6033
+ });
6034
+ return globalizeMemberRoles({
6035
+ snapshot: snapshot,
6036
+ rolesByProjectId: rolesByProjectId
6037
+ });
6038
+ }
6039
+
6040
+ function globalizeMemberRoles(args) {
6041
+ const {snapshot: snapshot, rolesByProjectId: rolesByProjectId} = args, humanIds = [ ...rolesByProjectId.keys() ].filter(id => classifyPrincipalId(id).namespace === "project");
6042
+ for (const {globalId: globalId, memberId: memberId} of snapshot.globalUsers) {
6043
+ const roles = rolesByProjectId.get(memberId);
6044
+ roles !== void 0 && rolesByProjectId.set(globalId, roles);
6045
+ }
6046
+ for (const id of humanIds) rolesByProjectId.delete(id);
6047
+ return Object.fromEntries(rolesByProjectId);
6048
+ }
6049
+
6050
+ function projectMemberRoles(args) {
6051
+ const result = /* @__PURE__ */ new Map;
6052
+ for (const member of args.members) {
6053
+ const {id: id, roles: roles} = member;
6054
+ if (!Array.isArray(roles) || !roles.every(isProjectMemberRole)) throw new Error(`Project member role directory response is invalid for project "${args.projectId}" and member "${id}"`);
6055
+ result.set(id, roles.map(role => role.name));
6056
+ }
6057
+ return result;
6058
+ }
6059
+
6060
+ function isProjectMemberRole(role) {
6061
+ return isRecord(role) && typeof role.name == "string";
6062
+ }
6063
+
6064
+ function findStage(definition, stageName) {
6065
+ const stage = definition.stages.find(s => s.name === stageName);
6066
+ if (stage === void 0) throw new Error(`Stage "${stageName}" not found in definition ${definition.name}`);
6067
+ return stage;
6068
+ }
6069
+
6070
+ async function resolveStageFieldEntries(args) {
6071
+ const {client: client, instance: instance, stage: stage, now: now, refSurface: refSurface, initialFields: initialFields, recordDiscard: recordDiscard} = args;
6072
+ return resolveDeclaredFields({
6073
+ entryDefs: stage.fields,
6074
+ initialFields: initialFields ?? [],
6075
+ ctx: {
6076
+ client: client,
6077
+ now: now,
6078
+ refSurface: refSurface,
5476
6079
  selfId: instance._id,
5477
6080
  tag: instance.tag,
5478
6081
  stageName: stage.name,
5479
6082
  workflowResource: instance.workflowResource,
6083
+ memberRoles: args.memberRoles,
6084
+ roleAliases: args.roleAliases,
5480
6085
  workflowFields: instance.fields ?? [],
5481
6086
  ...instance.perspective !== void 0 ? {
5482
6087
  perspective: instance.perspective
@@ -5503,6 +6108,8 @@ async function resolveActivityFieldEntries(args) {
5503
6108
  stageName: stage.name,
5504
6109
  workflowResource: instance.workflowResource,
5505
6110
  activityName: activity.name,
6111
+ memberRoles: args.memberRoles,
6112
+ roleAliases: args.roleAliases,
5506
6113
  workflowFields: instance.fields ?? [],
5507
6114
  ...instance.perspective !== void 0 ? {
5508
6115
  perspective: instance.perspective
@@ -5658,171 +6265,6 @@ function resolveMetadata(metadata, ctx) {
5658
6265
  return out;
5659
6266
  }
5660
6267
 
5661
- function userLoginProvider(user) {
5662
- return user?.provider ?? user?.loginProvider;
5663
- }
5664
-
5665
- function isRecord(value) {
5666
- return typeof value == "object" && value !== null && !Array.isArray(value);
5667
- }
5668
-
5669
- function optionalString(value) {
5670
- return value === void 0 || typeof value == "string";
5671
- }
5672
-
5673
- function isClientProjectUser(value) {
5674
- return isRecord(value) && typeof value.id == "string" && optionalString(value.sanityUserId) && optionalString(value.displayName) && optionalString(value.email) && (value.imageUrl === null || optionalString(value.imageUrl)) && optionalString(value.provider) && optionalString(value.loginProvider);
5675
- }
5676
-
5677
- function objectProperty(value, property) {
5678
- if (!isRecord(value)) return;
5679
- const propertyValue = value[property];
5680
- return typeof propertyValue == "object" && propertyValue !== null ? propertyValue : void 0;
5681
- }
5682
-
5683
- function stringProperty(value, property) {
5684
- const propertyValue = Reflect.get(value, property);
5685
- return typeof propertyValue == "string" ? propertyValue : void 0;
5686
- }
5687
-
5688
- function apiErrorType(error) {
5689
- const response = objectProperty(error, "response"), body = objectProperty(response, "body");
5690
- if (!body) return;
5691
- const nestedError = objectProperty(body, "error");
5692
- return (nestedError ? stringProperty(nestedError, "type") : void 0) ?? stringProperty(body, "type");
5693
- }
5694
-
5695
- function isProjectUserNotFoundError(error) {
5696
- return apiErrorType(error) === "projectUserNotFoundError";
5697
- }
5698
-
5699
- const memberJoinCache = /* @__PURE__ */ new WeakMap;
5700
-
5701
- function joinCacheFor(client) {
5702
- let cache = memberJoinCache.get(client);
5703
- return cache === void 0 && (cache = /* @__PURE__ */ new Map, memberJoinCache.set(client, cache)),
5704
- cache;
5705
- }
5706
-
5707
- async function projectMemberIds(request, projectId) {
5708
- const project = await request({
5709
- uri: `/projects/${encodeURIComponent(projectId)}`
5710
- }), members = isRecord(project) ? project.members : void 0;
5711
- return Array.isArray(members) ? members.map(member => isRecord(member) ? member.id : void 0).filter(id => typeof id == "string") : [];
5712
- }
5713
-
5714
- async function resolveGlobalProjectUser(args) {
5715
- const {client: client, request: request, projectId: projectId, id: id} = args, cache = joinCacheFor(client), key = `${projectId}:${id}`, hit = cache.get(key);
5716
- if (hit !== void 0) return hit === null ? {
5717
- status: "missing"
5718
- } : {
5719
- status: "resolved",
5720
- user: hit
5721
- };
5722
- try {
5723
- await ingestMemberJoin({
5724
- request: request,
5725
- projectId: projectId,
5726
- cache: cache
5727
- });
5728
- const found = cache.get(key);
5729
- return found != null ? {
5730
- status: "resolved",
5731
- user: found
5732
- } : (cache.set(key, null), {
5733
- status: "missing"
5734
- });
5735
- } catch (cause) {
5736
- return {
5737
- status: "inaccessible",
5738
- cause: cause
5739
- };
5740
- }
5741
- }
5742
-
5743
- async function ingestMemberJoin(args) {
5744
- const {request: request, projectId: projectId, cache: cache} = args, memberIds = await projectMemberIds(request, projectId);
5745
- if (memberIds.length === 0) return;
5746
- const requested = new Set(memberIds), response = await request({
5747
- uri: `/projects/${encodeURIComponent(projectId)}/users/${memberIds.map(encodeURIComponent).join(",")}`
5748
- });
5749
- for (const row of Array.isArray(response) ? response : [ response ]) {
5750
- if (!isClientProjectUser(row) || !requested.has(row.id)) continue;
5751
- const globalId = directoryBridgeId(row.sanityUserId);
5752
- globalId !== void 0 && cache.set(`${projectId}:${globalId}`, row);
5753
- }
5754
- }
5755
-
5756
- function clientProjectUserDirectory(client, projectId) {
5757
- return {
5758
- findById: async id => {
5759
- if (!client.request) return {
5760
- status: "inaccessible",
5761
- cause: new Error("Project-user resolution requires WorkflowClient.request")
5762
- };
5763
- if (classifyPrincipalId(id).namespace === "global") return resolveGlobalProjectUser({
5764
- client: client,
5765
- request: client.request,
5766
- projectId: projectId,
5767
- id: id
5768
- });
5769
- try {
5770
- const response = await client.request({
5771
- uri: `/projects/${encodeURIComponent(projectId)}/users/${encodeURIComponent(id)}`
5772
- }), candidate = Array.isArray(response) ? response[0] : response;
5773
- return candidate == null ? {
5774
- status: "missing"
5775
- } : isClientProjectUser(candidate) ? candidate.id !== id ? {
5776
- status: "inaccessible",
5777
- cause: new Error(`Project-user response answered id "${candidate.id}", not the requested "${id}"`)
5778
- } : {
5779
- status: "resolved",
5780
- user: candidate
5781
- } : {
5782
- status: "inaccessible",
5783
- cause: new Error("Project-user response had an invalid shape")
5784
- };
5785
- } catch (cause) {
5786
- return isProjectUserNotFoundError(cause) ? {
5787
- status: "missing"
5788
- } : {
5789
- status: "inaccessible",
5790
- cause: cause
5791
- };
5792
- }
5793
- }
5794
- };
5795
- }
5796
-
5797
- function resolveClientActor(client, args) {
5798
- return resolveActor(clientProjectUserDirectory(client, args.projectId), args.actor);
5799
- }
5800
-
5801
- async function resolveActor(directory, actor) {
5802
- if (actor.kind !== "person") return {
5803
- status: "not-person",
5804
- actor: actor
5805
- };
5806
- const personActor = {
5807
- ...actor,
5808
- kind: "person"
5809
- }, lookup = await directory.findById(personActor.id);
5810
- return lookup.status === "resolved" ? {
5811
- status: "resolved",
5812
- actor: personActor,
5813
- user: lookup.user
5814
- } : lookup.status === "inaccessible" ? {
5815
- status: "inaccessible",
5816
- actor: personActor,
5817
- ...lookup.cause === void 0 ? {} : {
5818
- cause: lookup.cause
5819
- }
5820
- } : {
5821
- status: "missing",
5822
- actor: personActor
5823
- };
5824
- }
5825
-
5826
6268
  const IDENTITY_KINDS = /* @__PURE__ */ new Set([ "actor", "assignee", "assignees" ]);
5827
6269
 
5828
6270
  async function localizeGuardMetadata(args) {
@@ -6468,6 +6910,8 @@ async function buildActivityEntry({ctx: ctx, stage: stage, activity: activity, r
6468
6910
  activity: activity,
6469
6911
  now: ctx.now,
6470
6912
  refSurface: ctx.refSurface,
6913
+ memberRoles: ctx.memberRoles,
6914
+ roleAliases: ctx.definition.roleAliases,
6471
6915
  ...recordDiscard !== void 0 ? {
6472
6916
  recordDiscard: recordDiscard
6473
6917
  } : {}
@@ -6670,7 +7114,8 @@ async function spawnRow({ctx: ctx, mutation: mutation, activity: activity, actio
6670
7114
  context: context,
6671
7115
  actor: actor,
6672
7116
  now: now,
6673
- refSurface: ctx.refSurface
7117
+ refSurface: ctx.refSurface,
7118
+ memberRolesLoader: ctx.memberRolesLoader
6674
7119
  });
6675
7120
  mutation.pendingCreates.push({
6676
7121
  body: body,
@@ -6892,13 +7337,16 @@ async function resolveDefinitionRef({client: client, ref: ref, tag: tag}) {
6892
7337
  }
6893
7338
 
6894
7339
  async function prepareChildInstance(args) {
6895
- const {client: client, parent: parent, definition: definition, initialFields: initialFields, context: context, actor: actor, now: now, refSurface: refSurface} = args, childTag = parent.tag, workflowResource = parent.workflowResource, childDocId = instanceDocId(childTag), childRef = {
7340
+ const {client: client, parent: parent, definition: definition, initialFields: initialFields, context: context, actor: actor, now: now, refSurface: refSurface, memberRolesLoader: memberRolesLoader} = args, childTag = parent.tag, workflowResource = parent.workflowResource, childDocId = instanceDocId(childTag), childRef = {
6896
7341
  id: gdrFromResource(workflowResource, childDocId),
6897
7342
  type: WORKFLOW_INSTANCE_TYPE
6898
7343
  }, ancestors = [ ...parent.ancestors, {
6899
7344
  id: selfGdr(parent),
6900
7345
  type: WORKFLOW_INSTANCE_TYPE
6901
- } ], inheritedPerspective = parent.perspective, fieldDiscards = [], childFields = await resolveDeclaredFields({
7346
+ } ], inheritedPerspective = parent.perspective, fieldDiscards = [], memberRoles = await memberRolesLoader({
7347
+ workflowResource: workflowResource,
7348
+ definition: definition
7349
+ }), childFields = await resolveDeclaredFields({
6902
7350
  entryDefs: definition.fields,
6903
7351
  initialFields: initialFields,
6904
7352
  ctx: {
@@ -6909,6 +7357,8 @@ async function prepareChildInstance(args) {
6909
7357
  workflowResource: workflowResource,
6910
7358
  definitionName: definition.name,
6911
7359
  refSurface: refSurface,
7360
+ memberRoles: memberRoles,
7361
+ roleAliases: definition.roleAliases,
6912
7362
  inputProvenance: "definition",
6913
7363
  ...inheritedPerspective !== void 0 ? {
6914
7364
  perspective: inheritedPerspective
@@ -6979,6 +7429,8 @@ async function enterStage({ctx: ctx, mutation: mutation, nextStage: nextStage, a
6979
7429
  stage: nextStage,
6980
7430
  now: at,
6981
7431
  refSurface: ctx.refSurface,
7432
+ memberRoles: ctx.memberRoles,
7433
+ roleAliases: ctx.definition.roleAliases,
6982
7434
  recordDiscard: recordFieldDiscards({
6983
7435
  target: mutation.history,
6984
7436
  scope: "stage",
@@ -7159,47 +7611,454 @@ async function grantsPermissionOn(args) {
7159
7611
  return !1;
7160
7612
  }
7161
7613
 
7162
- function aclPathForResource(res) {
7163
- if (res.type === "dataset") {
7164
- const {projectId: projectId, dataset: dataset} = datasetResourceParts(res.id);
7165
- return `/projects/${projectId}/datasets/${dataset}/acl`;
7614
+ function aclPathForResource(res) {
7615
+ if (res.type === "dataset") {
7616
+ const {projectId: projectId, dataset: dataset} = datasetResourceParts(res.id);
7617
+ return `/projects/${projectId}/datasets/${dataset}/acl`;
7618
+ }
7619
+ if (res.type === "canvas") return `/canvases/${res.id}/acl`;
7620
+ }
7621
+
7622
+ async function fetchGrants(args) {
7623
+ const {client: client, resourcePath: resourcePath, signal: signal} = args;
7624
+ return client.request({
7625
+ url: resourcePath,
7626
+ tag: REQUEST_TAG.accessGrants,
7627
+ ...signal ? {
7628
+ signal: signal
7629
+ } : {}
7630
+ });
7631
+ }
7632
+
7633
+ async function advisoryCanForCall(args) {
7634
+ const actor = args.options?.actor;
7635
+ if (!(args.options?.grants === void 0 || actor === void 0)) return advisoryCan({
7636
+ instance: args.instance,
7637
+ identity: lakePrincipalId({
7638
+ actor: actor,
7639
+ localPrincipalId: args.options.localPrincipalId
7640
+ }),
7641
+ grants: args.options.grants
7642
+ });
7643
+ }
7644
+
7645
+ async function advisoryCan({instance: instance, identity: identity, grants: grants}) {
7646
+ if (grants === void 0) return;
7647
+ const can = {};
7648
+ for (const permission of DOCUMENT_VALUE_PERMISSIONS) can[permission] = await grantsPermissionOn({
7649
+ document: instance,
7650
+ grants: grants,
7651
+ permission: permission,
7652
+ userId: identity
7653
+ });
7654
+ return can;
7655
+ }
7656
+
7657
+ const DANGEROUS_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([ "__proto__", "constructor", "prototype" ]);
7658
+
7659
+ function attributeEntry(row) {
7660
+ 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 ];
7661
+ }
7662
+
7663
+ function normalizeUserAttributes(response) {
7664
+ if (!isRecord(response)) return;
7665
+ const rows = response.attributes;
7666
+ if (!Array.isArray(rows)) return;
7667
+ const out = {};
7668
+ for (const row of rows) {
7669
+ const entry = attributeEntry(row);
7670
+ entry !== void 0 && (out[entry[0]] = entry[1]);
7671
+ }
7672
+ return out;
7673
+ }
7674
+
7675
+ const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap, orgIdCache = /* @__PURE__ */ new WeakMap, attributesCache = /* @__PURE__ */ new WeakMap;
7676
+
7677
+ async function resolveAccess(taggedClient, args = {}) {
7678
+ const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
7679
+ 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).");
7680
+ const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
7681
+ client: client,
7682
+ requestFn: requestFn,
7683
+ resourcePath: args.grantsFromPath
7684
+ }) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
7685
+ 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.");
7686
+ return {
7687
+ actor: identity.actor,
7688
+ ...identity.localPrincipalId !== void 0 ? {
7689
+ localPrincipalId: identity.localPrincipalId
7690
+ } : {},
7691
+ ...grants !== void 0 ? {
7692
+ grants: grants
7693
+ } : {}
7694
+ };
7695
+ }
7696
+
7697
+ async function resolveUserAttributes(taggedClient) {
7698
+ const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
7699
+ if (requestFn !== void 0) return cachedAttributes({
7700
+ client: client,
7701
+ requestFn: requestFn
7702
+ });
7703
+ }
7704
+
7705
+ function cachedActor(client, requestFn) {
7706
+ const cached = actorCache.get(client);
7707
+ if (cached !== void 0) return cached;
7708
+ const pending = fetchActor(client, requestFn).catch(err => {
7709
+ throw actorCache.get(client) === pending && actorCache.delete(client), err;
7710
+ });
7711
+ return actorCache.set(client, pending), pending;
7712
+ }
7713
+
7714
+ function grantsForClientPath(taggedClient, resourcePath) {
7715
+ const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
7716
+ return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
7717
+ client: client,
7718
+ requestFn: requestFn,
7719
+ resourcePath: resourcePath
7720
+ });
7721
+ }
7722
+
7723
+ function lazyRequest(client) {
7724
+ return client.request === void 0 ? void 0 : opts => client.request(opts);
7725
+ }
7726
+
7727
+ function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
7728
+ return cachedByKey({
7729
+ store: grantsCache,
7730
+ client: client,
7731
+ key: resourcePath,
7732
+ load: () => fetchGrantsCached(requestFn, resourcePath)
7733
+ });
7734
+ }
7735
+
7736
+ function cachedByKey(args) {
7737
+ let byKey = args.store.get(args.client);
7738
+ byKey === void 0 && (byKey = /* @__PURE__ */ new Map, args.store.set(args.client, byKey));
7739
+ const cached = byKey.get(args.key);
7740
+ if (cached !== void 0) return cached;
7741
+ const pending = args.evictOnRejection ? args.load().catch(err => {
7742
+ throw byKey.get(args.key) === pending && byKey.delete(args.key), err;
7743
+ }) : args.load();
7744
+ return byKey.set(args.key, pending), pending;
7745
+ }
7746
+
7747
+ async function fetchActor(client, requestFn) {
7748
+ 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;
7749
+ if (sessionId === void 0) return;
7750
+ const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
7751
+ client: client,
7752
+ sessionId: sessionId,
7753
+ resourceId: resourceId
7754
+ }) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
7755
+ refuseProjectScopedActor({
7756
+ id: id,
7757
+ globalUser: globalUser,
7758
+ globalHostId: globalHostId,
7759
+ bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
7760
+ });
7761
+ const roleNames = roleNamesFor(resourceUser, globalUser);
7762
+ return {
7763
+ actor: {
7764
+ kind: "person",
7765
+ id: id,
7766
+ ...roleNames.length > 0 ? {
7767
+ roles: roleNames
7768
+ } : {}
7769
+ },
7770
+ ...resourceId !== void 0 && resourceId !== id ? {
7771
+ localPrincipalId: resourceId
7772
+ } : {}
7773
+ };
7774
+ }
7775
+
7776
+ function roleNamesFor(resourceUser, globalUser) {
7777
+ return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
7778
+ }
7779
+
7780
+ const NO_BRIDGE = {
7781
+ status: "not-applicable"
7782
+ };
7783
+
7784
+ function globalRouteReason(globalUser, globalHostId) {
7785
+ return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
7786
+ }
7787
+
7788
+ async function bridgeProjectPrincipal(args) {
7789
+ const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
7790
+ return classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project" ? {
7791
+ status: "unavailable",
7792
+ reason: "no project-scoped principal from the resource host to address the directory with"
7793
+ } : directoryGlobalId({
7794
+ client: client,
7795
+ principalId: resourceId
7796
+ });
7797
+ }
7798
+
7799
+ async function directoryGlobalId(args) {
7800
+ const {client: client, principalId: principalId} = args, projectId = projectIdOf(client);
7801
+ if (projectId === void 0) return {
7802
+ status: "unavailable",
7803
+ reason: "the client reports no projectId, so its user directory has no address"
7804
+ };
7805
+ const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
7806
+ if (lookup.status !== "resolved") return {
7807
+ status: "unavailable",
7808
+ reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
7809
+ ...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
7810
+ cause: lookup.cause
7811
+ } : {}
7812
+ };
7813
+ const globalId = directoryBridgeId(lookup.user.sanityUserId);
7814
+ return globalId === void 0 ? {
7815
+ status: "unavailable",
7816
+ reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
7817
+ } : {
7818
+ status: "resolved",
7819
+ globalId: globalId
7820
+ };
7821
+ }
7822
+
7823
+ function refuseProjectScopedActor(args) {
7824
+ const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
7825
+ if (classifyPrincipalId(id).namespace !== "project") return;
7826
+ const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
7827
+ bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
7828
+ const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
7829
+ 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 : {
7830
+ cause: cause
7831
+ });
7832
+ }
7833
+
7834
+ function usableId(user) {
7835
+ if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
7836
+ }
7837
+
7838
+ async function fetchCurrentUser(requestFn, hostDescription) {
7839
+ try {
7840
+ return await requestFn({
7841
+ uri: "/users/me",
7842
+ tag: REQUEST_TAG.accessResolveActor
7843
+ });
7844
+ } catch (err) {
7845
+ 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.`, {
7846
+ cause: err
7847
+ });
7848
+ }
7849
+ }
7850
+
7851
+ async function fetchGlobalUser(client) {
7852
+ const sibling = globalHostRequestOf(client);
7853
+ if ("reason" in sibling) return {
7854
+ user: void 0,
7855
+ reason: sibling.reason,
7856
+ ...sibling.cause !== void 0 ? {
7857
+ cause: sibling.cause
7858
+ } : {}
7859
+ };
7860
+ try {
7861
+ const user = await sibling.request({
7862
+ uri: "/users/me",
7863
+ tag: REQUEST_TAG.accessResolveActor
7864
+ }), id = usableId(user);
7865
+ return sibling.requireGlobalPrincipal && id !== void 0 && classifyPrincipalId(id).namespace === "project" ? {
7866
+ user: void 0,
7867
+ reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
7868
+ } : {
7869
+ user: user
7870
+ };
7871
+ } catch (err) {
7872
+ return {
7873
+ user: void 0,
7874
+ reason: `global-host /users/me failed: ${errorMessage(err)}`,
7875
+ cause: err
7876
+ };
7877
+ }
7878
+ }
7879
+
7880
+ function globalHostRequestOf(client) {
7881
+ if (typeof client.withConfig != "function") return {
7882
+ reason: "the client cannot reach the global API host (no withConfig)"
7883
+ };
7884
+ const hostResolution = resolveGlobalApiHost(client);
7885
+ try {
7886
+ const globalClient = client.withConfig({
7887
+ useProjectHostname: !1,
7888
+ apiVersion: ENGINE_API_VERSION,
7889
+ ...hostResolution.apiHost === void 0 ? {} : {
7890
+ apiHost: hostResolution.apiHost
7891
+ }
7892
+ }), request = lazyRequest(globalClient);
7893
+ return request === void 0 ? {
7894
+ reason: "the global-host sibling client cannot issue requests"
7895
+ } : {
7896
+ request: request,
7897
+ requireGlobalPrincipal: hostResolution.requireGlobalPrincipal
7898
+ };
7899
+ } catch (err) {
7900
+ return {
7901
+ reason: `building the global-host sibling client failed: ${errorMessage(err)}`,
7902
+ cause: err
7903
+ };
7904
+ }
7905
+ }
7906
+
7907
+ function resolveGlobalApiHost(client) {
7908
+ if (typeof client.config != "function") return {
7909
+ requireGlobalPrincipal: !1
7910
+ };
7911
+ const apiHost = client.config().apiHost;
7912
+ if (apiHost === void 0) return {
7913
+ requireGlobalPrincipal: !1
7914
+ };
7915
+ let parsed;
7916
+ try {
7917
+ parsed = new URL(apiHost);
7918
+ } catch {
7919
+ return {
7920
+ requireGlobalPrincipal: !0
7921
+ };
7922
+ }
7923
+ if (/^api\.sanity\.(io|work)$/.test(parsed.hostname)) return {
7924
+ requireGlobalPrincipal: !1
7925
+ };
7926
+ const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
7927
+ return match === null ? {
7928
+ requireGlobalPrincipal: !0
7929
+ } : (parsed.hostname = `api.sanity.${match[1]}`, {
7930
+ apiHost: parsed.origin,
7931
+ requireGlobalPrincipal: !0
7932
+ });
7933
+ }
7934
+
7935
+ async function fetchGrantsCached(requestFn, resourcePath) {
7936
+ try {
7937
+ return await fetchGrants({
7938
+ client: {
7939
+ request: requestFn
7940
+ },
7941
+ resourcePath: resourcePath
7942
+ });
7943
+ } catch (err) {
7944
+ 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)}`);
7945
+ return;
7946
+ }
7947
+ }
7948
+
7949
+ function projectIdOf(client) {
7950
+ if (typeof client.config != "function") return;
7951
+ const projectId = client.config().projectId;
7952
+ return typeof projectId == "string" && projectId.length > 0 ? projectId : void 0;
7953
+ }
7954
+
7955
+ function cachedAttributes(args) {
7956
+ const projectId = projectIdOf(args.client);
7957
+ return projectId === void 0 ? Promise.resolve(void 0) : resolveOrganizationId({
7958
+ client: args.client,
7959
+ requestFn: args.requestFn,
7960
+ projectId: projectId
7961
+ }).then(orgId => {
7962
+ if (orgId !== void 0) return cachedByKey({
7963
+ store: attributesCache,
7964
+ client: args.client,
7965
+ key: orgId,
7966
+ evictOnRejection: !0,
7967
+ load: () => fetchAttributesCached({
7968
+ client: args.client,
7969
+ orgId: orgId
7970
+ })
7971
+ });
7972
+ });
7973
+ }
7974
+
7975
+ async function resolveOrganizationId(args) {
7976
+ const {client: client, requestFn: requestFn, projectId: projectId} = args;
7977
+ return cachedByKey({
7978
+ store: orgIdCache,
7979
+ client: client,
7980
+ key: projectId,
7981
+ evictOnRejection: !0,
7982
+ load: async () => {
7983
+ try {
7984
+ const project = await requestFn({
7985
+ uri: `/projects/${encodeURIComponent(projectId)}`,
7986
+ tag: REQUEST_TAG.accessResolveOrg
7987
+ });
7988
+ if (!isRecord(project)) return;
7989
+ const orgId = project.organizationId;
7990
+ return typeof orgId == "string" && orgId.length > 0 ? orgId : void 0;
7991
+ } catch (err) {
7992
+ const status = httpStatusOf(err);
7993
+ if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
7994
+ throw new Error(`workflow: failed to resolve organizationId for project "${projectId}"; advisory $attributes cannot be bound. Original error: ${errorMessage(err)}`, {
7995
+ cause: err
7996
+ });
7997
+ }
7998
+ }
7999
+ });
8000
+ }
8001
+
8002
+ const ATTRIBUTES_FETCH_LIMIT = 100, EXPECTED_ATTRIBUTES_ABSENCE = /* @__PURE__ */ new Set([ 401, 402, 403, 404 ]);
8003
+
8004
+ function httpStatusOf(err) {
8005
+ if (!isRecord(err)) return;
8006
+ const status = err.statusCode;
8007
+ return typeof status == "number" ? status : void 0;
8008
+ }
8009
+
8010
+ async function fetchAttributesCached(args) {
8011
+ const {client: client, orgId: orgId} = args, sibling = globalHostRequestOf(client);
8012
+ if ("reason" in sibling) {
8013
+ console.warn(`workflow: skipped org attributes fetch (${sibling.reason}); advisory $attributes stays undefined (conditions referencing it fail closed).`);
8014
+ return;
8015
+ }
8016
+ try {
8017
+ const response = await sibling.request({
8018
+ uri: `/organizations/${encodeURIComponent(orgId)}/users/me/attributes?limit=${ATTRIBUTES_FETCH_LIMIT}`,
8019
+ tag: REQUEST_TAG.accessAttributes
8020
+ }), envelope = isRecord(response) ? response : void 0;
8021
+ if (envelope?.hasMore === !0) {
8022
+ const page = Array.isArray(envelope.attributes) ? envelope.attributes : [];
8023
+ 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.`);
8024
+ }
8025
+ const normalized = normalizeUserAttributes(response);
8026
+ return normalized === void 0 && console.warn(`workflow: org attributes response for organization "${orgId}" was unusable; advisory $attributes stays undefined (conditions referencing it fail closed).`),
8027
+ normalized;
8028
+ } catch (err) {
8029
+ const status = httpStatusOf(err);
8030
+ if (status !== void 0 && EXPECTED_ATTRIBUTES_ABSENCE.has(status)) return;
8031
+ throw new Error(`workflow: failed to fetch org attributes for organization "${orgId}". Original error: ${errorMessage(err)}`, {
8032
+ cause: err
8033
+ });
7166
8034
  }
7167
- if (res.type === "canvas") return `/canvases/${res.id}/acl`;
7168
8035
  }
7169
8036
 
7170
- async function fetchGrants(args) {
7171
- const {client: client, resourcePath: resourcePath, signal: signal} = args;
7172
- return client.request({
7173
- url: resourcePath,
7174
- tag: REQUEST_TAG.accessGrants,
7175
- ...signal ? {
7176
- signal: signal
8037
+ function callerBoundVars(args) {
8038
+ const vars = {
8039
+ ...args.can !== void 0 ? {
8040
+ can: args.can
8041
+ } : {},
8042
+ ...args.attributes !== void 0 ? {
8043
+ attributes: args.attributes
7177
8044
  } : {}
7178
- });
8045
+ };
8046
+ return Object.keys(vars).length > 0 ? vars : void 0;
7179
8047
  }
7180
8048
 
7181
- async function advisoryCanForCall(args) {
7182
- const actor = args.options?.actor;
7183
- if (!(args.options?.grants === void 0 || actor === void 0)) return advisoryCan({
8049
+ async function callerBoundVarsForCall(args) {
8050
+ const can = await advisoryCanForCall({
7184
8051
  instance: args.instance,
7185
- identity: lakePrincipalId({
7186
- actor: actor,
7187
- localPrincipalId: args.options.localPrincipalId
7188
- }),
7189
- grants: args.options.grants
7190
- });
7191
- }
7192
-
7193
- async function advisoryCan({instance: instance, identity: identity, grants: grants}) {
7194
- if (grants === void 0) return;
7195
- const can = {};
7196
- for (const permission of DOCUMENT_VALUE_PERMISSIONS) can[permission] = await grantsPermissionOn({
7197
- document: instance,
7198
- grants: grants,
7199
- permission: permission,
7200
- userId: identity
8052
+ options: args.options
8053
+ }), attributes = args.options?.attributes !== void 0 ? args.options.attributes : await resolveUserAttributes(args.client);
8054
+ return callerBoundVars({
8055
+ ...can !== void 0 ? {
8056
+ can: can
8057
+ } : {},
8058
+ ...attributes !== void 0 ? {
8059
+ attributes: attributes
8060
+ } : {}
7201
8061
  });
7202
- return can;
7203
8062
  }
7204
8063
 
7205
8064
  function requirementDescriptor(requirement) {
@@ -7322,7 +8181,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
7322
8181
  }
7323
8182
  });
7324
8183
  if (action.filter !== void 0) {
7325
- const can = await advisoryCanForCall({
8184
+ const vars = await callerBoundVarsForCall({
8185
+ client: ctx.client,
7326
8186
  instance: ctx.instance,
7327
8187
  options: options
7328
8188
  });
@@ -7334,10 +8194,8 @@ async function resolveActionCommit({ctx: ctx, activityName: activityName, action
7334
8194
  ...actor !== void 0 ? {
7335
8195
  actor: actor
7336
8196
  } : {},
7337
- ...can !== void 0 ? {
7338
- vars: {
7339
- can: can
7340
- }
8197
+ ...vars !== void 0 ? {
8198
+ vars: vars
7341
8199
  } : {}
7342
8200
  }
7343
8201
  })) throw new ActionDisabledError({
@@ -7410,7 +8268,9 @@ async function applyActionFire({ctx: ctx, mutation: mutation, activity: activity
7410
8268
  self: selfGdr(ctx.instance),
7411
8269
  now: ctx.now,
7412
8270
  snapshot: ctx.snapshot,
7413
- refSurface: ctx.refSurface
8271
+ refSurface: ctx.refSurface,
8272
+ memberRoles: ctx.memberRoles,
8273
+ roleAliases: ctx.definition.roleAliases
7414
8274
  });
7415
8275
  if (await queueEffects({
7416
8276
  ctx: ctx,
@@ -7593,6 +8453,8 @@ async function primeInitialStage(args) {
7593
8453
  stage: stage,
7594
8454
  now: now,
7595
8455
  refSurface: refSurface,
8456
+ memberRoles: ctx.memberRoles,
8457
+ roleAliases: ctx.definition.roleAliases,
7596
8458
  recordDiscard: recordFieldDiscards({
7597
8459
  target: discards,
7598
8460
  scope: "stage",
@@ -7652,7 +8514,7 @@ async function primeInitialStage(args) {
7652
8514
 
7653
8515
  const CASCADE_LIMIT = 100;
7654
8516
 
7655
- async function runCascadeHop({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts, instance: instance}) {
8517
+ async function runCascadeHop({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts, instance: instance}) {
7656
8518
  const contextOptions = {
7657
8519
  clientForGdr: clientForGdr,
7658
8520
  refSurface: refSurface,
@@ -7673,7 +8535,8 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
7673
8535
  } : {},
7674
8536
  ...settlingCohorts ? {
7675
8537
  settlingCohorts: settlingCohorts
7676
- } : {}
8538
+ } : {},
8539
+ memberRolesLoader: memberRolesLoader
7677
8540
  }, ctx = instance === void 0 ? await loadContext({
7678
8541
  client: client,
7679
8542
  instanceId: instanceId,
@@ -7712,7 +8575,7 @@ async function runCascadeHop({client: client, instanceId: instanceId, actor: act
7712
8575
  });
7713
8576
  }
7714
8577
 
7715
- async function cascadeAutoTransitions({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts}) {
8578
+ async function cascadeAutoTransitions({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay, settlingCohorts: settlingCohorts}) {
7716
8579
  let count = 0;
7717
8580
  for (;;) {
7718
8581
  const drained = await drainCondemnedChildren({
@@ -7721,6 +8584,7 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
7721
8584
  actor: actor,
7722
8585
  clientForGdr: clientForGdr,
7723
8586
  refSurface: refSurface,
8587
+ memberRolesLoader: memberRolesLoader,
7724
8588
  clock: clock,
7725
8589
  executionContext: executionContext,
7726
8590
  telemetry: telemetry
@@ -7731,6 +8595,7 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
7731
8595
  actor: actor,
7732
8596
  clientForGdr: clientForGdr,
7733
8597
  refSurface: refSurface,
8598
+ memberRolesLoader: memberRolesLoader,
7734
8599
  clock: clock,
7735
8600
  executionContext: executionContext,
7736
8601
  telemetry: telemetry,
@@ -7747,7 +8612,7 @@ async function cascadeAutoTransitions({client: client, instanceId: instanceId, a
7747
8612
  }
7748
8613
  }
7749
8614
 
7750
- async function drainCondemnedChildren({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining = /* @__PURE__ */ new Set, instance: preloadedInstance}) {
8615
+ async function drainCondemnedChildren({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining = /* @__PURE__ */ new Set, instance: preloadedInstance}) {
7751
8616
  if (draining.has(instanceId)) return {
7752
8617
  instance: preloadedInstance,
7753
8618
  drained: !1
@@ -7770,6 +8635,7 @@ async function drainCondemnedChildren({client: client, instanceId: instanceId, a
7770
8635
  actor: actor,
7771
8636
  clientForGdr: clientForGdr,
7772
8637
  refSurface: refSurface,
8638
+ memberRolesLoader: memberRolesLoader,
7773
8639
  clock: clock,
7774
8640
  executionContext: executionContext,
7775
8641
  telemetry: telemetry,
@@ -7787,7 +8653,7 @@ async function drainCondemnedChildren({client: client, instanceId: instanceId, a
7787
8653
  };
7788
8654
  }
7789
8655
 
7790
- async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining}) {
8656
+ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, draining: draining}) {
7791
8657
  const childId = toBareId(row.ref.id);
7792
8658
  try {
7793
8659
  const result = await abortInstance({
@@ -7800,6 +8666,7 @@ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, a
7800
8666
  } : {},
7801
8667
  clientForGdr: clientForGdr,
7802
8668
  refSurface: refSurface,
8669
+ memberRolesLoader: memberRolesLoader,
7803
8670
  ...clock ? {
7804
8671
  clock: clock
7805
8672
  } : {},
@@ -7817,6 +8684,7 @@ async function settleCondemnedRow({client: client, ownerId: ownerId, row: row, a
7817
8684
  actor: actor,
7818
8685
  clientForGdr: clientForGdr,
7819
8686
  refSurface: refSurface,
8687
+ memberRolesLoader: memberRolesLoader,
7820
8688
  clock: clock,
7821
8689
  executionContext: executionContext,
7822
8690
  telemetry: telemetry,
@@ -7967,7 +8835,8 @@ async function buildCascadeStepContext(args, instance) {
7967
8835
  } : {},
7968
8836
  ...args.settlingCohorts ? {
7969
8837
  settlingCohorts: args.settlingCohorts
7970
- } : {}
8838
+ } : {},
8839
+ memberRolesLoader: args.memberRolesLoader
7971
8840
  });
7972
8841
  }
7973
8842
 
@@ -8195,6 +9064,7 @@ function spawnStepArgs(ctx, args) {
8195
9064
  actor: args.actor,
8196
9065
  clientForGdr: ctx.clientForGdr,
8197
9066
  refSurface: ctx.refSurface,
9067
+ memberRolesLoader: ctx.memberRolesLoader,
8198
9068
  clock: ctx.clock,
8199
9069
  executionContext: ctx.executionContext,
8200
9070
  telemetry: ctx.telemetry,
@@ -8336,7 +9206,11 @@ function validateEffectOutputs(args) {
8336
9206
  issues.push(`"${key}" is not a declared output`);
8337
9207
  continue;
8338
9208
  }
8339
- const check = effectOutputCheck(shape, value);
9209
+ const check = effectOutputCheck({
9210
+ shape: shape,
9211
+ value: value,
9212
+ eligibility: args
9213
+ });
8340
9214
  "issues" in check ? issues.push(...check.issues.map(i => `"${key}": ${i}`)) : normalized[key] = check.output;
8341
9215
  }
8342
9216
  if (issues.length > 0) throw new EffectOutputsInvalidError({
@@ -8346,7 +9220,8 @@ function validateEffectOutputs(args) {
8346
9220
  return normalized;
8347
9221
  }
8348
9222
 
8349
- function effectOutputCheck(shape, value) {
9223
+ function effectOutputCheck(args) {
9224
+ const {shape: shape, value: value, eligibility: eligibility} = args;
8350
9225
  return parseFieldValue({
8351
9226
  entryType: shape.type,
8352
9227
  value: value,
@@ -8361,7 +9236,12 @@ function effectOutputCheck(shape, value) {
8361
9236
  } : {},
8362
9237
  ...shape.validation !== void 0 ? {
8363
9238
  validation: shape.validation
8364
- } : {}
9239
+ } : {},
9240
+ ...shape.roles !== void 0 ? {
9241
+ roles: shape.roles
9242
+ } : {},
9243
+ memberRoles: eligibility.memberRoles,
9244
+ roleAliases: eligibility.roleAliases
8365
9245
  });
8366
9246
  }
8367
9247
 
@@ -8384,7 +9264,7 @@ function requirePendingEffect(instance, effectKey) {
8384
9264
  });
8385
9265
  }
8386
9266
 
8387
- function validateCompletionInput({pending: pending, definition: definition, status: status, ops: ops, outputs: outputs}) {
9267
+ function validateCompletionInput({pending: pending, definition: definition, status: status, ops: ops, outputs: outputs, memberRoles: memberRoles, roleAliases: roleAliases}) {
8388
9268
  if (status === "failed" && ops !== void 0 && ops.length > 0) throw new EffectOpsInvalidError({
8389
9269
  effect: pending.name,
8390
9270
  issues: [ "ops cannot accompany a failed completion — field.set the outcome on a done completion instead" ]
@@ -8396,7 +9276,9 @@ function validateCompletionInput({pending: pending, definition: definition, stat
8396
9276
  const normalizedOutputs = outputs !== void 0 ? validateEffectOutputs({
8397
9277
  outputs: outputs,
8398
9278
  declared: findEffect(definition, pending.name)?.outputs ?? [],
8399
- effectName: pending.name
9279
+ effectName: pending.name,
9280
+ memberRoles: memberRoles,
9281
+ roleAliases: roleAliases
8400
9282
  }) : void 0;
8401
9283
  return {
8402
9284
  ops: ops !== void 0 ? validateEffectOps(ops, pending.name) : [],
@@ -8415,7 +9297,9 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
8415
9297
  definition: ctx.definition,
8416
9298
  status: status,
8417
9299
  ops: ops,
8418
- outputs: outputs
9300
+ outputs: outputs,
9301
+ memberRoles: ctx.memberRoles,
9302
+ roleAliases: ctx.definition.roleAliases
8419
9303
  }), mutation = startMutation(ctx.instance);
8420
9304
  recordProcessedRequest({
8421
9305
  mutation: mutation,
@@ -8446,7 +9330,9 @@ async function commitCompleteEffect({ctx: ctx, effectKey: effectKey, status: sta
8446
9330
  self: selfGdr(ctx.instance),
8447
9331
  now: ranAt,
8448
9332
  snapshot: ctx.snapshot,
8449
- refSurface: ctx.refSurface
9333
+ refSurface: ctx.refSurface,
9334
+ memberRoles: ctx.memberRoles,
9335
+ roleAliases: ctx.definition.roleAliases
8450
9336
  }), needsGuardRefresh = wroteEffectOutputs || ranOps.some(isFieldOp);
8451
9337
  return await persistThenMaybeRefresh({
8452
9338
  ctx: ctx,
@@ -8615,7 +9501,9 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
8615
9501
  self: selfGdr(ctx.instance),
8616
9502
  now: ctx.now,
8617
9503
  snapshot: ctx.snapshot,
8618
- refSurface: ctx.refSurface
9504
+ refSurface: ctx.refSurface,
9505
+ memberRoles: ctx.memberRoles,
9506
+ roleAliases: ctx.definition.roleAliases
8619
9507
  }), await persistThenMaybeRefresh({
8620
9508
  ctx: ctx,
8621
9509
  mutation: mutation,
@@ -8623,309 +9511,66 @@ async function commitReport({ctx: ctx, effectKey: effectKey, claimToken: claimTo
8623
9511
  didChangeState: !0
8624
9512
  }), {
8625
9513
  effectKey: effectKey,
8626
- effect: pending.name
8627
- };
8628
- }
8629
-
8630
- const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
8631
-
8632
- function isResetActivityTarget(value) {
8633
- return RESET_ACTIVITY_TARGETS.includes(value);
8634
- }
8635
-
8636
- async function resetActivity(args) {
8637
- const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
8638
- client: client,
8639
- instanceId: instanceId,
8640
- options: options
8641
- });
8642
- return commitResetActivity({
8643
- ctx: ctx,
8644
- activity: activity,
8645
- to: to,
8646
- requestRecord: requestRecord,
8647
- actor: options?.actor
8648
- });
8649
- }
8650
-
8651
- async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
8652
- if (assertRequestUnprocessed({
8653
- instance: ctx.instance,
8654
- record: requestRecord,
8655
- now: ctx.now
8656
- }), isTerminal(ctx)) return {
8657
- fired: !1
8658
- };
8659
- const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
8660
- if (openStage2 === void 0 || entry === void 0) throw new ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
8661
- const from = entry.status;
8662
- if (from === to) return {
8663
- fired: !1
8664
- };
8665
- 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.`);
8666
- return recordProcessedRequest({
8667
- mutation: mutation,
8668
- record: requestRecord,
8669
- now: ctx.now
8670
- }), applyActivityStatusChange({
8671
- entry: entry,
8672
- history: mutation.history,
8673
- stage: openStage2.name,
8674
- to: to,
8675
- at: ctx.now,
8676
- ...actor !== void 0 ? {
8677
- actor: actor
8678
- } : {}
8679
- }), await persist(ctx, mutation), {
8680
- fired: !0,
8681
- stage: openStage2.name,
8682
- activity: activity,
8683
- from: from,
8684
- to: to
8685
- };
8686
- }
8687
-
8688
- const actorCache = /* @__PURE__ */ new WeakMap, grantsCache = /* @__PURE__ */ new WeakMap;
8689
-
8690
- async function resolveAccess(taggedClient, args = {}) {
8691
- const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
8692
- 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).");
8693
- const grantsPromise = args.grantsFromPath !== void 0 ? cachedGrants({
8694
- client: client,
8695
- requestFn: requestFn,
8696
- resourcePath: args.grantsFromPath
8697
- }) : Promise.resolve(void 0), [identity, grants] = await Promise.all([ cachedActor(client, requestFn), grantsPromise ]);
8698
- 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.");
8699
- return {
8700
- actor: identity.actor,
8701
- ...identity.localPrincipalId !== void 0 ? {
8702
- localPrincipalId: identity.localPrincipalId
8703
- } : {},
8704
- ...grants !== void 0 ? {
8705
- grants: grants
8706
- } : {}
8707
- };
8708
- }
8709
-
8710
- function cachedActor(client, requestFn) {
8711
- const cached = actorCache.get(client);
8712
- if (cached !== void 0) return cached;
8713
- const pending = fetchActor(client, requestFn).catch(err => {
8714
- throw actorCache.get(client) === pending && actorCache.delete(client), err;
8715
- });
8716
- return actorCache.set(client, pending), pending;
8717
- }
8718
-
8719
- function grantsForClientPath(taggedClient, resourcePath) {
8720
- const client = unwrapRequestTag(taggedClient), requestFn = lazyRequest(client);
8721
- return requestFn === void 0 ? Promise.resolve(void 0) : cachedGrants({
8722
- client: client,
8723
- requestFn: requestFn,
8724
- resourcePath: resourcePath
8725
- });
8726
- }
8727
-
8728
- function lazyRequest(client) {
8729
- return client.request === void 0 ? void 0 : opts => client.request(opts);
8730
- }
8731
-
8732
- function cachedGrants({client: client, requestFn: requestFn, resourcePath: resourcePath}) {
8733
- let byPath = grantsCache.get(client);
8734
- byPath === void 0 && (byPath = /* @__PURE__ */ new Map, grantsCache.set(client, byPath));
8735
- let cached = byPath.get(resourcePath);
8736
- return cached === void 0 && (cached = fetchGrantsCached(requestFn, resourcePath),
8737
- byPath.set(resourcePath, cached)), cached;
8738
- }
8739
-
8740
- async function fetchActor(client, requestFn) {
8741
- 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;
8742
- if (sessionId === void 0) return;
8743
- const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
8744
- client: client,
8745
- sessionId: sessionId,
8746
- resourceId: resourceId
8747
- }) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
8748
- refuseProjectScopedActor({
8749
- id: id,
8750
- globalUser: globalUser,
8751
- globalHostId: globalHostId,
8752
- bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
8753
- });
8754
- const roleNames = roleNamesFor(resourceUser, globalUser);
8755
- return {
8756
- actor: {
8757
- kind: "person",
8758
- id: id,
8759
- ...roleNames.length > 0 ? {
8760
- roles: roleNames
8761
- } : {}
8762
- },
8763
- ...resourceId !== void 0 && resourceId !== id ? {
8764
- localPrincipalId: resourceId
8765
- } : {}
8766
- };
8767
- }
8768
-
8769
- function roleNamesFor(resourceUser, globalUser) {
8770
- return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
8771
- }
8772
-
8773
- const NO_BRIDGE = {
8774
- status: "not-applicable"
8775
- };
8776
-
8777
- function globalRouteReason(globalUser, globalHostId) {
8778
- return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
8779
- }
8780
-
8781
- async function bridgeProjectPrincipal(args) {
8782
- const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
8783
- return classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project" ? {
8784
- status: "unavailable",
8785
- reason: "no project-scoped principal from the resource host to address the directory with"
8786
- } : directoryGlobalId({
8787
- client: client,
8788
- principalId: resourceId
8789
- });
8790
- }
8791
-
8792
- async function directoryGlobalId(args) {
8793
- const {client: client, principalId: principalId} = args, projectId = typeof client.config == "function" ? client.config().projectId : void 0;
8794
- if (projectId === void 0) return {
8795
- status: "unavailable",
8796
- reason: "the client reports no projectId, so its user directory has no address"
8797
- };
8798
- const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
8799
- if (lookup.status !== "resolved") return {
8800
- status: "unavailable",
8801
- reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
8802
- ...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
8803
- cause: lookup.cause
8804
- } : {}
8805
- };
8806
- const globalId = directoryBridgeId(lookup.user.sanityUserId);
8807
- return globalId === void 0 ? {
8808
- status: "unavailable",
8809
- reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
8810
- } : {
8811
- status: "resolved",
8812
- globalId: globalId
8813
- };
8814
- }
8815
-
8816
- function refuseProjectScopedActor(args) {
8817
- const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
8818
- if (classifyPrincipalId(id).namespace !== "project") return;
8819
- const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
8820
- bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
8821
- const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
8822
- 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 : {
8823
- cause: cause
8824
- });
9514
+ effect: pending.name
9515
+ };
8825
9516
  }
8826
9517
 
8827
- function usableId(user) {
8828
- if (!(!user || typeof user.id != "string" || user.id.length === 0)) return user.id;
8829
- }
9518
+ const RESET_ACTIVITY_TARGETS = [ "active", "skipped" ];
8830
9519
 
8831
- async function fetchCurrentUser(requestFn, hostDescription) {
8832
- try {
8833
- return await requestFn({
8834
- uri: "/users/me",
8835
- tag: REQUEST_TAG.accessResolveActor
8836
- });
8837
- } catch (err) {
8838
- 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.`, {
8839
- cause: err
8840
- });
8841
- }
9520
+ function isResetActivityTarget(value) {
9521
+ return RESET_ACTIVITY_TARGETS.includes(value);
8842
9522
  }
8843
9523
 
8844
- async function fetchGlobalUser(client) {
8845
- if (typeof client.withConfig != "function") return {
8846
- user: void 0,
8847
- reason: "the client cannot reach the global API host (no withConfig)"
8848
- };
8849
- let globalRequest, globalClient;
8850
- const hostResolution = resolveGlobalApiHost(client);
8851
- try {
8852
- globalClient = client.withConfig({
8853
- useProjectHostname: !1,
8854
- ...hostResolution.apiHost === void 0 ? {} : {
8855
- apiHost: hostResolution.apiHost
8856
- }
8857
- }), globalRequest = lazyRequest(globalClient);
8858
- } catch (err) {
8859
- return {
8860
- user: void 0,
8861
- reason: `building the global-host sibling client failed: ${errorMessage(err)}`,
8862
- cause: err
8863
- };
8864
- }
8865
- if (globalRequest === void 0) return {
8866
- user: void 0,
8867
- reason: "the global-host sibling client cannot issue requests"
8868
- };
8869
- try {
8870
- const user = await globalRequest({
8871
- uri: "/users/me",
8872
- tag: REQUEST_TAG.accessResolveActor
8873
- }), id = usableId(user);
8874
- return hostResolution.requireGlobalPrincipal && id !== void 0 && classifyPrincipalId(id).namespace === "project" ? {
8875
- user: void 0,
8876
- reason: `global-host /users/me returned project-scoped principal "${id}"; the sibling client is still bound to a project API host`
8877
- } : {
8878
- user: user
8879
- };
8880
- } catch (err) {
8881
- return {
8882
- user: void 0,
8883
- reason: `global-host /users/me failed: ${errorMessage(err)}`,
8884
- cause: err
8885
- };
8886
- }
9524
+ async function resetActivity(args) {
9525
+ const {client: client, instanceId: instanceId, activity: activity, to: to, requestRecord: requestRecord, options: options} = args, ctx = await loadCallContext({
9526
+ client: client,
9527
+ instanceId: instanceId,
9528
+ options: options
9529
+ });
9530
+ return commitResetActivity({
9531
+ ctx: ctx,
9532
+ activity: activity,
9533
+ to: to,
9534
+ requestRecord: requestRecord,
9535
+ actor: options?.actor
9536
+ });
8887
9537
  }
8888
9538
 
8889
- function resolveGlobalApiHost(client) {
8890
- if (typeof client.config != "function") return {
8891
- requireGlobalPrincipal: !1
9539
+ async function commitResetActivity({ctx: ctx, activity: activity, to: to, requestRecord: requestRecord, actor: actor}) {
9540
+ if (assertRequestUnprocessed({
9541
+ instance: ctx.instance,
9542
+ record: requestRecord,
9543
+ now: ctx.now
9544
+ }), isTerminal(ctx)) return {
9545
+ fired: !1
8892
9546
  };
8893
- const apiHost = client.config().apiHost;
8894
- if (apiHost === void 0) return {
8895
- requireGlobalPrincipal: !1
9547
+ const mutation = startMutation(ctx.instance), openStage2 = findOpenStageEntry(mutation), entry = findCurrentActivityEntry(mutation, activity);
9548
+ if (openStage2 === void 0 || entry === void 0) throw new ContractViolationError(`resetActivity: activity "${activity}" is not in the current stage of instance "${ctx.instance._id}"`);
9549
+ const from = entry.status;
9550
+ if (from === to) return {
9551
+ fired: !1
8896
9552
  };
8897
- let parsed;
8898
- try {
8899
- parsed = new URL(apiHost);
8900
- } catch {
8901
- return {
8902
- requireGlobalPrincipal: !0
8903
- };
8904
- }
8905
- if (/^api\.sanity\.(io|work)$/.test(parsed.hostname)) return {
8906
- requireGlobalPrincipal: !1
9553
+ 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.`);
9554
+ return recordProcessedRequest({
9555
+ mutation: mutation,
9556
+ record: requestRecord,
9557
+ now: ctx.now
9558
+ }), applyActivityStatusChange({
9559
+ entry: entry,
9560
+ history: mutation.history,
9561
+ stage: openStage2.name,
9562
+ to: to,
9563
+ at: ctx.now,
9564
+ ...actor !== void 0 ? {
9565
+ actor: actor
9566
+ } : {}
9567
+ }), await persist(ctx, mutation), {
9568
+ fired: !0,
9569
+ stage: openStage2.name,
9570
+ activity: activity,
9571
+ from: from,
9572
+ to: to
8907
9573
  };
8908
- const match = /^[^.]+\.api\.sanity\.(io|work)$/.exec(parsed.hostname);
8909
- return match === null ? {
8910
- requireGlobalPrincipal: !0
8911
- } : (parsed.hostname = `api.sanity.${match[1]}`, {
8912
- apiHost: parsed.origin,
8913
- requireGlobalPrincipal: !0
8914
- });
8915
- }
8916
-
8917
- async function fetchGrantsCached(requestFn, resourcePath) {
8918
- try {
8919
- return await fetchGrants({
8920
- client: {
8921
- request: requestFn
8922
- },
8923
- resourcePath: resourcePath
8924
- });
8925
- } catch (err) {
8926
- 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)}`);
8927
- return;
8928
- }
8929
9574
  }
8930
9575
 
8931
9576
  const REPLAY_SURFACE = {
@@ -9109,7 +9754,7 @@ async function resourceActorId(client) {
9109
9754
  async function evaluateInstance(args) {
9110
9755
  const {client: client, tag: tag, workflowResource: workflowResource, instanceId: instanceId, resourceClients: resourceClients} = args, now = (args.clock ?? wallClock)();
9111
9756
  validateTag(tag);
9112
- const [access, instance] = await Promise.all([ resolveAccess(client, {
9757
+ const [access, instance, attributes] = await Promise.all([ resolveAccess(client, {
9113
9758
  ...args.grantsFromPath !== void 0 ? {
9114
9759
  grantsFromPath: args.grantsFromPath
9115
9760
  } : {}
@@ -9117,7 +9762,7 @@ async function evaluateInstance(args) {
9117
9762
  client: client,
9118
9763
  instanceId: instanceId,
9119
9764
  tag: tag
9120
- }) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
9765
+ }), resolveUserAttributes(client) ]), {actor: actor, grants: grants, localPrincipalId: localPrincipalId} = access, definition = parseDefinitionSnapshot(instance), clientForGdr = buildClientForGdr({
9121
9766
  client: client,
9122
9767
  workflowResource: workflowResource,
9123
9768
  resourceClients: resourceClients
@@ -9142,6 +9787,9 @@ async function evaluateInstance(args) {
9142
9787
  } : {},
9143
9788
  ...grants !== void 0 ? {
9144
9789
  grants: grants
9790
+ } : {},
9791
+ ...attributes !== void 0 ? {
9792
+ attributes: attributes
9145
9793
  } : {}
9146
9794
  });
9147
9795
  }
@@ -9156,6 +9804,33 @@ function memoizedByName(render) {
9156
9804
  };
9157
9805
  }
9158
9806
 
9807
+ async function callerBoundProjectionScopes(args) {
9808
+ const can = await advisoryCan({
9809
+ instance: args.instance,
9810
+ identity: args.identity,
9811
+ grants: args.grants
9812
+ }), vars = callerBoundVars({
9813
+ ...can !== void 0 ? {
9814
+ can: can
9815
+ } : {},
9816
+ ...args.attributes !== void 0 ? {
9817
+ attributes: args.attributes
9818
+ } : {}
9819
+ }), opts = {
9820
+ actor: args.actor,
9821
+ ...vars !== void 0 ? {
9822
+ vars: vars
9823
+ } : {}
9824
+ };
9825
+ return {
9826
+ scope: await renderConditionScope(args.scopeSource, opts),
9827
+ scopeForActivity: memoizedByName(activityName => renderConditionScope(args.scopeSource, {
9828
+ activityName: activityName,
9829
+ ...opts
9830
+ }))
9831
+ };
9832
+ }
9833
+
9159
9834
  function currentStageOf(instance, definition) {
9160
9835
  try {
9161
9836
  return findStage(definition, instance.currentStage);
@@ -9181,7 +9856,7 @@ async function explainSite(args) {
9181
9856
  }
9182
9857
 
9183
9858
  async function evaluateFromSnapshot(args) {
9184
- 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({
9859
+ 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({
9185
9860
  instance: instance,
9186
9861
  definition: definition,
9187
9862
  snapshot: snapshot,
@@ -9198,22 +9873,14 @@ async function evaluateFromSnapshot(args) {
9198
9873
  }, anchorIdentity = lakePrincipalId({
9199
9874
  actor: actor,
9200
9875
  localPrincipalId: args.localPrincipalId
9201
- }), can = await advisoryCan({
9202
- instance: instance,
9203
- identity: anchorIdentity,
9204
- grants: grants
9205
- }), scope = await renderConditionScope(scopeSource, {
9876
+ }), {scope: scope, scopeForActivity: scopeForActivity} = await callerBoundProjectionScopes({
9877
+ scopeSource: scopeSource,
9206
9878
  actor: actor,
9207
- vars: {
9208
- can: can
9209
- }
9210
- }), scopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
9211
- activityName: activityName,
9212
- actor: actor,
9213
- vars: {
9214
- can: can
9215
- }
9216
- })), cascadeScopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
9879
+ instance: instance,
9880
+ grants: grants,
9881
+ attributes: attributes,
9882
+ identity: anchorIdentity
9883
+ }), cascadeScopeForActivity = memoizedByName(activityName => renderConditionScope(scopeSource, {
9217
9884
  activityName: activityName
9218
9885
  })), currentActivityEntries = findOpenStageEntry(instance)?.activities ?? [], guardDenial = await instanceGuardReason({
9219
9886
  instance: instance,
@@ -9262,6 +9929,7 @@ async function evaluateFromSnapshot(args) {
9262
9929
  }
9263
9930
  const currentStage = {
9264
9931
  stage: stage,
9932
+ ...semanticsOf(stage),
9265
9933
  activities: activityEvaluations,
9266
9934
  transitions: transitionEvaluations,
9267
9935
  autonomy: stageAutonomy2
@@ -9278,6 +9946,7 @@ async function evaluateFromSnapshot(args) {
9278
9946
  return {
9279
9947
  instance: instance,
9280
9948
  definition: definition,
9949
+ ...semanticsOf(definition),
9281
9950
  actor: actor,
9282
9951
  currentStage: currentStage,
9283
9952
  pendingOnYou: pendingOnYou,
@@ -9329,6 +9998,12 @@ async function evaluateEditableFields(args) {
9329
9998
  ...site.validation !== void 0 ? {
9330
9999
  validation: site.validation
9331
10000
  } : {},
10001
+ ...site.roles !== void 0 ? {
10002
+ roles: site.roles,
10003
+ ...definition.roleAliases !== void 0 ? {
10004
+ roleAliases: definition.roleAliases
10005
+ } : {}
10006
+ } : {},
9332
10007
  value: value,
9333
10008
  editable: reason === void 0,
9334
10009
  ...reason !== void 0 ? {
@@ -9433,6 +10108,7 @@ async function evaluateActivity(args) {
9433
10108
  }));
9434
10109
  return {
9435
10110
  activity: activity,
10111
+ ...semanticsOf(activity),
9436
10112
  status: status,
9437
10113
  kind: deriveActivityKind(activity),
9438
10114
  classification: deriveExecutorClassification(activity),
@@ -9603,9 +10279,13 @@ function fireableActionVerdict({args: args, insights: insights}) {
9603
10279
  function actionEvaluationIdentity(action) {
9604
10280
  return {
9605
10281
  action: action,
9606
- ...action.semantics !== void 0 ? {
9607
- semantics: action.semantics
9608
- } : {}
10282
+ ...semanticsOf(action)
10283
+ };
10284
+ }
10285
+
10286
+ function semanticsOf(node) {
10287
+ return node.semantics === void 0 ? {} : {
10288
+ semantics: node.semantics
9609
10289
  };
9610
10290
  }
9611
10291
 
@@ -9674,23 +10354,63 @@ function idsArm(filter, params) {
9674
10354
  }
9675
10355
  }
9676
10356
 
9677
- function instancesQuery(args) {
9678
- const {tag: tag, filter: filter = {}} = args;
9679
- if (validateTag(tag), filter.limit !== void 0 && (!Number.isInteger(filter.limit) || filter.limit <= 0)) throw new ContractViolationError(`instancesQuery: limit must be a positive integer; got ${JSON.stringify(filter.limit)}`);
9680
- const conditions = [ `_type == "${WORKFLOW_INSTANCE_TYPE}"`, tagScopeFilter() ], params = {
9681
- tag: tag
9682
- };
10357
+ function beforeArm(filter, params) {
10358
+ const before = filter.before;
10359
+ if (before !== void 0) {
10360
+ if (filter.limit === void 0) throw new ContractViolationError("instancesQuery: `before` requires `limit` — a cursor pages the newest-first sliced read");
10361
+ if (before.id === "" || before.startedAt === "") throw new ContractViolationError(`instancesQuery: \`before\` needs a non-empty id and startedAt; got ${JSON.stringify(before)}`);
10362
+ return params.beforeStartedAt = before.startedAt, params.beforeId = before.id, "(startedAt < $beforeStartedAt || (startedAt == $beforeStartedAt && _id > $beforeId))";
10363
+ }
10364
+ }
10365
+
10366
+ function compiledConditions(filter, params) {
10367
+ if (filter.limit !== void 0 && (!Number.isInteger(filter.limit) || filter.limit <= 0)) throw new ContractViolationError(`instancesQuery: limit must be a positive integer; got ${JSON.stringify(filter.limit)}`);
10368
+ const conditions = [ `_type == "${WORKFLOW_INSTANCE_TYPE}"`, tagScopeFilter() ];
9683
10369
  filter.includeCompleted !== !0 && conditions.push(inFlightFilter()), filter.definition !== void 0 && (conditions.push("definition == $definition"),
9684
10370
  params.definition = filter.definition), filter.stage !== void 0 && (conditions.push("currentStage == $stage"),
9685
10371
  params.stage = filter.stage);
10372
+ const cursor = beforeArm(filter, params);
10373
+ cursor !== void 0 && conditions.push(cursor);
9686
10374
  const arms = [ documentArm(filter, params), idsArm(filter, params) ].filter(arm => arm !== void 0);
9687
- arms.length > 0 && conditions.push(`(${arms.join(" || ")})`);
9688
- const body = `*[${conditions.join(" && ")}]`;
9689
- return filter.limit !== void 0 ? {
9690
- query: `${body} | order(startedAt desc) [0...${filter.limit}]`,
10375
+ return arms.length > 0 && conditions.push(`(${arms.join(" || ")})`), conditions;
10376
+ }
10377
+
10378
+ function orderedSlice(filter) {
10379
+ return filter.limit !== void 0 ? ` | order(startedAt desc, _id asc) [0...${filter.limit}]` : " | order(startedAt asc, _id asc)";
10380
+ }
10381
+
10382
+ function instancesQuery(args) {
10383
+ const {tag: tag, filter: filter = {}} = args;
10384
+ validateTag(tag);
10385
+ const params = {
10386
+ tag: tag
10387
+ };
10388
+ return {
10389
+ query: `*[${compiledConditions(filter, params).join(" && ")}]${orderedSlice(filter)}`,
9691
10390
  params: params
9692
- } : {
9693
- query: `${body} | order(startedAt asc)`,
10391
+ };
10392
+ }
10393
+
10394
+ function instanceChangesQuery(args) {
10395
+ return validateTag(args.tag), {
10396
+ query: `*[_type == "${WORKFLOW_INSTANCE_TYPE}" && ${tagScopeFilter()}]`,
10397
+ params: {
10398
+ tag: args.tag
10399
+ }
10400
+ };
10401
+ }
10402
+
10403
+ const PREVIEW_FIELD_TYPES = [ "actor", "assignee", "assignees", "date", "datetime", "doc.ref", "doc.refs", "dueDate", "dueDatetime", "release.ref", "subject" ], PREVIEW_PROJECTION = `{\n _id, _type, modelVersion, minReaderModel, workflowResource, definition, pinnedVersion,\n currentStage, startedAt, completedAt, abortedAt, perspective, ancestors,\n "fields": fields[_type in $previewFieldTypes],\n "stages": stages[!defined(exitedAt) && name == ^.currentStage]{\n _key, name, enteredAt,\n "fields": fields[_type in $previewFieldTypes],\n "activities": activities[]{\n _key, name, status, completedBy,\n "fields": fields[_type in $previewFieldTypes]\n }\n },\n "claimedEffects": pendingEffects[defined(claim)]{name, title},\n "failedEffects": effectHistory[status == "failed"]{name, title}\n}`.replaceAll(/\s+/g, " ").trim();
10404
+
10405
+ function instancePreviewsQuery(args) {
10406
+ const {tag: tag, filter: filter = {}} = args;
10407
+ validateTag(tag);
10408
+ const params = {
10409
+ tag: tag,
10410
+ previewFieldTypes: PREVIEW_FIELD_TYPES
10411
+ };
10412
+ return {
10413
+ query: `*[${compiledConditions(filter, params).join(" && ")}]${orderedSlice(filter)} ${PREVIEW_PROJECTION}`,
9694
10414
  params: params
9695
10415
  };
9696
10416
  }
@@ -9875,6 +10595,11 @@ function hashDefinitionContent(def) {
9875
10595
  }
9876
10596
 
9877
10597
  function planDefinitionDeploy({def: def, latest: latest, target: target}) {
10598
+ assertRoleConstrainedAssignmentResource({
10599
+ context: "workflow.deployDefinitions",
10600
+ definition: def,
10601
+ workflowResource: target.workflowResource
10602
+ });
9878
10603
  const expanded = expandResourceAliases(def, target.resourceAliases), contentHash = hashDefinitionContent(expanded), unchanged = latest !== void 0 && latest.contentHash === contentHash, version = unchanged ? latest.version : (latest?.version ?? 0) + 1, docId = definitionDocId({
9879
10604
  tag: target.tag,
9880
10605
  definition: expanded.name,
@@ -10067,7 +10792,9 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
10067
10792
  self: selfGdr(ctx.instance),
10068
10793
  now: ctx.now,
10069
10794
  snapshot: ctx.snapshot,
10070
- refSurface: ctx.refSurface
10795
+ refSurface: ctx.refSurface,
10796
+ memberRoles: ctx.memberRoles,
10797
+ roleAliases: ctx.definition.roleAliases
10071
10798
  });
10072
10799
  return await persistThenMaybeRefresh({
10073
10800
  ctx: ctx,
@@ -10084,7 +10811,8 @@ async function commitEdit({ctx: ctx, target: target, mode: mode, value: value, r
10084
10811
  }
10085
10812
 
10086
10813
  async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
10087
- const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), can = await advisoryCanForCall({
10814
+ const actor = options?.actor, window = fieldWindowOpen(ctx.instance, site), vars = await callerBoundVarsForCall({
10815
+ client: ctx.client,
10088
10816
  instance: ctx.instance,
10089
10817
  options: options
10090
10818
  }), predicateSatisfied = window.open && site.effective !== !0 && site.effective !== void 0 ? await ctxEvaluateCondition({
@@ -10097,10 +10825,8 @@ async function assertFieldEditable({ctx: ctx, site: site, options: options}) {
10097
10825
  ...actor !== void 0 ? {
10098
10826
  actor: actor
10099
10827
  } : {},
10100
- ...can !== void 0 ? {
10101
- vars: {
10102
- can: can
10103
- }
10828
+ ...vars !== void 0 ? {
10829
+ vars: vars
10104
10830
  } : {}
10105
10831
  }
10106
10832
  }) : site.effective === !0, reason = editDisabledReason({
@@ -10167,6 +10893,7 @@ async function resolveOperationContext(args) {
10167
10893
  return {
10168
10894
  access: access,
10169
10895
  actor: access.actor,
10896
+ memberRolesLoader: createAssignmentMemberRolesLoader(args.client),
10170
10897
  clientForGdr: buildClientForGdr({
10171
10898
  client: args.client,
10172
10899
  workflowResource: args.workflowResource,
@@ -10199,6 +10926,7 @@ async function runCommitVerb(params) {
10199
10926
  actor: context.actor,
10200
10927
  clientForGdr: context.clientForGdr,
10201
10928
  refSurface: context.refSurface,
10929
+ memberRolesLoader: context.memberRolesLoader,
10202
10930
  clock: clock,
10203
10931
  executionContext: args.executionContext,
10204
10932
  telemetry: args.telemetry,
@@ -10223,7 +10951,7 @@ function requestRecordFor(args) {
10223
10951
  }
10224
10952
 
10225
10953
  async function runDeduped(args) {
10226
- const {client: client, tag: tag, instanceId: instanceId, record: record, before: before, now: now, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, run: run} = args, {clock: clock, executionContext: executionContext, telemetry: telemetry} = args, replay = async () => {
10954
+ const {client: client, tag: tag, instanceId: instanceId, record: record, before: before, now: now, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, run: run} = args, {clock: clock, executionContext: executionContext, telemetry: telemetry} = args, replay = async () => {
10227
10955
  const pre = await reload({
10228
10956
  client: client,
10229
10957
  instanceId: instanceId,
@@ -10235,6 +10963,7 @@ async function runDeduped(args) {
10235
10963
  actor: actor,
10236
10964
  clientForGdr: clientForGdr,
10237
10965
  refSurface: refSurface,
10966
+ memberRolesLoader: memberRolesLoader,
10238
10967
  clock: clock,
10239
10968
  executionContext: executionContext,
10240
10969
  telemetry: telemetry
@@ -10258,13 +10987,14 @@ async function runDeduped(args) {
10258
10987
  }
10259
10988
  }
10260
10989
 
10261
- async function cascade({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
10990
+ async function cascade({client: client, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, overlay: overlay}) {
10262
10991
  const count = await cascadeAutoTransitions({
10263
10992
  client: client,
10264
10993
  instanceId: instanceId,
10265
10994
  actor: actor,
10266
10995
  clientForGdr: clientForGdr,
10267
10996
  refSurface: refSurface,
10997
+ memberRolesLoader: memberRolesLoader,
10268
10998
  ...clock !== void 0 ? {
10269
10999
  clock: clock
10270
11000
  } : {},
@@ -10284,6 +11014,7 @@ async function cascade({client: client, instanceId: instanceId, actor: actor, cl
10284
11014
  actor: actor,
10285
11015
  clientForGdr: clientForGdr,
10286
11016
  refSurface: refSurface,
11017
+ memberRolesLoader: memberRolesLoader,
10287
11018
  ...clock !== void 0 ? {
10288
11019
  clock: clock
10289
11020
  } : {},
@@ -10297,7 +11028,7 @@ async function cascade({client: client, instanceId: instanceId, actor: actor, cl
10297
11028
  }
10298
11029
 
10299
11030
  async function cascadeAndReload(args) {
10300
- const {client: client, tag: tag, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock} = args;
11031
+ const {client: client, tag: tag, instanceId: instanceId, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock} = args;
10301
11032
  return {
10302
11033
  cascaded: await cascade({
10303
11034
  client: client,
@@ -10305,6 +11036,7 @@ async function cascadeAndReload(args) {
10305
11036
  actor: actor,
10306
11037
  clientForGdr: clientForGdr,
10307
11038
  refSurface: refSurface,
11039
+ memberRolesLoader: memberRolesLoader,
10308
11040
  clock: clock,
10309
11041
  ...args.executionContext !== void 0 ? {
10310
11042
  executionContext: args.executionContext
@@ -10328,6 +11060,7 @@ async function settleStart(args) {
10328
11060
  actor: args.actor,
10329
11061
  clientForGdr: args.clientForGdr,
10330
11062
  refSurface: args.refSurface,
11063
+ memberRolesLoader: args.memberRolesLoader,
10331
11064
  clock: args.clock,
10332
11065
  ...args.executionContext !== void 0 ? {
10333
11066
  executionContext: args.executionContext
@@ -10370,31 +11103,20 @@ function resumeMismatch(args) {
10370
11103
  }
10371
11104
 
10372
11105
  async function resumeStart(args) {
10373
- const {existing: existing} = args, mismatch = resumeMismatch({
11106
+ const {existing: existing, definition: definition, version: version, initialFieldCount: initialFieldCount, ...settlementArgs} = args, mismatch = resumeMismatch({
10374
11107
  existing: existing,
10375
- definition: args.definition,
10376
- version: args.version
11108
+ definition: definition,
11109
+ version: version
10377
11110
  });
10378
11111
  if (mismatch !== void 0) throw new ContractViolationError(`startInstance: instanceId "${existing._id}" already exists and ${mismatch}. A supplied instanceId is start's idempotency key — reuse one only to retry the same start.`);
10379
11112
  if (existing.stages.length === 0 && terminalState(existing) !== "in-flight") throw new ContractViolationError(`startInstance: instanceId "${existing._id}" belongs to a start that was discarded (aborted before it finished starting) — mint a new id to start again.`);
10380
11113
  const completesStart = isUnprimed(existing), emitStarted = () => resolveTelemetry(args.telemetry).log(WorkflowInstanceStarted, instanceStartedDataFor({
10381
11114
  instance: existing,
10382
- initialFieldCount: args.initialFieldCount,
11115
+ initialFieldCount: initialFieldCount,
10383
11116
  viaSpawn: !1
10384
11117
  })), cascaded = await settleStart({
10385
- client: args.client,
10386
- tag: args.tag,
11118
+ ...settlementArgs,
10387
11119
  instanceId: existing._id,
10388
- actor: args.actor,
10389
- clientForGdr: args.clientForGdr,
10390
- refSurface: args.refSurface,
10391
- clock: args.clock,
10392
- ...args.executionContext !== void 0 ? {
10393
- executionContext: args.executionContext
10394
- } : {},
10395
- ...args.telemetry !== void 0 ? {
10396
- telemetry: args.telemetry
10397
- } : {},
10398
11120
  ...completesStart ? {
10399
11121
  emitStarted: emitStarted
10400
11122
  } : {}
@@ -10410,7 +11132,7 @@ async function resumeStart(args) {
10410
11132
  };
10411
11133
  }
10412
11134
 
10413
- function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: clientForGdr, refSurface: refSurface, executionContext: executionContext, telemetry: telemetry}) {
11135
+ function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, executionContext: executionContext, telemetry: telemetry}) {
10414
11136
  return {
10415
11137
  ...actor !== void 0 ? {
10416
11138
  actor: actor
@@ -10418,6 +11140,7 @@ function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: client
10418
11140
  clock: clock,
10419
11141
  clientForGdr: clientForGdr,
10420
11142
  refSurface: refSurface,
11143
+ memberRolesLoader: memberRolesLoader,
10421
11144
  ...executionContext !== void 0 ? {
10422
11145
  executionContext: executionContext
10423
11146
  } : {},
@@ -10428,7 +11151,7 @@ function engineOptionsForActor({actor: actor, clock: clock, clientForGdr: client
10428
11151
  }
10429
11152
 
10430
11153
  async function abortAndPropagate(args) {
10431
- const {client: client, instanceId: instanceId, reason: reason, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, executionContext: executionContext, telemetry: telemetry, requestRecord: requestRecord} = args, result = await abortInstance({
11154
+ const {client: client, instanceId: instanceId, reason: reason, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, executionContext: executionContext, telemetry: telemetry, requestRecord: requestRecord} = args, result = await abortInstance({
10432
11155
  client: client,
10433
11156
  instanceId: instanceId,
10434
11157
  ...reason !== void 0 ? {
@@ -10442,6 +11165,7 @@ async function abortAndPropagate(args) {
10442
11165
  clock: clock,
10443
11166
  clientForGdr: clientForGdr,
10444
11167
  refSurface: refSurface,
11168
+ memberRolesLoader: memberRolesLoader,
10445
11169
  executionContext: executionContext,
10446
11170
  telemetry: telemetry
10447
11171
  })
@@ -10451,6 +11175,7 @@ async function abortAndPropagate(args) {
10451
11175
  actor: actor,
10452
11176
  clientForGdr: clientForGdr,
10453
11177
  refSurface: refSurface,
11178
+ memberRolesLoader: memberRolesLoader,
10454
11179
  clock: clock,
10455
11180
  ...executionContext !== void 0 ? {
10456
11181
  executionContext: executionContext
@@ -10468,6 +11193,7 @@ async function abortAndPropagate(args) {
10468
11193
  actor: actor,
10469
11194
  clientForGdr: clientForGdr,
10470
11195
  refSurface: refSurface,
11196
+ memberRolesLoader: memberRolesLoader,
10471
11197
  clock: clock,
10472
11198
  ...executionContext !== void 0 ? {
10473
11199
  executionContext: executionContext
@@ -10509,6 +11235,7 @@ async function dispatchGatedWrite(args) {
10509
11235
  actor: args.actor,
10510
11236
  clientForGdr: args.clientForGdr,
10511
11237
  refSurface: args.refSurface,
11238
+ memberRolesLoader: args.memberRolesLoader,
10512
11239
  clock: args.clock,
10513
11240
  executionContext: args.executionContext,
10514
11241
  telemetry: args.telemetry
@@ -10584,12 +11311,16 @@ function buildEngineCallOptions(args) {
10584
11311
  actor: args.actor,
10585
11312
  clientForGdr: args.clientForGdr,
10586
11313
  refSurface: args.refSurface,
11314
+ memberRolesLoader: args.memberRolesLoader,
10587
11315
  ...args.localPrincipalId !== void 0 ? {
10588
11316
  localPrincipalId: args.localPrincipalId
10589
11317
  } : {},
10590
11318
  ...args.grants !== void 0 ? {
10591
11319
  grants: args.grants
10592
11320
  } : {},
11321
+ ...args.attributes !== void 0 ? {
11322
+ attributes: args.attributes
11323
+ } : {},
10593
11324
  ...args.clock !== void 0 ? {
10594
11325
  clock: args.clock
10595
11326
  } : {},
@@ -10620,7 +11351,7 @@ async function applyAction(args) {
10620
11351
  }
10621
11352
 
10622
11353
  async function deleteDefinition(args) {
10623
- const {client: client, tag: tag, definition: definition, version: version, cascade: cascade2, reason: reason, executionContext: executionContext, telemetry: telemetry} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, versions = await loadDefinitionVersionsOrThrow({
11354
+ const {client: client, tag: tag, definition: definition, version: version, cascade: cascade2, reason: reason, executionContext: executionContext, telemetry: telemetry} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader} = await resolveOperationContext(args), clock = args.clock ?? wallClock, versions = await loadDefinitionVersionsOrThrow({
10624
11355
  client: client,
10625
11356
  definition: definition,
10626
11357
  tag: tag
@@ -10659,6 +11390,7 @@ async function deleteDefinition(args) {
10659
11390
  actor: actor,
10660
11391
  clientForGdr: clientForGdr,
10661
11392
  refSurface: refSurface,
11393
+ memberRolesLoader: memberRolesLoader,
10662
11394
  clock: clock,
10663
11395
  executionContext: executionContext,
10664
11396
  telemetry: telemetry
@@ -10717,6 +11449,7 @@ async function abortInstances(args) {
10717
11449
  actor: actor,
10718
11450
  clientForGdr: clientForGdr,
10719
11451
  refSurface: args.refSurface,
11452
+ memberRolesLoader: args.memberRolesLoader,
10720
11453
  clock: clock,
10721
11454
  ...executionContext !== void 0 ? {
10722
11455
  executionContext: executionContext
@@ -10749,11 +11482,12 @@ async function fetchStartSlice(args) {
10749
11482
 
10750
11483
  const workflow = {
10751
11484
  deployDefinitions: async rawArgs => {
10752
- assertReaderModelAcknowledgement(rawArgs.expectedMinReaderModel);
10753
- const args = taggedScope(rawArgs, REQUEST_TAG.deploy), {client: client, tag: tag, resourceAliases: resourceAliases} = args;
11485
+ const args = taggedScope(rawArgs, REQUEST_TAG.deploy), {client: client, tag: tag, workflowResource: workflowResource, resourceAliases: resourceAliases} = args;
10754
11486
  validateTag(tag);
10755
11487
  const definitions = args.definitions.map(def => parseDefinitionInput(def, "workflow.deployDefinitions"));
10756
- definitions.forEach(validateDefinition);
11488
+ definitions.forEach(validateDefinition), assertReaderModelAcknowledgement(args.expectedMinReaderModel, {
11489
+ requiredMinReaderModel: requiredDefinitionReaderModel(definitions)
11490
+ });
10757
11491
  const ordered = await sortByDependencies({
10758
11492
  client: client,
10759
11493
  definitions: definitions,
@@ -10772,6 +11506,7 @@ const workflow = {
10772
11506
  latest: latest,
10773
11507
  target: {
10774
11508
  tag: tag,
11509
+ workflowResource: workflowResource,
10775
11510
  ...resourceAliases !== void 0 ? {
10776
11511
  resourceAliases: resourceAliases
10777
11512
  } : {}
@@ -10822,7 +11557,7 @@ const workflow = {
10822
11557
  }), result;
10823
11558
  },
10824
11559
  startInstance: async rawArgs => {
10825
- const args = taggedScope(rawArgs, REQUEST_TAG.start), {client: client, tag: tag, definition: definitionName, version: version, initialFields: initialFields, instanceId: instanceId, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = operationContext, clock = args.clock ?? wallClock, seedFields = initialFields ?? [], existing = instanceId !== void 0 ? await getInstanceDocument(client, instanceId) : void 0;
11560
+ const args = taggedScope(rawArgs, REQUEST_TAG.start), {client: client, tag: tag, definition: definitionName, version: version, initialFields: initialFields, instanceId: instanceId, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader} = operationContext, clock = args.clock ?? wallClock, seedFields = initialFields ?? [], existing = instanceId !== void 0 ? await getInstanceDocument(client, instanceId) : void 0;
10826
11561
  return existing !== void 0 && existing.tag === tag ? resumeStart({
10827
11562
  client: client,
10828
11563
  tag: tag,
@@ -10833,6 +11568,7 @@ const workflow = {
10833
11568
  actor: actor,
10834
11569
  clientForGdr: clientForGdr,
10835
11570
  refSurface: refSurface,
11571
+ memberRolesLoader: memberRolesLoader,
10836
11572
  clock: clock,
10837
11573
  ...executionContext !== void 0 ? {
10838
11574
  executionContext: executionContext
@@ -10852,7 +11588,7 @@ const workflow = {
10852
11588
  return runCommitVerb({
10853
11589
  args: args,
10854
11590
  op: "fireAction",
10855
- run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
11591
+ run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
10856
11592
  if (findCurrentActivityEntry(before, activity) === void 0 && idempotent === !0) return {
10857
11593
  instance: before,
10858
11594
  cascaded: 0,
@@ -10866,6 +11602,7 @@ const workflow = {
10866
11602
  actor: actor,
10867
11603
  clientForGdr: clientForGdr,
10868
11604
  refSurface: refSurface,
11605
+ memberRolesLoader: memberRolesLoader,
10869
11606
  clock: clock,
10870
11607
  before: before,
10871
11608
  ...grantsFromPath !== void 0 ? {
@@ -10899,6 +11636,7 @@ const workflow = {
10899
11636
  clock: clock,
10900
11637
  clientForGdr: clientForGdr,
10901
11638
  refSurface: refSurface,
11639
+ memberRolesLoader: memberRolesLoader,
10902
11640
  ...executionContext !== void 0 ? {
10903
11641
  executionContext: executionContext
10904
11642
  } : {},
@@ -10927,7 +11665,7 @@ const workflow = {
10927
11665
  return runCommitVerb({
10928
11666
  args: args,
10929
11667
  op: "editField",
10930
- run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
11668
+ run: async ({access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
10931
11669
  const result = await dispatchGatedWrite({
10932
11670
  client: client,
10933
11671
  tag: tag,
@@ -10936,6 +11674,7 @@ const workflow = {
10936
11674
  actor: actor,
10937
11675
  clientForGdr: clientForGdr,
10938
11676
  refSurface: refSurface,
11677
+ memberRolesLoader: memberRolesLoader,
10939
11678
  clock: clock,
10940
11679
  before: before,
10941
11680
  ...grantsFromPath !== void 0 ? {
@@ -10970,6 +11709,7 @@ const workflow = {
10970
11709
  clock: clock,
10971
11710
  clientForGdr: clientForGdr,
10972
11711
  refSurface: refSurface,
11712
+ memberRolesLoader: memberRolesLoader,
10973
11713
  ...executionContext !== void 0 ? {
10974
11714
  executionContext: executionContext
10975
11715
  } : {},
@@ -10990,7 +11730,7 @@ const workflow = {
10990
11730
  });
10991
11731
  },
10992
11732
  completeEffect: async rawArgs => {
10993
- const args = taggedScope(rawArgs, REQUEST_TAG.completeEffect), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, status: status, outputs: outputs, ops: ops, detail: detail, error: error, durationMs: durationMs, executionContext: executionContext} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
11733
+ const args = taggedScope(rawArgs, REQUEST_TAG.completeEffect), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, status: status, outputs: outputs, ops: ops, detail: detail, error: error, durationMs: durationMs, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
10994
11734
  idempotencyKey: args.idempotencyKey,
10995
11735
  op: "completeEffect",
10996
11736
  idempotencyTtlMs: args.idempotencyTtlMs
@@ -11001,9 +11741,7 @@ const workflow = {
11001
11741
  instanceId: instanceId,
11002
11742
  record: record,
11003
11743
  now: clock(),
11004
- actor: actor,
11005
- clientForGdr: clientForGdr,
11006
- refSurface: refSurface,
11744
+ ...operationContext,
11007
11745
  clock: clock,
11008
11746
  executionContext: executionContext,
11009
11747
  telemetry: args.telemetry,
@@ -11032,10 +11770,8 @@ const workflow = {
11032
11770
  requestRecord: record
11033
11771
  } : {},
11034
11772
  options: engineOptionsForActor({
11035
- actor: actor,
11773
+ ...operationContext,
11036
11774
  clock: clock,
11037
- clientForGdr: clientForGdr,
11038
- refSurface: refSurface,
11039
11775
  executionContext: executionContext,
11040
11776
  telemetry: args.telemetry
11041
11777
  })
@@ -11043,9 +11779,7 @@ const workflow = {
11043
11779
  client: client,
11044
11780
  tag: tag,
11045
11781
  instanceId: instanceId,
11046
- actor: actor,
11047
- clientForGdr: clientForGdr,
11048
- refSurface: refSurface,
11782
+ ...operationContext,
11049
11783
  clock: clock,
11050
11784
  executionContext: executionContext,
11051
11785
  telemetry: args.telemetry
@@ -11066,7 +11800,7 @@ const workflow = {
11066
11800
  });
11067
11801
  },
11068
11802
  commitEffectOps: async rawArgs => {
11069
- const args = taggedScope(rawArgs, REQUEST_TAG.commitEffectOps), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, claimToken: claimToken, ops: ops, executionContext: executionContext} = args, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
11803
+ const args = taggedScope(rawArgs, REQUEST_TAG.commitEffectOps), {client: client, tag: tag, instanceId: instanceId, effectKey: effectKey, claimToken: claimToken, ops: ops, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), clock = args.clock ?? wallClock, record = requestRecordFor({
11070
11804
  idempotencyKey: args.idempotencyKey,
11071
11805
  op: "commitEffectOps",
11072
11806
  idempotencyTtlMs: args.idempotencyTtlMs
@@ -11078,9 +11812,7 @@ const workflow = {
11078
11812
  instanceId: instanceId,
11079
11813
  record: record,
11080
11814
  now: clock(),
11081
- actor: actor,
11082
- clientForGdr: clientForGdr,
11083
- refSurface: refSurface,
11815
+ ...operationContext,
11084
11816
  clock: clock,
11085
11817
  executionContext: executionContext,
11086
11818
  telemetry: args.telemetry,
@@ -11094,10 +11826,8 @@ const workflow = {
11094
11826
  requestRecord: record,
11095
11827
  leaseMs: args.leaseMs ?? DEFAULT_EFFECT_LEASE_MS,
11096
11828
  options: engineOptionsForActor({
11097
- actor: actor,
11829
+ ...operationContext,
11098
11830
  clock: clock,
11099
- clientForGdr: clientForGdr,
11100
- refSurface: refSurface,
11101
11831
  executionContext: executionContext,
11102
11832
  telemetry: args.telemetry
11103
11833
  })
@@ -11105,9 +11835,7 @@ const workflow = {
11105
11835
  client: client,
11106
11836
  tag: tag,
11107
11837
  instanceId: instanceId,
11108
- actor: actor,
11109
- clientForGdr: clientForGdr,
11110
- refSurface: refSurface,
11838
+ ...operationContext,
11111
11839
  clock: clock,
11112
11840
  executionContext: executionContext,
11113
11841
  telemetry: args.telemetry
@@ -11126,7 +11854,7 @@ const workflow = {
11126
11854
  });
11127
11855
  },
11128
11856
  tick: async rawArgs => {
11129
- const args = taggedScope(rawArgs, REQUEST_TAG.tick), {client: client, tag: tag, instanceId: instanceId, executionContext: executionContext} = args, {access: access, actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = await resolveOperationContext(args), clock = args.clock ?? wallClock, current = await reload({
11857
+ const args = taggedScope(rawArgs, REQUEST_TAG.tick), {client: client, tag: tag, instanceId: instanceId, executionContext: executionContext} = args, operationContext = await resolveOperationContext(args), {access: access} = operationContext, clock = args.clock ?? wallClock, current = await reload({
11130
11858
  client: client,
11131
11859
  instanceId: instanceId,
11132
11860
  tag: tag
@@ -11140,9 +11868,7 @@ const workflow = {
11140
11868
  client: client,
11141
11869
  tag: tag,
11142
11870
  instanceId: instanceId,
11143
- actor: actor,
11144
- clientForGdr: clientForGdr,
11145
- refSurface: refSurface,
11871
+ ...operationContext,
11146
11872
  clock: clock,
11147
11873
  executionContext: executionContext,
11148
11874
  telemetry: args.telemetry
@@ -11162,7 +11888,7 @@ const workflow = {
11162
11888
  return runCommitVerb({
11163
11889
  args: args,
11164
11890
  op: "setStage",
11165
- run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
11891
+ run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
11166
11892
  const result = await setStage({
11167
11893
  client: client,
11168
11894
  instanceId: instanceId,
@@ -11178,6 +11904,7 @@ const workflow = {
11178
11904
  clock: clock,
11179
11905
  clientForGdr: clientForGdr,
11180
11906
  refSurface: refSurface,
11907
+ memberRolesLoader: memberRolesLoader,
11181
11908
  executionContext: executionContext,
11182
11909
  telemetry: args.telemetry
11183
11910
  })
@@ -11187,6 +11914,7 @@ const workflow = {
11187
11914
  actor: actor,
11188
11915
  clientForGdr: clientForGdr,
11189
11916
  refSurface: refSurface,
11917
+ memberRolesLoader: memberRolesLoader,
11190
11918
  clock: clock,
11191
11919
  ...executionContext !== void 0 ? {
11192
11920
  executionContext: executionContext
@@ -11216,7 +11944,7 @@ const workflow = {
11216
11944
  return runCommitVerb({
11217
11945
  args: args,
11218
11946
  op: "abortInstance",
11219
- run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
11947
+ run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
11220
11948
  const changed = await abortAndPropagate({
11221
11949
  client: client,
11222
11950
  instanceId: instanceId,
@@ -11224,6 +11952,7 @@ const workflow = {
11224
11952
  actor: actor,
11225
11953
  clientForGdr: clientForGdr,
11226
11954
  refSurface: refSurface,
11955
+ memberRolesLoader: memberRolesLoader,
11227
11956
  clock: clock,
11228
11957
  ...executionContext !== void 0 ? {
11229
11958
  executionContext: executionContext
@@ -11257,7 +11986,7 @@ const workflow = {
11257
11986
  return runCommitVerb({
11258
11987
  args: args,
11259
11988
  op: "resetActivity",
11260
- run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, clock: clock, record: record, before: before}) => {
11989
+ run: async ({actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader, clock: clock, record: record, before: before}) => {
11261
11990
  const result = await resetActivity({
11262
11991
  client: client,
11263
11992
  instanceId: instanceId,
@@ -11271,6 +12000,7 @@ const workflow = {
11271
12000
  clock: clock,
11272
12001
  clientForGdr: clientForGdr,
11273
12002
  refSurface: refSurface,
12003
+ memberRolesLoader: memberRolesLoader,
11274
12004
  executionContext: executionContext,
11275
12005
  telemetry: args.telemetry
11276
12006
  })
@@ -11280,6 +12010,7 @@ const workflow = {
11280
12010
  actor: actor,
11281
12011
  clientForGdr: clientForGdr,
11282
12012
  refSurface: refSurface,
12013
+ memberRolesLoader: memberRolesLoader,
11283
12014
  clock: clock,
11284
12015
  ...executionContext !== void 0 ? {
11285
12016
  executionContext: executionContext
@@ -11585,7 +12316,7 @@ async function startRequirementVerdict(args) {
11585
12316
  }
11586
12317
 
11587
12318
  async function startFreshInstance(args) {
11588
- const {args: startArgs, operationContext: operationContext, clock: clock, seedFields: seedFields} = args, {client: client, tag: tag, workflowResource: workflowResource, definition: definitionName, version: version, ancestors: ancestors, context: context, instanceId: instanceId, perspective: perspective, executionContext: executionContext} = startArgs, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface} = operationContext, definition = await loadDefinition({
12319
+ const {args: startArgs, operationContext: operationContext, clock: clock, seedFields: seedFields} = args, {client: client, tag: tag, workflowResource: workflowResource, definition: definitionName, version: version, ancestors: ancestors, context: context, instanceId: instanceId, perspective: perspective, executionContext: executionContext} = startArgs, {actor: actor, clientForGdr: clientForGdr, refSurface: refSurface, memberRolesLoader: memberRolesLoader} = operationContext, definition = await loadDefinition({
11589
12320
  client: client,
11590
12321
  definition: definitionName,
11591
12322
  version: version,
@@ -11609,6 +12340,7 @@ async function startFreshInstance(args) {
11609
12340
  id: id,
11610
12341
  now: now,
11611
12342
  refSurface: refSurface,
12343
+ memberRolesLoader: memberRolesLoader,
11612
12344
  ...perspective !== void 0 ? {
11613
12345
  perspective: perspective
11614
12346
  } : {}
@@ -11640,6 +12372,7 @@ async function startFreshInstance(args) {
11640
12372
  actor: actor,
11641
12373
  clientForGdr: clientForGdr,
11642
12374
  refSurface: refSurface,
12375
+ memberRolesLoader: memberRolesLoader,
11643
12376
  clock: clock,
11644
12377
  ...executionContext !== void 0 ? {
11645
12378
  executionContext: executionContext
@@ -11695,7 +12428,10 @@ async function assertStartInputs(args) {
11695
12428
  }
11696
12429
 
11697
12430
  async function resolveStartFields(args) {
11698
- const {client: client, tag: tag, workflowResource: workflowResource, definition: definition, initialFields: initialFields, id: id, now: now, refSurface: refSurface, perspective: perspective} = args, fieldDiscards = [];
12431
+ const {client: client, tag: tag, workflowResource: workflowResource, definition: definition, initialFields: initialFields, id: id, now: now, refSurface: refSurface, memberRolesLoader: memberRolesLoader, perspective: perspective} = args, fieldDiscards = [], memberRoles = await memberRolesLoader({
12432
+ workflowResource: workflowResource,
12433
+ definition: definition
12434
+ });
11699
12435
  return {
11700
12436
  resolvedFields: await resolveDeclaredFields({
11701
12437
  entryDefs: definition.fields ?? [],
@@ -11708,6 +12444,8 @@ async function resolveStartFields(args) {
11708
12444
  workflowResource: workflowResource,
11709
12445
  definitionName: definition.name,
11710
12446
  refSurface: refSurface,
12447
+ memberRoles: memberRoles,
12448
+ roleAliases: definition.roleAliases,
11711
12449
  ...perspective !== void 0 ? {
11712
12450
  perspective: perspective
11713
12451
  } : {},
@@ -12348,7 +13086,7 @@ function createInstanceSession(args) {
12348
13086
  refSurface: evalScope.refSurface
12349
13087
  });
12350
13088
  }, evaluateWith = async ({held: held, guards: guards, self: self}) => {
12351
- const {actor: actor, localPrincipalId: localPrincipalId, grants: grants} = await access(), resourceGrants = await subjectResourceGrants({
13089
+ const [{actor: actor, localPrincipalId: localPrincipalId, grants: grants}, attributes] = await Promise.all([ access(), resolveUserAttributes(client) ]), resourceGrants = await subjectResourceGrants({
12352
13090
  clientForGdr: evalScope.clientForGdr,
12353
13091
  instance: instance
12354
13092
  }), normalizedSelf = await normalizeInstanceIdentities({
@@ -12370,13 +13108,17 @@ function createInstanceSession(args) {
12370
13108
  } : {},
12371
13109
  ...grants !== void 0 ? {
12372
13110
  grants: grants
13111
+ } : {},
13112
+ ...attributes !== void 0 ? {
13113
+ attributes: attributes
12373
13114
  } : {}
12374
13115
  });
12375
- }, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope}) => {
13116
+ }, settleAfterApply = async ({actor: actor, held: held, ranOps: ranOps, scope: scope, memberRolesLoader: memberRolesLoader}) => {
12376
13117
  const cascaded = await cascadeHeld({
12377
13118
  scope: scope,
12378
13119
  actor: actor,
12379
- held: held
13120
+ held: held,
13121
+ memberRolesLoader: memberRolesLoader
12380
13122
  });
12381
13123
  return instance = await reload({
12382
13124
  client: scope.client,
@@ -12390,12 +13132,13 @@ function createInstanceSession(args) {
12390
13132
  ranOps: ranOps
12391
13133
  } : {}
12392
13134
  };
12393
- }, cascadeHeld = ({scope: scope, actor: actor, held: held}) => cascade({
13135
+ }, cascadeHeld = ({scope: scope, actor: actor, held: held, memberRolesLoader: memberRolesLoader}) => cascade({
12394
13136
  client: scope.client,
12395
13137
  instanceId: instance._id,
12396
13138
  actor: actor,
12397
13139
  clientForGdr: scope.clientForGdr,
12398
13140
  refSurface: scope.refSurface,
13141
+ memberRolesLoader: memberRolesLoader,
12399
13142
  ...clock !== void 0 ? {
12400
13143
  clock: clock
12401
13144
  } : {},
@@ -12492,6 +13235,7 @@ function createInstanceSession(args) {
12492
13235
  },
12493
13236
  tick() {
12494
13237
  return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
13238
+ const memberRolesLoader = createAssignmentMemberRolesLoader(tickScope.client);
12495
13239
  await assertInstanceWriteAllowed({
12496
13240
  instance: instance,
12497
13241
  guards: heldGuards,
@@ -12507,7 +13251,8 @@ function createInstanceSession(args) {
12507
13251
  }), cascaded = await cascadeHeld({
12508
13252
  scope: tickScope,
12509
13253
  actor: actor,
12510
- held: held
13254
+ held: held,
13255
+ memberRolesLoader: memberRolesLoader
12511
13256
  });
12512
13257
  return instance = await reload({
12513
13258
  client: tickScope.client,
@@ -12526,6 +13271,7 @@ function createInstanceSession(args) {
12526
13271
  },
12527
13272
  fireAction({activity: activity, action: action, params: params}) {
12528
13273
  return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
13274
+ const memberRolesLoader = createAssignmentMemberRolesLoader(fireScope.client);
12529
13275
  assertActionAllowed({
12530
13276
  evaluation: await evaluateWith({
12531
13277
  held: held,
@@ -12546,6 +13292,7 @@ function createInstanceSession(args) {
12546
13292
  } : {},
12547
13293
  clientForGdr: fireScope.clientForGdr,
12548
13294
  refSurface: fireScope.refSurface,
13295
+ memberRolesLoader: memberRolesLoader,
12549
13296
  ...grants !== void 0 ? {
12550
13297
  grants: grants
12551
13298
  } : {},
@@ -12565,7 +13312,8 @@ function createInstanceSession(args) {
12565
13312
  actor: actor,
12566
13313
  held: held,
12567
13314
  ranOps: ranOps,
12568
- scope: fireScope
13315
+ scope: fireScope,
13316
+ memberRolesLoader: memberRolesLoader
12569
13317
  });
12570
13318
  return telemetry.log(WorkflowActionFired, actionFiredData({
12571
13319
  instance: preOp,
@@ -12587,6 +13335,7 @@ function createInstanceSession(args) {
12587
13335
  return Promise.reject(err);
12588
13336
  }
12589
13337
  return commit(async ({actor: actor, localPrincipalId: localPrincipalId}, held) => {
13338
+ const memberRolesLoader = createAssignmentMemberRolesLoader(editScope.client);
12590
13339
  assertEditAllowed(await evaluateWith({
12591
13340
  held: held,
12592
13341
  guards: heldGuards,
@@ -12608,6 +13357,7 @@ function createInstanceSession(args) {
12608
13357
  } : {},
12609
13358
  clientForGdr: editScope.clientForGdr,
12610
13359
  refSurface: editScope.refSurface,
13360
+ memberRolesLoader: memberRolesLoader,
12611
13361
  ...grants !== void 0 ? {
12612
13362
  grants: grants
12613
13363
  } : {},
@@ -12624,7 +13374,8 @@ function createInstanceSession(args) {
12624
13374
  actor: actor,
12625
13375
  held: held,
12626
13376
  ranOps: ranOps,
12627
- scope: editScope
13377
+ scope: editScope,
13378
+ memberRolesLoader: memberRolesLoader
12628
13379
  });
12629
13380
  return telemetry.log(WorkflowFieldEdited, fieldEditedData({
12630
13381
  instance: preOp,
@@ -12943,8 +13694,11 @@ function attributeMember({member: member, group: group, chain: chain}) {
12943
13694
  }
12944
13695
 
12945
13696
  function diffEntry({def: rawDef, latestRaw: latestRaw, target: target}) {
12946
- assertReaderModelAcknowledgement(target.expectedMinReaderModel);
12947
- const def = parseDefinitionInput(rawDef, "diffEntry"), plan = planDefinitionDeploy({
13697
+ const def = parseDefinitionInput(rawDef, "diffEntry");
13698
+ assertReaderModelAcknowledgement(target.expectedMinReaderModel, {
13699
+ requiredMinReaderModel: requiredDefinitionReaderModel([ def ])
13700
+ });
13701
+ const plan = planDefinitionDeploy({
12948
13702
  def: def,
12949
13703
  latest: asLatest(latestRaw),
12950
13704
  target: target
@@ -12975,10 +13729,13 @@ function asLatest(raw) {
12975
13729
  }
12976
13730
 
12977
13731
  async function computeDiffEntries({client: client, defs: defs, target: target}) {
12978
- assertReaderModelAcknowledgement(target.expectedMinReaderModel);
13732
+ const definitions = defs.map(def => parseDefinitionInput(def, "computeDiffEntries"));
13733
+ assertReaderModelAcknowledgement(target.expectedMinReaderModel, {
13734
+ requiredMinReaderModel: requiredDefinitionReaderModel(definitions)
13735
+ });
12979
13736
  const entries = [];
12980
- for (const rawDef of defs) {
12981
- const def = parseDefinitionInput(rawDef, "computeDiffEntries"), latest = await loadLatestDeployed({
13737
+ for (const def of definitions) {
13738
+ const latest = await loadLatestDeployed({
12982
13739
  client: client,
12983
13740
  definition: def.name,
12984
13741
  tag: target.tag
@@ -13065,7 +13822,7 @@ const HISTORY_DISPLAY = {
13065
13822
  },
13066
13823
  opApplied: {
13067
13824
  title: "Op applied",
13068
- description: "An inline field-mutation op (field.set / field.append / status.set / etc.) ran during an action commit."
13825
+ description: "An action, direct edit, or effect completion executed an operation and recorded its audit payload."
13069
13826
  },
13070
13827
  fieldQueryDiscarded: {
13071
13828
  title: "Query result discarded",
@@ -13170,6 +13927,10 @@ const HISTORY_DISPLAY = {
13170
13927
  title: "Set field entry",
13171
13928
  description: "Overwrite a field entry's value with a resolved value expression."
13172
13929
  },
13930
+ "field.setIfMissing": {
13931
+ title: "Set field entry if missing",
13932
+ 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."
13933
+ },
13173
13934
  "field.unset": {
13174
13935
  title: "Unset field entry",
13175
13936
  description: "Reset a field entry to its default (null for scalars, [] for array kinds)."
@@ -13178,6 +13939,14 @@ const HISTORY_DISPLAY = {
13178
13939
  title: "Append to field entry",
13179
13940
  description: "Push a resolved item onto an array-kind entry (array, assignees, doc.refs)."
13180
13941
  },
13942
+ "field.inc": {
13943
+ title: "Increment field entry",
13944
+ description: "Add a resolved numeric delta, defaulting to 1, to a number entry that already holds a finite number."
13945
+ },
13946
+ "field.dec": {
13947
+ title: "Decrement field entry",
13948
+ description: "Subtract a resolved numeric delta, defaulting to 1, from a number entry that already holds a finite number."
13949
+ },
13181
13950
  "field.updateWhere": {
13182
13951
  title: "Update matching rows",
13183
13952
  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)."
@@ -13291,4 +14060,4 @@ function displayDescription(typeKey) {
13291
14060
  if (typeKey) return DISPLAY[typeKey]?.description;
13292
14061
  }
13293
14062
 
13294
- 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, 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, 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 };
14063
+ export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MAX_READER, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DECISION_SEMANTICS, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, SIGNAL_SEMANTICS, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstancePreviewSchema, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, actorFulfillsRole, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, 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, instanceChangesQuery, instanceDocId, instanceGuardQuery, instancePreviewsQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isRevisionConflict, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseInstancePreviewDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readInstancePreviewDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredDefinitionReaderModel, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resolveUserAttributes, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, 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 };