This page covers the abstraction layer behind BitzOrcas’s eventing. The actual CAP infrastructure lives in Eventing — here we document the contracts and ports that make the system testable and infrastructure-independent.
Domain events
Domain events are in-process events dispatched by the Mediator pipeline’s DomainEventDispatchPipelineBehavior:
// Defined in BitzOrcas.Domainpublic abstract record DomainEvent;
// Example: Sandbox modulepublic record NoteCreatedDomainEvent(Guid NoteId, string Title) : DomainEvent;Lifecycle
- Aggregate calls
AddDomainEvent(event)during a command DomainEventDispatchPipelineBehaviorcollects events after handler execution- Events are dispatched after the transaction commits
- Handlers process events within the same request scope
Key difference from integration events
| Aspect | Domain Event | Integration Event |
|---|---|---|
| Scope | In-process (same request) | Cross-process (via message broker) |
| Transport | Mediator pipeline | CAP + RabbitMQ |
| Contract location | BitzOrcas.Domain | BitzOrcas.SaaS.Contracts |
| Transactional | Same DB transaction | CAP Outbox (eventual consistency) |
| Handler attribute | N/A (auto-discovered) | [CapSubscribe] |
Integration event contracts
BitzOrcas.SaaS.Contracts is a shared assembly containing all cross-module event definitions:
BitzOrcas.SaaS.Contracts/├── Auditing/ → Audit trail events├── Catalog/ → Plan/subscription catalog events├── Chat/ → Channel/message/member events├── Files/ → File upload/delete events├── Notifications/ → Notification delivery requests├── PlatformBilling/ → Invoice/subscription/usage events├── Tickets/ → Ticket lifecycle events└── Webhooks/ → Webhook event envelopes + signature helpersContracts are pure DTOs — no behavior, no infrastructure dependencies. Both the API Host and JobHost reference this assembly.
INotificationPublisher port
public interface INotificationPublisher{ Task PublishAsync<T>(T @event, CancellationToken ct = default) where T : notnull;}Implementations
| Implementation | Mode | Behavior |
|---|---|---|
NullNotificationPublisher | Default (no DB) | No-op — events silently dropped |
CapNotificationPublisher | Production (with CAP) | Publishes to CAP Outbox for RabbitMQ delivery |
The Null pattern enables API Shell mode — the entire application starts without RabbitMQ, useful for unit testing and local development.
Other event-related ports
| Port | Purpose |
|---|---|
IFileEventPublisher | File upload/delete events |
ICatalogEventPublisher | Catalog plan changes |
IChatEventPublisher | Chat message events |
ITicketEventPublisher | Ticket lifecycle events |
IPlatformBillingEventPublisher | Billing/subscription events |
Each follows the same Null/Production pattern — a no-op default registered in CoreRuntime, overridden by CAP-based implementation in PersistenceAdapters.
Webhook event type registry
public interface IWebhookEventTypeRegistry{ IReadOnlySet<string> RegisteredTypes { get; } bool IsRegistered(string eventType);}- Default:
InMemoryWebhookEventTypeRegistry— statically configured event types - Events in
WebhookEventTypesdefine the available subscription targets
Event naming convention
All integration events follow the pattern {module}.{entity}.{action}:
ticket.created — New ticket openedticket.assigned — Ticket assigned to agentticket.commented — Comment addedticket.status_changed — Status transitionchat.message_sent — New chat messagefile.uploaded — File asset createdbilling.invoice_paid — Invoice payment received