Boundaries

Versioned contracts

Refactor internal facts freely while keeping external promises explicit and reviewable.

Map internal facts deliberately

PaymentChargedPublication.cs
C#
// The only place where an internal fact becomes a public contract.
public sealed class PaymentChargedPublication : Publication<PaymentCharged, PaymentChargedV1>
{
    public override PaymentChargedV1 Map(PaymentCharged e) => new(e.OrderId, e.Amount, "EUR");
}

Review the contract as text

Every integration event is captured in contracts.wyrd.txt. Breaking changes fail the build; compatible additions receive an IDE code fix.

Contract diagnostic
text
# contracts.wyrd.txt (reviewed in PRs)
payments.payment-charged v1 | Amount: decimal; Currency: string; OrderId: string

# If you change Amount from decimal to double:
error WYRD0201: Breaking change in integration event 'payments.payment-charged' v1:
field 'Amount' changed type from decimal to double. Existing subscribers would fail
to read it. Publish it as v2 and keep v1 until subscribers migrate, or revert the change.

Analyzer rules

WYRD0001Error

A type cannot be both a command and an event.

WYRD0002Error

A command must have a single owning slice.

WYRD0003 / 0004Info

Events should be past tense; commands should be imperative.

WYRD0011 / 0012Warning

Process rules: every step says how it is undone or .NoCompensation("why") (WYRD0011), every wait has .Within (WYRD0012).

WYRD0014Warning

Every step declares its retry policy, .Retry(...) or .NoRetry("why"). There is no default. Replaces the removed WYRD0010.

WYRD0013Warning

The process syntax a repository picks (wyrd_process_style), with a one-click fluent ⇄ pipe conversion.

WYRD0020Error

A switch over a [Union] must handle every case; when it does, no discard is needed.

WYRD0101Error

Domain types cannot leak inside a public integration event contract.

WYRD0200 / 0202Warning

New integration event or compatible optional field added — one-click IDE code fix updates contracts.wyrd.txt.

WYRD0201 / 0203Error

Breaking field change or deleted contract without retirement.

WYRD0300–0302Error

Keeps [WyrdJsonContext] complete and collision-free for Native AOT.