Domain overview & context map
Baseleg uses Domain-Driven Design (DDD) as its primary modelling approach. Aviation operations have rich, well-understood business rules: aircraft can only be booked when available, instructors cannot be double-booked, a person’s compliance currency determines what they can legally fly. These rules are non-trivial, and the wrong architecture (business logic scattered across UI handlers or raw SQL) leads to bugs that erode trust. DDD gives us a disciplined way to encapsulate business rules in domain packages independent of frameworks and databases, name things correctly using the aviation domain’s own language, and separate concerns through bounded contexts so each capability evolves independently.
Baseleg is organized into bounded contexts. Each context owns a slice of the domain with its own model, language, and rules — even when contexts reference the same real-world entity (e.g. a person appears in People, Scheduling, and Training, but each context holds only the fields it needs). Each context has its own domain package (packages/domain/<context>/) containing entities, value objects, and domain rules, and its own application package (packages/application/<context>/) containing use cases — see Architecture for the full layering rules.
Diagram styling is provisional — it will be rebuilt against the new docs theme’s token set as part of the visual refresh.
Bounded contexts
People
Manages identity and types within the organisation. The canonical source of truth for who exists in the system.
- Package:
packages/domain/people,packages/application/people - Aggregate root: Person
- Key concepts: Person, Student, Instructor, Staff, Admin, Type
Aircraft
Manages the fleet and its operational state. The canonical source of truth for what aircraft exist and whether they are available.
- Package:
packages/domain/aircraft,packages/application/aircraft - Aggregate root: Aircraft
- Key concepts: Aircraft, Grounded, Registration
Scheduling
Manages time-based allocation of aircraft and instructors, and the operational Checkout/Return transactions that turn a Booking into an actual Flight. Enforces booking rules and prevents conflicts.
- Package:
packages/domain/scheduling,packages/application/scheduling - Aggregate root: Booking
- Key concepts: Booking, Flight, TimeRange, Conflict, Checkout, Return
Training (v1 lite)
Records training activity and progression for students.
- Package:
packages/domain/training,packages/application/training - Key concepts: Lesson, Flight, Endorsement
Billing (v1 lite)
Tracks charge items and manages the invoice lifecycle.
- Package:
packages/domain/billing,packages/application/billing - Key concepts: Usage Event, Charge Item, Invoice Draft, Invoice
Compliance (v1 lite)
Monitors currency requirements and produces compliance alerts.
- Package:
packages/domain/compliance,packages/application/compliance - Key concepts: Currency, Compliance Alert, Document Expiry
Notifications (adapter context)
Delivers communication events from other contexts to external channels (email, SMS, in-app).
- Package:
packages/domain/notifications,packages/application/notifications - Key concepts: Notification, Channel, Delivery
Reporting (v1 lite)
Produces operational summaries and exports from data across contexts.
- Package:
packages/domain/reporting,packages/application/reporting - Key concepts: Report, Export, Summary
v1 product spine
The v1 spine focuses on the three primary contexts:
People ──── Scheduling ──── Aircraft
│ │
└── Training └── Billing / Compliance / Notifications / Reporting
(lite) (lite)
- People — who can book
- Aircraft — what can be booked
- Scheduling — when, and with what constraints
Training, Billing, Compliance, Notifications, and Reporting are intentionally lite until the spine is reliable.
Cross-context relationships
Contexts are kept loosely coupled. When a context needs data from another, it holds only the minimum identifier or read-model needed — it does not import the other context’s domain package.
| From | To | What is shared |
|---|---|---|
| Scheduling | People | Person ID (booking owner, instructor reference) |
| Scheduling | Aircraft | Aircraft ID + availability/grounded state |
| Training | People | Person ID (student, instructor references) |
| Training | Scheduling | Booking ID (optional link from lesson to booking) |
| Billing | Scheduling | Booking ID (charge items linked to bookings) |
| Billing | People | Person ID (invoice recipient) |
| Scheduling | Billing | Writes a Usage Event via the UsageEventRecorder port on Flight completion (Scheduling writes, Billing does not read back) |
| Compliance | People | Person ID (currency requirements per person) |
| Compliance | Aircraft | Aircraft ID (airworthiness documents) |
| Notifications | All | Event payloads from other contexts |
| Reporting | All | Read-model queries (infrastructure layer only) |
Cross-context coupling should always be through identifiers or read-models — never through domain object references.
Ubiquitous language
All code, documentation, and conversations should use the domain language defined in Ubiquitous Language. Using the correct terminology reduces ambiguity and keeps the codebase aligned with the business model.
How to navigate
- Adding a feature? Find the relevant bounded context above for its entities, rules, and use cases.
- Unsure about a term? Check Ubiquitous Language.