Skip to content

Resource events and context changes

Resource events describe committed facts about a resource. In a Net Operation Project, use the Moltaro.Package.NET contracts and the installation’s net-operation-project/developer-surface catalog to check available types and injectable services. See the curated .NET reference for exact member signatures.

IMoltaroResourceEventBus.PublishAsync accepts a MoltaroResourceEventPublishRequest with a Resource identity, an EventType, and optional ActorUserId, CorrelationId, ProducerKey and PayloadJson. It returns a MoltaroResourceEventPublishResult containing EventId. Await publication inside the operation that owns the fact. The event write participates in the publisher’s current database transaction; a rollback removes it along with the mutation. Worker delivery starts after commit and is at least once, so a consumer must make repeated handling safe.

Core Entity lifecycle events use Created, Updated, Archived, Restored and Deleted. Collaboration events describe changes to comments, attachments and tags on their owner resource. Governed commands already publish their supported facts. Calling a Board or Workflow command from C# does not require publishing those facts again.

IMoltaroResourceEventConsumer describes an event consumer through Descriptor and handles a MoltaroResourceEvent through HandleAsync. Descriptor filters select event types, module keys, resource kinds and context resource IDs. An empty filter dimension matches any value in that dimension. Runtime discovery and supported service injection follow the installed developer surface.

MoltaroResourceEventTypes.ContextChanged means that a resource’s related Board or Workflow context changed. The event’s Resource is the destination whose context changed. MoltaroContextChangedPayload.Source identifies the Board Item or Workflow Instance that caused the change. The destination’s Entity fields, row version and ordinary Updated event are unaffected by this fact.

Boards publish context for supported external Targets. Workflow publishes context for its Subject. Explicit Workflow-to-Board-to-Target propagation keeps the same causal root. An Itself Board Item has no external Target.

Use MoltaroContextChangedPayload.FromJson(resourceEvent.PayloadJson!) to read and validate a context payload. Use ToJson() to validate and serialize one. Version 1 uses PascalCase JSON property names and these closed categories:

ReasonFacetMeaning
BoardStatusChangedBoardsThe Board Item’s status changed.
BoardMembershipChangedBoardsBoard membership or a governed relationship changed.
BoardCycleChangedBoardsThe Board Item’s cycle changed.
BoardDataChangedBoardsEffective Board Data changed.
WorkflowFactsChangedWorkflowPublic Workflow facts changed.

The payload contains:

  • Version, currently 1; Source; Reason; and Facet.
  • CauseEventId, the immediate cause, and CausalRootEventId, the original cause retained across explicit propagation.
  • BoardId for Board reasons, or WorkflowDefinitionId and WorkflowInstanceId for Workflow facts. Source identity must agree with its owning context and instance IDs.
  • Optional PreviousStatusId, CurrentStatusId, PreviousCycleId and CurrentCycleId when the producer captures those facts.
  • Optional PreviousMembership and CurrentMembership, each containing at most 256 distinct MoltaroContextMembershipEndpoint values. Each endpoint contains RelationshipId, Owner and Member identities only. These are changed relationships, not an unrestricted graph or a snapshot of resource values. null means unavailable; [] means known empty.
  • VisitedFacets, a sequence of one to four distinct resource/facet pairs, starting with Source. Visit(resource, facet) returns null for an already visited pair and rejects a fifth visit. A propagation failure must roll back the owning operation rather than commit a partial chain.

Identifiers must be nonblank, trimmed strings of at most 128 characters. Unknown versions, reasons and facets, inconsistent identities, duplicate membership endpoints and invalid visit sequences fail validation.

MoltaroResourceIdentity contains ModuleKey, ResourceKind, ContextResourceId and ResourceObjectId. Preserve all four values. For example:

var entity = MoltaroResourceIdentity.EntityInstance(entityDefinitionId, instanceId);
var card = MoltaroResourceIdentity.BoardItem(boardId, boardItemId);
var entitlement = MoltaroResourceIdentity.Entitlement(planId, entitlementId);

The Entitlement context is its Plan ID. The Entity context is its definition ID. Use the resource provider’s resolved identity when translating a Board Target; an object ID alone does not identify a resource.

ContextChanged requires an active transaction on the publishing context. The owner mutation, original event and derived context event must all use that transaction. Publishing outside it throws resourceEvents.context.transactionRequired. Preserve the cause’s actor, correlation and producer provenance.

Publication is deduplicated by CauseEventId, the destination’s four identity parts, Facet and Reason. Repeating that identity with the same JSON payload and provenance returns the original event ID. A different payload, actor, correlation or producer throws resourceEvents.context.publicationConflict. Do not change these values to turn a conflicting replay into a second fact. Ordinary event types retain their existing publication behavior.

The database assigns immutable transaction and stream stamps. Event IDs, occurrence timestamps and transaction ID ordering do not prove commit order. Operators must use the supported installation and restore procedures so that the API and Worker can validate the stream’s external evidence at startup.

An event is a fact, not an access grant. Its source, destination and relationship IDs do not authorize reading or changing those resources. Consumers must use their supported authority and the usual governed query and command services. ContextChanged does not implicitly start a Workflow or grant access to its Subject, Board Target, fields or diagnostics.