Model¶
Bounded contexts, aggregates, vertical slices.
The shape under every CORA feature: a BC owns a slice of the domain, an aggregate owns a consistency boundary inside it, a vertical slice owns one command or query end-to-end. Get these three right and adding a feature stops being a refactor.
Bounded contexts¶
CORA is a set of bounded contexts (BCs) organised into groups. Each BC owns its model, language, and API surface. Each aggregate inside a BC owns one consistency boundary.
Status legend: Active = aggregate is shipping and listed under Modules; Planned = scoped, not yet implemented.
| Group | BC | Aggregates | Status |
|---|---|---|---|
| Foundation | access |
actor |
Active |
| Foundation | equipment |
assembly, asset, family, fixture, frame, model, mount, role |
Active |
| Procedure | recipe |
capability, method, plan, practice, recipe |
Active |
| Procedure | run |
run |
Active |
| Procedure | campaign |
campaign |
Active |
| Resource | supply |
supply |
Active |
| Resource | operation |
procedure |
Active |
| Resource | budget |
budget |
Planned |
| Authority | trust |
conduit, policy, ratification, surface, visit, zone |
Active |
| Authority | safety |
clearance, clearance_template |
Active |
| Authority | federation |
credential, facility, permit, seal |
Active |
| Assurance | enclosure |
enclosure |
Active |
| Assurance | calibration |
calibration |
Active |
| Assurance | caution |
caution |
Active |
| Governance | decision |
decision |
Active |
| Governance | agent |
agent |
Active |
| Governance | strategy |
strategy |
Planned |
| Outcome | subject |
subject |
Active |
| Outcome | data |
acquisition, attestation, dataset, distribution, edition |
Active |
Seventeen BCs and forty-one aggregates ship today; two more BCs are reserved with single planned aggregates. Each group is named for the operational role its BCs play in running an experiment: Foundation owns the shared facts every other group refers to (identity, equipment); Procedure is the planned-work recipe ladder and its execution instances; Resource is the continuous and consumable substrate work runs on, plus its upkeep; Authority is where CORA itself decides or grants permission to act, intra- and cross-facility; Assurance is observed state and recorded evidence that conditions work but that CORA does not decide; Governance is the audit and configuration of consequential choices; and Outcome is what the experiment studies and produces. The ISA and peer standards that shaped several BCs (ISA-88, ISA-106, ISA-99) are documentation provenance recorded in the glossary, not the partition. To place a new BC, take the first role above that fits; if none fits, the BC charter is mis-scoped rather than the scheme needing an eighth group, and a new group is added only when three homeless BCs share a genuinely new role.
Aggregates¶
The unit of consistency inside a BC: state, invariants, events. Every aggregate is a stream in the event store, identified by (stream_type, stream_id) and folded from its events into an in-memory state per command. The same shape repeats across BCs: a state.py carries the fields and invariants, an events.py carries the closed union of events, and an evolver.py folds events back into state. See Reference/Modeling for the rules.
Vertical slices¶
One folder per command or query, holding everything the slice needs:
features/<verb>_<aggregate>/
├── command.py input shape
├── decider.py pure rule: (state, command) -> events
├── handler.py shell: wires core to ports
├── route.py HTTP API adapter
└── tool.py agent (MCP) tool adapter
Independently readable, testable, deletable. For the in-repo file layout, see Reference/Layout.
What each piece does
- Command. Immutable input shape, one per slice. Captures the caller's intent. Structurally validated at the adapter, semantically validated by the decider.
- Functional core. Decider takes a command and current state, returns events. Evolver folds events back into state. Both pure, no I/O.
- Imperative shell. Handler wires the core to side-effect ports (clock, IDs, event store, authorize, idempotency). Real ports in production, fakes in tests.
- Thin adapters. One per surface, translates protocol-specific input into the same handler call. Schema validation only, no business rules.
Query slices follow the same shape with query in place of command and no decider, since there's no state change. Single-record reads fold the stream; list and filter reads hit a projection. See Reference/Patterns.