Kernel Flow Semantics

Overview

This document defines the CQRS and transactional semantics for kernel execution flows. These semantics ensure deterministic, reliable execution with proper transactional boundaries and event delivery guarantees.

Related Specifications:

Flow Annotation Contract

All kernel flows MUST include @cqrs annotation specifying their kind (command, query, or event). Additional annotations are required based on the CQRS kind as defined in the P04 pattern.

Validation

Flow annotations are validated by tools/flow_lint.py against the AST schema (tools/schemas/ast-v3.schema.json).

1
python tools/flow_lint.py docs/specs/shared/kernel.ast.json --strict

Kernel Flows

1. ExecuteCommand

CQRS Kind: Command

Semantics:

Annotations:

1
2
3
4
5
{
  "cqrs": { "kind": "command" },
  "tx": { "transactional": true },
  "idempotency": { "enabled": true, "key": "correlationId" }
}

Port Interface: CommandBus

Invariants:


2. ExecuteQuery

CQRS Kind: Query

Semantics:

Annotations:

1
2
3
4
{
  "cqrs": { "kind": "query" },
  "read_model": { "source": "ReadProjection" }
}

Port Interface: QueryBus

Invariants:


3. PublishEvent

CQRS Kind: Event

Semantics:

Annotations:

1
2
3
4
{
  "cqrs": { "kind": "event" },
  "outbox": { "mode": "required" }
}

Port Interface: EventBus

Invariants:

Outbox Pattern Flow:

  1. Command executes within transaction
  2. Event recorded to outbox table (same transaction)
  3. Transaction commits
  4. Outbox processor publishes events asynchronously
  5. Events marked as published after successful delivery

4. ManageTransaction

CQRS Kind: Command

Semantics:

Annotations:

1
2
3
4
5
{
  "cqrs": { "kind": "command" },
  "tx": { "transactional": true },
  "idempotency": { "enabled": true, "key": "transactionId" }
}

Port Interface: UnitOfWork

Invariants:


Transactional Boundaries

Command Execution Flow

1
2
3
4
5
6
7
1. Begin transaction (UnitOfWork.begin)
2. Load aggregates (Repository.findById)
3. Execute command logic
4. Save modified aggregates (Repository.save with optimistic locking)
5. Record events to outbox (OutboxPort.record)
6. Commit transaction (UnitOfWork.commit)
7. [Async] Publish events from outbox

Failure Handling


Event Delivery Guarantees

Outbox Pattern

Ensures at-least-once delivery by persisting events transactionally:

  1. Event Recording: Events written to outbox table in same transaction as domain changes
  2. Transaction Commit: Both domain changes and event records commit atomically
  3. Asynchronous Publishing: Separate process polls outbox for unpublished events
  4. Idempotent Handlers: Event handlers must be idempotent (events may be delivered multiple times)

Event Envelope

All events wrapped in EventEnvelope containing:


Validation & Compliance

Flow Lint Checks

Run flow lint to validate all flows have required annotations:

1
python tools/flow_lint.py docs/specs/shared/kernel.ast.json --strict

Checks:

AST Schema Validation

AST JSON must conform to tools/schemas/ast-v3.schema.json:


Implementation Notes

Port Independence

All kernel ports defined as TypeScript interfaces in libs/sea/ports/src/gen/kernel/ports.ts. Adapters implement these interfaces without kernel coupling.

Domain Types

Domain types (CommandContext, QueryContext, EventEnvelope, TransactionBoundary) defined in libs/sea/domain/src/gen/kernel/types.ts.

Testing

Kernel ports tested independently without shell dependencies (see libs/sea/ports/src/gen/kernel/ports.spec.ts).


References