Evidence, Ownership, and Lineage¶
The ontology becomes useful when teams can trace a product decision back to its evidence. A feature should say which source owns the raw fact, which projection gives it domain meaning, and which consumer is allowed to act on it.
Ownership Pattern¶
flowchart LR
Raw["Raw evidence<br/>protocol payloads, telemetry, schedules, meters, logs"]
Owner["Evidence owner<br/>source system or adapter boundary"]
Projection["Domain projection<br/>vehicle activity, energy system, charging, commercial record"]
Decision["Decision owner<br/>domain use case or aggregate"]
Consumer["Consumer<br/>UI, report, support, API, downstream event"]
Audit["Lineage and audit<br/>source id, timestamps, version, confidence"]
Raw --> Owner
Owner --> Projection
Projection --> Decision
Projection --> Consumer
Decision --> Consumer
Owner --> Audit
Projection --> Audit
Decision --> Audit
Use this pattern before adding a new feed or report:
- Name the raw evidence.
- Name the evidence owner.
- Name the core concept or projection it supports.
- Name the domain decision that can act on it.
- Name the consumer and the lineage it needs.
Vehicle Activity Lineage¶
vehicle activity is a projection. It joins evidence about movement, assignment, energy state, charging state, readiness, and health.
flowchart TB
subgraph Evidence["Evidence feeds"]
Telematics["Telematics<br/>location, motion, SoC"]
Trips["Trip observations<br/>movement episodes"]
Schedule["Schedule and dispatch<br/>blocks, duties, assignments"]
Charging["Charging sessions<br/>start, stop, meter, status"]
Faults["Incidents and diagnostics<br/>faults, degraded state"]
end
subgraph Projection["Vehicle activity projection"]
Mobility["mobility state"]
Assignment["assignment state"]
Energy["energy state"]
ChargeState["charging state"]
Readiness["readiness state"]
Health["health state"]
end
subgraph Consumers["Consumers"]
Dispatch["dispatch confidence"]
SmartCharging["charging priority"]
Incidents["incident impact"]
Reports["fleet and charging reports"]
Support["support explanation"]
end
Telematics --> Mobility
Telematics --> Energy
Trips --> Mobility
Schedule --> Assignment
Charging --> ChargeState
Charging --> Energy
Faults --> Health
Assignment --> Readiness
Energy --> Readiness
ChargeState --> Readiness
Health --> Readiness
Readiness --> Dispatch
Readiness --> SmartCharging
Health --> Incidents
Mobility --> Reports
ChargeState --> Reports
Readiness --> Support
The projection should preserve time validity and source lineage. If telematics, schedule, and charging feeds disagree, the projection should expose the confidence or conflict rather than hiding it in a report.
Energy System Lineage¶
energy system is the supply-side projection. It joins topology, power, constraints, allocation, and quality state.
flowchart TB
subgraph Inputs["Supply-side evidence"]
Topology["Topology config<br/>microgrid, nodes, circuits"]
Meters["Meter telemetry<br/>site load, circuit load"]
Chargers["Charger telemetry<br/>status, active demand"]
Envelopes["External envelopes<br/>OSCP, OpenADR, DERMS"]
Tariffs["Tariffs and carbon factors"]
Storage["Storage / generation state"]
Control["Control history<br/>profiles, limits, fallback"]
end
subgraph EnergySystem["Energy system projection"]
Source["energy source"]
Resource["energy resource"]
TopologyState["topology state"]
Power["power state"]
Constraint["constraint state"]
Allocation["allocation state"]
Quality["quality state"]
end
subgraph Consumers["Consumers"]
Balancing["smart charging allocation"]
EnergyOps["energy operations"]
Dispatch["readiness confidence"]
Incidents["capacity and control incidents"]
Reports["cost, carbon, compliance"]
end
Topology --> TopologyState
Meters --> Power
Chargers --> Resource
Chargers --> Power
Envelopes --> Constraint
Tariffs --> Constraint
Storage --> Source
Storage --> Resource
Control --> Allocation
Control --> Quality
Constraint --> Balancing
Power --> Balancing
TopologyState --> Balancing
Source --> EnergyOps
Resource --> EnergyOps
Quality --> Incidents
Allocation --> Dispatch
Constraint --> Reports
Power --> Reports
The microgrid owns generic physical topology and constraint state. Grid or protocol identity should stay in the OSCP, OpenADR, DERMS, or adapter boundary unless the product feature is about that identity.
Session And Commercial Lineage¶
Physical, operational, and commercial records share evidence, but they answer different questions.
flowchart LR
RawSession["Raw charger evidence<br/>transaction, meter values, status"]
Physical["Physical session<br/>energy transfer"]
Operational["Operational session<br/>vehicle, work, readiness, policy"]
Commercial["Commercial record<br/>access, tariff, CDR, settlement"]
Report["Report row<br/>cost, carbon, reliability, proof"]
Support["Support view<br/>what happened and why"]
RawSession --> Physical
Physical --> Operational
Physical --> Commercial
Operational --> Report
Commercial --> Report
Physical --> Support
Operational --> Support
When a report says a vehicle missed readiness, it should be possible to trace the statement back through the readiness target, allocation decision, command, session, meter evidence, and any relevant fault or envelope.
Implementation Boundary Reminder¶
The implementation should follow the same shape as the ontology:
- Domain code owns invariants and state transitions.
- Service command code coordinates use cases through ports.
- Queries return read models or projections.
- Adapters own protocol, database, external API, and event-bus details.
- Cross-context access should go through ports, events, or anti-corruption adapters.
This aligns with ADR 0031: Adopt DDD, Hexagonal Architecture, and CQRS for Python Domain Services.
Lineage Checklist¶
Before changing a feed, projection, report, or support view, confirm:
- Which raw evidence supports the value?
- Which source owns the evidence?
- Which timestamps and identifiers must be retained?
- Which projection resolves the domain meaning?
- Which domain decision may act on it?
- Which consumers need confidence, freshness, or conflict information?
- Which report or audit trail must still be rebuildable?