Ports and adapters
Trace the dependency direction that keeps incident and recovery semantics independent of infrastructure vendors.
Dependency direction
Domain depends only on Python, Pydantic, and standard-library types. Application coordinates domain and ports. Adapters implement local or provider-specific behavior. The CLI selects concrete adapters. Nothing in domain or application knows which database, model provider, or observability vendor is in play.
What belongs where
| Layer | Owns | Must not own |
|---|---|---|
| Domain | Incidents, evidence, diagnoses, playbooks, proposals, approvals, verification, truth | Database, HTTP, CLI, cloud, agent SDK |
| Application | Use-case orchestration, collection budgets, lifecycle order | SQLite, hosted products, provider SDKs |
| Ports | Provider-neutral capability protocols | Concrete credentials or clients |
| Adapters | Deterministic rules, SQLite, Markdown/JSON, webhook, plugin catalog | Core business semantics |
| CLI | Composition and user commands | Reusable domain policy |
Extension rule
Substantial vendor connectors ship as independent packages when practical—the repository already proves this with lumis-sdk-postgres-memory and lumis-sdk-http-json-evidence, neither of which adds its driver to core. This keeps core installation small and makes permissions, trust, maintenance, and compatibility visible per connector.