# Event Template

Standards for domain and integration events.

## Domain Events

- Emitted when an aggregate state change may matter inside or outside the service.
- Written via outbox in the same DB transaction as the write ([ADR-006](../architecture/adr/ADR-006.md)).
- Consumers treat events as facts; producers do not assume synchronous handling.

## Integration Events

- Cross-service contracts for interoperability (same envelope).
- Stable payload fields; evolve additively when possible.
- Consumers must be idempotent (inbox / `event_id`).

## Naming

Preferred forms (follow the owning service’s established style):

| Style | Example | When |
| --- | --- | --- |
| `{aggregate}.{past_tense}` | `tenant.created` | Core / generic |
| `{service}.{aggregate}.{past_tense}` | `crm.lead.created`, `loyalty.member.enrolled` | Namespaced business services |

Use past tense. Do not use generic names like `update` without the aggregate.

## Versioning

1. Envelope fields remain stable ([event-driven-architecture.md](../architecture/event-driven-architecture.md)).
2. Payload additive changes preferred.
3. Breaking payload changes: new event type or explicit `payload_version` documented in catalog and handover.
4. Never reuse an `event_type` string for a different meaning.

## Payload Rules

Envelope (canonical):

```json
{
  "event_id": "uuid",
  "event_type": "service.aggregate.past_tense",
  "aggregate_type": "aggregate",
  "aggregate_id": "uuid",
  "tenant_id": "uuid|null",
  "source_service": "service-name",
  "payload": {},
  "occurred_at": "ISO-8601"
}
```

Payload must:

- Include enough IDs for consumers to fetch details via API if needed
- Avoid embedding secrets or large binaries
- Prefer refs over duplicated foreign aggregates
- Remain JSON-serializable

## Catalog & Registration

1. List new events in the phase doc and [event-catalog.md](../reference/event-catalog.md).
2. Update [module-registry.md](../module-registry.md) Events fields.
3. Update [service-manifest.yaml](service-manifest.yaml) event list.

## Completeness

Outbox events for cross-service-relevant state changes are a **mandatory phase artifact** unless justified N/A ([mandatory-phase-artifacts.md](mandatory-phase-artifacts.md), [enterprise-completeness.md](enterprise-completeness.md)). Missing event emission for in-scope integrations fails the Event Completeness gate.

## Related Documents

- [Event-Driven Architecture](../architecture/event-driven-architecture.md)
- [ADR-006](../architecture/adr/ADR-006.md)
- [Services Contracts](../reference/services-contracts.md)
- [Service Layer Template](service-layer-template.md)
- [Quality Gates](quality-gates.md)
