Milestone
M3 - SaaS Reliability Path
Priority
P1
Problem
Domain events and side-effect intents need a transactional boundary. Without a transactional outbox contract, users can accidentally publish external side effects before a database transaction commits, or lose events after commit.
Scope
Define TransactionalOutboxStore in an outbox core package.
Candidate API
interface TransactionalOutboxStore {
record(intent: OutboxIntent, options: OutboxRecordOptions): Promise<OutboxRecord>;
claimBatch(options: ClaimBatchOptions): Promise<ClaimedOutboxRecord[]>;
markDispatched(id: string, result: DispatchResult): Promise<void>;
markFailed(id: string, problem: Problem): Promise<void>;
}
Acceptance criteria
- Outbox records include tenant boundary, idempotency key, trace context, retry metadata, and source event/command identifiers.
- Recording inside a Unit of Work rolls back with the transaction.
- Claiming supports safe concurrent dispatch semantics.
- Failure is represented as a Croco Problem with retryability metadata.
- Contract tests exist for duplicate idempotency keys, retryable failure, terminal failure, and dispatch success.
Milestone
M3 - SaaS Reliability Path
Priority
P1
Problem
Domain events and side-effect intents need a transactional boundary. Without a transactional outbox contract, users can accidentally publish external side effects before a database transaction commits, or lose events after commit.
Scope
Define
TransactionalOutboxStorein an outbox core package.Candidate API
Acceptance criteria