Skip to content

policy

Stateless reaction that emits Commands when an Event occurs. See Concepts: Policy.

Schema

properties:
    scope:
        type: object
        properties:
            domain:
                type: string
                pattern: "^[a-z][a-z0-9-]*$"
        required: [domain]
        additionalProperties: false
    deliveryGuarantee:
        type: string
        enum: [at-least-once, at-most-once]
    idempotency:
        type: object
        properties:
            owner:
                type: string
                enum:
                    - self
                    - downstream
                    - infrastructure
                    - none
                    - not-required
            strategy:
                type: string
        required: [owner]
        additionalProperties: false
    handles:
        type: array
        minItems: 1
        items:
            oneOf:
                - type: object
                  properties:
                    boundedContext:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    aggregate:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    event:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                  required: [boundedContext, aggregate, event]
                  additionalProperties: false
                - type: object
                  properties:
                    boundedContext:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    event:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                  required: [boundedContext, event]
                  additionalProperties: false
    emits:
        type: array
        minItems: 1
        items:
            oneOf:
                - type: object
                  properties:
                    boundedContext:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    aggregate:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    command:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                  required: [boundedContext, aggregate, command]
                  additionalProperties: false
                - type: object
                  properties:
                    boundedContext:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    dynamicConsistencyBoundary:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                    command:
                        type: string
                        pattern: "^[a-z][a-z0-9-]*$"
                  required: [boundedContext, dynamicConsistencyBoundary, command]
                  additionalProperties: false
    constraints:
        type: array
        items:
            type: object
            properties:
                name:
                    type: string
                    pattern: "^[a-z][a-z0-9-]*$"
                rule:
                    type: string
            required: [name, rule]
            additionalProperties: false
required: [scope, deliveryGuarantee, handles, emits]
allOf:
    - if:
        properties:
            deliveryGuarantee:
                const: at-least-once
        required: [deliveryGuarantee]
      then:
        required: [idempotency]

Anatomy

A Policy scopes to a Domain via scope.domain. Domain-scope reflects the Policy's role as an in-domain reaction that connects Events from one consistency unit to Commands targeting another – the binding crosses Bounded Contexts, so anchoring it inside one would misrepresent its reach.

The required deliveryGuarantee field carries at-least-once or at-most-once. As with Event Handlers, the schema turns at-least-once into a constraint: if the Policy is at-least-once, it must also carry an idempotency object. With at-most-once, idempotency is optional.

The idempotency object names who tolerates duplicate delivery and, optionally, how. idempotency.owner is one of self, downstream, infrastructure, none, or not-required, with the same meanings as on Event Handlers. The optional idempotency.strategy is free-form prose describing the concrete mechanism.

The handles array lists Event references with at least one entry. Each reference is a discriminated oneOf: Aggregate-bound entries carry boundedContext, aggregate, and event, while BC-scoped entries carry boundedContext and event.

The emits array lists Command references with at least one entry. Each reference is also a discriminated oneOf: an Aggregate-bound Command reference carries boundedContext, aggregate, and command, while a DCB-bound Command reference carries boundedContext, dynamicConsistencyBoundary, and command. The two shapes mirror the two scope shapes a Command itself can carry.

The optional constraints array holds named rules under which the Policy runs (or doesn't). Each entry is { name, rule }. Constraints sit outside handles and emits; they describe activation conditions for the Policy as a whole.

A Policy is stateless. For stateful, multi-Event coordination with timers and lifecycle, use a Process Manager.

description and metadata carry the usual free-form prose and non-semantic attachments. apiVersion is schema.esdm.io/core/v1, kind is policy, and name is the Policy's kebab-case identifier.