Google Sign-In Required

Use your company Google account to access the BetterFleet private content.

Back to private home

BetterFleet Support Private
Skip to content
BetterFleet Dev Wiki
System Design: Depot Simulation
Initializing search
    bf-dev
    • Home
    • Product Capabilities
    • Process
    • Current Work
    • System Design
    • Software Reference
    • Operations
    bf-dev
    • Home
      • Overview
      • Manage
      • Overview
      • Product Engineering Workflow
      • Product Engineering Delivery
      • Product Engineering Workflow in Linear
        • GitLab Feature Flags
        • In-App Docs Authoring
        • Release Notes
      • Templates
      • Publishing
      • Workflow Companions
      • Overview
      • Active Artifacts
      • Backlog Artifacts
      • Archived Artifacts
      • Overview
      • Microgrid
      • OSCP
        • Challenge
        • Specification
        • Spec
        • Architecture
        • Overview
        • Script Runtime Model
        • Compose Profiles and Modes
        • Repo Topology
        • CI and Release Integration
        • Overview
        • Internal Application Diagrams
          • Overview
          • Web Model
          • Core Model
        • Service Interaction Flows
        • Data and State
          • Index
          • bf-manage-web
          • bf-manage-core
          • bf-manage-connect
          • bf-manage-sitepwrmon
          • bf-manage-incidents
          • bf-telematics
          • bf-depot-sim
          • bf-manage-roaming
          • bf-support-microsite
          • bf-digital-twin
          • bf-schedule-creator
        • Overview
        • Internal Application Diagrams
        • Migration and Flags
        • Simulation Request Lifecycle
          • Index
          • bf-bnl-ui
          • bf-bnl-settings
          • bf-bnl-schedule-analysis-compute
          • bf-route-modelling
          • bf-schedule-creator
          • bf-digital-twin
        • Overview
        • Secrets and Env Strategy
        • Vendors and Local Dependencies
        • ADRs
        • Service Matrix
        • Cloud Dependencies
        • Ports and URLs
      • Onboarding
      • Daily Operations Runbook
        • Overview
        • Staging Hotfix Release
        • Production Hotfix Release
        • Terraform Plan Dry Runs
      • Troubleshooting
      • Testing Guide
    • 1. Problem
    • 2. System Overview
    • 3. Core Domain Model
    • 4. Domain Aggregates
      • Simulation Configuration Aggregate
      • Simulation Run Aggregate
      • OSCP Capacity Provider Session Aggregate
    • 5. Service Boundaries
      • Simulation Configuration Service
      • Simulation Run Service
      • OCPP Charge Point Service
      • BetterFleet IoT Packet Service
      • Telematics Service
      • OSCP Capacity Provider Service
      • Scenario Control Service
    • 6. Event Model
    • 7. API Contracts
      • Control API
        • POST /simulation-runs/{simulation_run_id}/oscp-sessions
        • POST /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/commands/send-handshake
        • POST /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/commands/send-forecast
        • PATCH /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/overrides
        • GET /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/messages
      • Protocol API
        • POST /oscp/cp/2.0/handshake
        • POST /oscp/cp/2.0/handshake_acknowledge
        • POST /oscp/cp/2.0/heartbeat
        • POST /oscp/cp/2.0/update_group_measurements
        • POST /oscp/cp/2.0/update_asset_measurements
        • POST /oscp/cp/2.0/adjust_group_capacity_forecast
        • POST /oscp/cp/2.0/group_capacity_compliance_error
    • 8. Data Ownership
      • SimulationConfiguration
      • SimulationRun
      • OscpCapacityProviderSession
      • OscpMessageLedgerEntry
      • OscpMessageExpectation
      • OscpScenarioOverride
    • 9. Operational Workflows
      • BetterFleet-Initiated Handshake
      • Capacity Provider-Initiated Handshake
      • Heartbeat and Offline Control
      • Forecast Publication
      • BetterFleet Outbound Message Validation
      • Failure Scenario Injection
    • 10. Failure Handling
    • 11. Future Extensions

    System Design: Depot Simulation¶

    1. Problem¶

    bf-depot-sim is BetterFleet's reference simulator for depot behaviour.

    It exists so BetterFleet can be tested without relying on real depot hardware.

    That hardware includes:

    • chargers
    • buses and other vehicles
    • site sensors and meters
    • electrical infrastructure and site state
    • external partner systems that interact with BetterFleet through published protocols

    Depot-sim must let operators and testers control the simulated world in real time.

    That control includes:

    • starting and stopping chargers and transactions
    • changing charger, vehicle, sensor, and site state
    • forcing faults, outages, and mismatches
    • applying scripted, random, or manual scenarios
    • inspecting simulator state and external protocol outcomes

    The reference solution owns:

    • saved simulation configurations
    • resumable simulation runs
    • one shared simulation world
    • protocol projections over that world
    • control and inspection APIs used by operators and automated tests

    Depot-sim integrates with BetterFleet only through external interfaces.

    It never reads BetterFleet databases, internal event streams, or in-process objects directly.

    This boundary is part of the product philosophy.

    If BetterFleet behaves correctly against depot-sim through published interfaces, it should behave the same against real hardware and partner systems.

    The reference solution therefore needs stable simulator implementations for these interface families:

    • OCPP charger interfaces
    • BetterFleet site power and sensor packet interfaces
    • BetterFleet telematics-facing interfaces
    • OSCP Capacity Provider interfaces
    • simulator control and inspection APIs

    All interface families are projections over one simulation world.

    No interface family becomes the source of truth for depot state.

    2. System Overview¶

    Depot-sim remains one deployable service.

    The reference solution is decomposed into explicit internal boundaries.

    Those boundaries separate:

    • simulation configuration
    • simulation runtime
    • scenario control
    • external interface projections
    • operator and test control surfaces

    It does not become the source of truth for depot state.

    It exposes BetterFleet-facing and operator-facing interfaces from the same underlying simulation run.

    The external interface projection family includes:

    • OCPP Charge Point Service
    • BetterFleet IoT Packet Service
    • Telematics Service
    • OSCP Capacity Provider Service

    Each projection service translates shared runtime state into one external contract.

    Each projection service may keep protocol-local session or delivery state.

    It reads simulation runtime state through ports.

    It does not write simulation runtime state directly.

    Simulation runtime is exposed through SimulationRuntimePort.

    Projection services depend on that stable port rather than runtime internals.

    ADR alignment:

    • 0018 applies. Persistence stays behind repositories.
    • 0023 is proposed only. Internal domain events are useful, but optional.
    • 0024 is proposed only. This design does not depend on a shared event bus.
    flowchart LR
        UI[Depot Sim Control API]
        CFG[Simulation Configuration Service]
        RUN[Simulation Run Service]
        SCN[Scenario Control Service]
        OCPP[OCPP Charge Point Service]
        IOT[BetterFleet IoT Packet Service]
        TEL[Telematics Service]
        OSCP[OSCP Capacity Provider Service]
        BF[BetterFleet External Interfaces]
    
        UI --> CFG
        UI --> RUN
        UI --> SCN
    
        CFG --> RUN
        RUN --> OSCP
        RUN --> OCPP
        RUN --> IOT
        RUN --> TEL
        SCN --> OSCP
        SCN --> OCPP
        SCN --> IOT
        SCN --> TEL
    
        BF --> OCPP
        BF --> IOT
        BF --> TEL
        BF --> OSCP
        OCPP --> BF
        IOT --> BF
        TEL --> BF
        OSCP --> BF

    3. Core Domain Model¶

    SimulationConfiguration
    - saved, versioned depot definition
    - owns topology, managed scopes, projection bindings, and scenario presets

    ManagedScope
    - named electrical boundary inside one configuration
    - gives protocol projections a stable routing target

    ElectricalTopology
    - rooted model of the simulated site electrical structure
    - defines the nodes a managed scope can reference

    ProjectionBinding
    - maps one managed scope to one external protocol role
    - stores projection defaults, not live transport state
    - covers OCPP, BetterFleet packet, telematics, and OSCP projection families

    ProjectionRuntimeState
    - runtime delivery or session state for one projection family
    - tracks health, checkpoints, and protocol-local state without owning depot truth

    OscpCapacityProviderBinding
    - OSCP-specific specialization of ProjectionBinding for one managed scope
    - stores default group_id, measurement mode, and default scenario preset

    SimulationRun
    - one executing or resumable run pinned to one configuration version
    - owns logical time and mutable depot state

    VehicleRuntimeState
    - runtime state for one simulated vehicle
    - tracks depot presence, SoC, and charging state

    ChargerRuntimeState
    - runtime state for one charger or connector
    - tracks availability, network health, and charging session state

    SensorRuntimeState
    - runtime state for one simulated sensor or meter
    - tracks measured values, heartbeat state, and availability

    NodeRuntimeState
    - runtime state for one electrical node or managed boundary
    - tracks load, constraint, and breach-relevant values

    OscpCapacityProviderSession
    - runtime OSCP relationship for one simulation run and one BetterFleet configuration
    - owns lifecycle state, negotiated behaviour, timers, and correlation state
    - uses lifecycle states offline, accepting_handshake, awaiting_handshake_acknowledge, online, and degraded

    OscpNegotiatedBehaviour
    - effective heartbeat and measurement rules for one session
    - records what the session will actually honour

    OscpScenarioOverride
    - explicit forced behaviour for one session
    - drives timeout, reject, ignore, and mismatch cases

    OscpForecastPlan
    - one scheduled or manual outbound forecast from depot-sim to BetterFleet
    - lets tests send controlled forecast blocks deterministically

    OscpMessageLedgerEntry
    - immutable record of one OSCP message attempt or receipt
    - stores direction, headers, body snapshot, outcome, and validation result
    - validation result is accepted, rejected, ignored, or indeterminate

    OscpMessageExpectation
    - expected BetterFleet outbound message for one scenario or runtime condition
    - supports positive and negative test assertions

    4. Domain Aggregates¶

    Simulation Configuration Aggregate¶

    Root: SimulationConfiguration

    Entities:

    • ManagedScope
    • ElectricalTopology
    • ProjectionBinding
    • OscpCapacityProviderBinding
    • scenario preset definitions

    Invariants:

    • topology is rooted and acyclic
    • every managed scope references an existing topology node
    • every projection binding targets one managed scope
    • projection binding defaults are versioned with the configuration
    • active runs never adopt a new configuration version implicitly

    Simulation Run Aggregate¶

    Root: SimulationRun

    Entities:

    • VehicleRuntimeState
    • ChargerRuntimeState
    • SensorRuntimeState
    • NodeRuntimeState
    • generic ProjectionRuntimeState

    Invariants:

    • each run references exactly one configuration version
    • logical time moves forward only
    • one active runner lease owns one run at a time
    • protocol projections read runtime state through ports
    • protocol projections cannot rewrite saved configuration

    OSCP Capacity Provider Session Aggregate¶

    Root: OscpCapacityProviderSession

    Entities:

    • OscpNegotiatedBehaviour
    • OscpScenarioOverride
    • OscpForecastPlan
    • OscpMessageLedgerEntry
    • OscpMessageExpectation

    Invariants:

    • one active session exists per simulation_run_id + remote_configuration_id
    • session state gates which messages may be accepted
    • message ledger entries are append-only
    • an outcome update may only finalize an existing ledger entry
    • overrides are explicit and time-bounded
    • every accepted inbound BetterFleet message resolves to one session
    • every outbound depot-sim message carries one session identity

    5. Service Boundaries¶

    All boundaries below are internal to bf-depot-sim.

    Simulation Configuration Service¶

    Responsibilities:

    • persist versioned simulation configurations
    • manage managed scopes and projection bindings
    • store projection binding defaults and scenario presets
    • import or translate legacy circuit-centric definitions

    Owned Data:

    • SimulationConfiguration
    • ManagedScope
    • ProjectionBinding
    • OscpCapacityProviderBinding
    • scenario preset definitions

    External Dependencies:

    • configuration repositories
    • configuration translation adapters for supported input shapes

    Simulation Run Service¶

    Responsibilities:

    • start, stop, pause, resume, and tick simulation runs
    • maintain vehicle, charger, sensor, and electrical runtime state
    • expose read ports for projection services
    • emit runtime events relevant to projections

    Owned Data:

    • SimulationRun
    • VehicleRuntimeState
    • ChargerRuntimeState
    • SensorRuntimeState
    • NodeRuntimeState
    • runner lease and checkpoint data

    External Dependencies:

    • SimulationRuntimePort
    • configuration service read port
    • runtime repositories

    OCPP Charge Point Service¶

    Responsibilities:

    • project charger runtime state through OCPP charger endpoints
    • receive BetterFleet charger control requests through OCPP
    • keep OCPP session state outside the core run aggregate

    Owned Data:

    • OCPP session state
    • connector protocol state

    External Dependencies:

    • simulation runtime read and command ports
    • OCPP transport adapters
    • scheduler and clock abstractions

    BetterFleet IoT Packet Service¶

    Responsibilities:

    • project site power and sensor runtime state into BetterFleet packet contracts
    • publish packet sequences at the required cadence
    • retain packet delivery checkpoints and failure state

    Owned Data:

    • packet projection state
    • packet delivery checkpoints

    External Dependencies:

    • simulation runtime read port
    • packet transport adapters
    • scheduler and clock abstractions

    Telematics Service¶

    Responsibilities:

    • project vehicle runtime and route state into telematics-facing interfaces
    • serve or publish vehicle state snapshots without exposing internal simulator objects
    • retain telematics projection state and snapshot metadata

    Owned Data:

    • telematics projection state
    • telematics snapshot metadata

    External Dependencies:

    • simulation runtime read port
    • telematics transport or API adapters

    OSCP Capacity Provider Service¶

    Responsibilities:

    • expose CP protocol routes under /oscp/cp/2.0
    • send outbound handshake, heartbeat, and forecast messages to BetterFleet
    • receive and validate BetterFleet outbound OSCP messages
    • manage lifecycle state, negotiation state, and timeouts
    • persist message ledger and expectations

    Owned Data:

    • OscpCapacityProviderSession
    • OscpNegotiatedBehaviour
    • OscpForecastPlan
    • OscpMessageLedgerEntry
    • protocol timers and correlation metadata

    External Dependencies:

    • bf-manage-core OSCP HTTP endpoints
    • simulation runtime read port
    • scheduler and clock abstractions
    • HTTP client and HTTP server adapters

    Scenario Control Service¶

    Responsibilities:

    • apply named scenario presets
    • apply manual session overrides
    • force reject, ignore, timeout, or mismatch behaviour across projection services
    • raise and retire message expectations for tests

    Owned Data:

    • OscpScenarioOverride
    • OscpMessageExpectation
    • scenario execution history

    External Dependencies:

    • OSCP Capacity Provider Service
    • OCPP Charge Point Service
    • BetterFleet IoT Packet Service
    • Telematics Service
    • Simulation Run Service read port

    6. Event Model¶

    Depot-sim uses two event classes:

    • cross-cutting simulation events that describe the shared simulation world
    • projection-specific events that describe protocol behaviour derived from that world

    The cross-cutting events define simulator truth.

    Projection events never replace that truth.

    SimulationRunStarted

    Triggered when:

    • an operator or API starts a run

    Produced by:

    • Simulation Run Service

    Consumed by:

    • OSCP Capacity Provider Service
    • OCPP Charge Point Service
    • BetterFleet IoT Packet Service
    • Telematics Service
    • Scenario Control Service

    SimulationRunResumed

    Triggered when:

    • depot-sim restores a resumable run after restart

    Produced by:

    • Simulation Run Service

    Consumed by:

    • OSCP Capacity Provider Service
    • OCPP Charge Point Service
    • BetterFleet IoT Packet Service
    • Telematics Service

    ProjectionStateChanged

    Triggered when:

    • any projection service changes health, connectivity, or delivery checkpoint state

    Produced by:

    • OCPP Charge Point Service
    • BetterFleet IoT Packet Service
    • Telematics Service
    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters
    • Scenario Control Service

    SensorPacketPublished

    Triggered when:

    • the BetterFleet IoT Packet Service publishes one packet sequence

    Produced by:

    • BetterFleet IoT Packet Service

    Consumed by:

    • query and inspection adapters

    TelematicsSnapshotServed

    Triggered when:

    • the Telematics Service serves or publishes one vehicle state snapshot

    Produced by:

    • Telematics Service

    Consumed by:

    • query and inspection adapters

    OscpProviderSessionAttached

    Triggered when:

    • a run is bound to one BetterFleet OSCP configuration

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    OscpHandshakeReceived

    Triggered when:

    • BetterFleet calls /oscp/cp/2.0/handshake

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • Scenario Control Service
    • query and inspection adapters

    OscpHandshakeAcknowledgeSent

    Triggered when:

    • depot-sim posts a handshake acknowledgement to BetterFleet

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    OscpHeartbeatSent

    Triggered when:

    • depot-sim posts a heartbeat to BetterFleet

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    OscpHeartbeatReceived

    Triggered when:

    • BetterFleet posts a heartbeat to depot-sim

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    OscpForecastPublished

    Triggered when:

    • depot-sim sends UpdateGroupCapacityForecast

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    OscpOutboundMessageReceived

    Triggered when:

    • BetterFleet sends a measurement, adjustment, or compliance message

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • Scenario Control Service
    • query and inspection adapters

    OscpOutboundMessageValidated

    Triggered when:

    • depot-sim accepts, rejects, or ignores a BetterFleet outbound message

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    ManagedScopeBreachDetected

    Triggered when:

    • simulation runtime detects a breach against an active forecasted scope

    Produced by:

    • Simulation Run Service

    Consumed by:

    • Scenario Control Service

    OscpMessageExpectationRaised

    Triggered when:

    • a scenario or runtime condition expects a BetterFleet outbound message

    Produced by:

    • Scenario Control Service

    Consumed by:

    • OSCP Capacity Provider Service
    • query and inspection adapters

    OscpSessionTimedOut

    Triggered when:

    • handshake or heartbeat timing rules fail

    Produced by:

    • OSCP Capacity Provider Service

    Consumed by:

    • query and inspection adapters

    7. API Contracts¶

    Depot-sim exposes:

    • control and inspection APIs for operators and automated tests
    • protocol APIs that emulate the external interfaces BetterFleet uses in production

    The concrete contracts below show the control surface and the OSCP protocol surface.

    OCPP, BetterFleet packet, and telematics contracts are also part of the reference solution, but their wire-level message shapes are defined by those protocol families rather than restated here.

    Control API¶

    POST /simulation-runs/{simulation_run_id}/oscp-sessions¶

    Creates one OSCP Capacity Provider session for one run.

    Request:

    {
      "managed_scope_id": "scope-grid-1",
      "betterfleet_base_url": "http://bf-manage-core:5001/oscp",
      "remote_configuration_id": "2b5f4a88-d4b4-41ad-a1c8-889f3ee71111",
      "group_id": "group-1",
      "measurement_publication_mode": "GROUP",
      "measurement_configuration": "INTERMITTENT",
      "scenario_preset": "connected_baseline"
    }
    

    Response:

    {
      "session_id": "6dc59c9e-59a9-4f9b-a0f3-cc5d2b721111",
      "state": "offline"
    }
    

    POST /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/commands/send-handshake¶

    Makes depot-sim initiate the handshake.

    Request:

    {
      "heartbeat_interval_seconds": 5
    }
    

    Response:

    {
      "ledger_entry_id": "b2f7b8f2-7181-4f9e-a42d-2f08efea1111",
      "state": "awaiting_handshake_acknowledge"
    }
    

    POST /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/commands/send-forecast¶

    Sends one controlled forecast to BetterFleet.

    Request:

    {
      "type": "CONSUMPTION",
      "forecasted_blocks": [
        {
          "capacity": 500.0,
          "phase": "ALL",
          "unit": "KW",
          "start_time": "2026-04-02T10:00:00Z",
          "end_time": "2026-04-02T10:15:00Z"
        }
      ]
    }
    

    Response:

    {
      "ledger_entry_id": "0f37a794-0f6d-4f66-a0da-2b3b0fe61111",
      "delivery_status": "accepted"
    }
    

    PATCH /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/overrides¶

    Applies or clears a deterministic failure override.

    Request:

    {
      "mode": "reject_heartbeat_with_403",
      "until": "2026-04-02T10:20:00Z"
    }
    

    Response:

    {
      "session_id": "6dc59c9e-59a9-4f9b-a0f3-cc5d2b721111",
      "override_state": "active"
    }
    

    GET /simulation-runs/{simulation_run_id}/oscp-sessions/{session_id}/messages¶

    Returns the message ledger for one session.

    Response:

    {
      "messages": [
        {
          "direction": "inbound",
          "message_type": "UpdateAssetMeasurements",
          "outcome": "accepted"
        }
      ]
    }
    

    Protocol API¶

    All protocol routes use the BetterFleet OSCP routing contract.

    Required headers:

    • X-OSCP-Configuration-ID
    • X-Request-ID
    • X-Correlation-ID when the message answers an earlier message

    Any protocol route may return 503 Service Unavailable.

    That response is reserved for stale or unavailable simulator state.

    POST /oscp/cp/2.0/handshake¶

    Accepts BetterFleet-initiated handshake.

    Successful response:

    {}
    

    HTTP response:

    204 No Content

    POST /oscp/cp/2.0/handshake_acknowledge¶

    Accepts BetterFleet acknowledgement of a depot-sim initiated handshake.

    HTTP response:

    204 No Content

    POST /oscp/cp/2.0/heartbeat¶

    Accepts BetterFleet heartbeat when the session is online.

    Request:

    {
      "offlineModeAt": "2026-04-02T10:15:00Z"
    }
    

    HTTP responses:

    • 204 No Content when accepted
    • 403 Forbidden when the session is intentionally offline or mismatched

    POST /oscp/cp/2.0/update_group_measurements¶

    Receives BetterFleet group measurement publication.

    HTTP responses:

    • 204 No Content when accepted
    • 403 Forbidden when lifecycle or binding state is invalid
    • 422 Unprocessable Entity when payload validation fails

    POST /oscp/cp/2.0/update_asset_measurements¶

    Receives BetterFleet asset measurement publication.

    HTTP responses:

    • 204 No Content when accepted
    • 403 Forbidden when lifecycle or binding state is invalid
    • 422 Unprocessable Entity when payload validation fails

    POST /oscp/cp/2.0/adjust_group_capacity_forecast¶

    Receives BetterFleet manual adjustment request.

    HTTP responses:

    • 204 No Content when accepted
    • 403 Forbidden when no active compatible forecast exists
    • 422 Unprocessable Entity when payload validation fails

    POST /oscp/cp/2.0/group_capacity_compliance_error¶

    Receives BetterFleet compliance error publication.

    HTTP responses:

    • 204 No Content when accepted
    • 403 Forbidden when correlation or lifecycle state is invalid
    • 422 Unprocessable Entity when payload validation fails

    8. Data Ownership¶

    SimulationConfiguration¶

    • Written by: Simulation Configuration Service
    • Read by: Simulation Run Service, OSCP Capacity Provider Service, query adapters
    • Not modified by: Simulation Run Service, OSCP Capacity Provider Service

    SimulationRun¶

    • Written by: Simulation Run Service
    • Read by: OSCP Capacity Provider Service, Scenario Control Service, query adapters
    • Not modified by: OSCP Capacity Provider Service

    OscpCapacityProviderSession¶

    • Written by: OSCP Capacity Provider Service
    • Read by: Scenario Control Service, query adapters
    • Not modified by: Simulation Run Service

    OscpMessageLedgerEntry¶

    • Written by: OSCP Capacity Provider Service only
    • Read by: query adapters and test clients
    • Not modified by: external protocol handlers outside the service boundary

    OscpMessageExpectation¶

    • Written by: Scenario Control Service
    • Read by: OSCP Capacity Provider Service and query adapters
    • Not modified by: BetterFleet protocol calls

    OscpScenarioOverride¶

    • Written by: Scenario Control Service
    • Read by: OSCP Capacity Provider Service
    • Not modified by: BetterFleet protocol calls

    Read models are derived only.

    They are not authoritative write targets.

    9. Operational Workflows¶

    BetterFleet-Initiated Handshake¶

    1. Operator creates an OSCP session for a simulation run.
    2. BetterFleet calls /oscp/cp/2.0/handshake.
    3. The OSCP service resolves the session by X-OSCP-Configuration-ID.
    4. Scenario control decides allow, reject, ignore, or delay.
    5. The OSCP service records the inbound handshake in the ledger.
    6. The OSCP service returns 204 or 403.
    7. When allowed, depot-sim sends /oscp/fp/2.0/handshake_acknowledge.
    8. If BetterFleet accepts, the session moves to online.
    9. The heartbeat schedule starts.

    Capacity Provider-Initiated Handshake¶

    1. Operator calls send-handshake.
    2. The OSCP service posts /oscp/fp/2.0/handshake.
    3. The service records the outbound handshake in the ledger.
    4. The session moves to awaiting_handshake_acknowledge.
    5. BetterFleet calls /oscp/cp/2.0/handshake_acknowledge.
    6. The OSCP service validates the session state.
    7. The session moves to online.
    8. The heartbeat schedule starts.

    Heartbeat and Offline Control¶

    1. When online, depot-sim sends heartbeats on the negotiated interval.
    2. BetterFleet may also send heartbeats to depot-sim.
    3. Each heartbeat updates session liveness state.
    4. An override may stop sending heartbeats.
    5. An override may reject incoming heartbeats with 403.
    6. The ledger stores each accepted, rejected, or ignored heartbeat.
    7. Expired liveness moves the session to offline.

    Forecast Publication¶

    1. Operator or scenario submits an OscpForecastPlan.
    2. The OSCP service validates session state and group_id.
    3. The service posts /oscp/fp/2.0/update_group_capacity_forecast.
    4. The ledger records request headers, payload, and outcome.
    5. Scenario control may raise future message expectations.
    6. Query APIs expose the last forecast result.

    BetterFleet Outbound Message Validation¶

    1. BetterFleet posts a measurement, adjustment, or compliance message.
    2. The OSCP service resolves the session and active binding.
    3. The service validates headers, lifecycle, and correlation.
    4. The service validates message-specific rules.
    5. The service records the message in the ledger.
    6. The service returns 204, 403, or 422.
    7. Query APIs expose whether the message was accepted or rejected.

    Failure Scenario Injection¶

    1. Operator applies a scenario preset or manual override.
    2. Scenario control marks the active session behaviour.
    3. The next matching OSCP action is delayed, ignored, or rejected.
    4. The ledger marks the deliberate outcome.
    5. The override expires or is cleared explicitly.
    sequenceDiagram
        participant BF as bf-manage-core
        participant CP as Depot Sim OSCP CP Service
        participant SCN as Scenario Control
    
        BF->>CP: POST /oscp/cp/2.0/handshake
        CP->>SCN: Check override
        SCN-->>CP: allow / reject / ignore
        CP-->>BF: 204 or 403
        CP->>BF: POST /oscp/fp/2.0/handshake_acknowledge
        BF-->>CP: 204
        CP->>BF: POST /oscp/fp/2.0/heartbeat

    10. Failure Handling¶

    Failure Type Detection Simulator Behaviour
    Service restart Depot-sim process stops or redeploys Reload SimulationRun and OscpCapacityProviderSession state from repositories. Resume only sessions whose timers are still valid.
    Duplicate message delivery Same request identity appears again Return the prior outcome when the request is idempotent. Do not append a second final ledger result.
    BetterFleet unreachable HTTP timeout or transport failure on outbound handshake, heartbeat, or forecast Mark the ledger entry as failed. Move the session to degraded or offline by policy. Keep prior session history.
    BetterFleet stops sending heartbeats Heartbeat expiry elapses Mark the session offline. Close any expectation that requires an online session.
    Depot-sim stops sending heartbeats Scenario override or scheduler failure Keep the ledger history. Let BetterFleet detect offline state naturally.
    Intentional ignore case Scenario override says ignore Record intent in the ledger. Return no response until timeout behavior is satisfied.
    Intentional mismatch case Scenario override forces wrong lifecycle or binding state Return deterministic 403. Record the reason in the ledger.
    Payload shape failure JSON body misses required fields or invalid enum values Return 422. Store validation errors with the ledger entry.
    Stale validation state Runtime snapshot is older than the allowed validation window Return 503 or mark the session indeterminate by policy. Do not silently accept stale semantics.
    Limit or scope violation Message does not match active group_id, asset, scope, or forecast correlation Return 403 for state violations. Return 422 for payload semantics. Record the exact rule failure.

    Failure handling rules:

    • projection failure does not delete simulation state
    • OSCP session failure does not mutate saved configuration
    • every failure must be visible through the message ledger
    • scenario-driven failures must be distinguishable from accidental failures
    • session recovery must be explicit after offline or timeout unless the scenario says otherwise

    11. Future Extensions¶

    • add register, reregister, and unregister when the BetterFleet registration flow is part of the active integration
    • support multiple active OSCP sessions for different managed scopes in one run
    • add segmented message support if the BetterFleet interface needs it
    • add stronger numeric validation of measurement payloads against runtime power windows
    • add UI editing for OSCP scenario presets and active overrides
    • move timer ownership to a durable scheduler when multi-instance execution is required
    • support additional partner profiles without changing the core session aggregate
    • support future Capacity Optimizer flows without moving OSCP protocol state into SimulationRun
    Made with Material for MkDocs