4.6. ADR-006: Centralize Communication Lifecycle Authority

4.6.1. Status

Accepted

Date: 2026-08-24

4.6.2. Context

Deferred communication introduces coordination across transport activation, variant detection, diagnostic admission, runtime updates, and HTTP availability. If each subsystem controls these concerns independently, their views can diverge: transport can be active while initialization is incomplete, an update can race diagnostic work, or one feature can remove another feature’s HTTP restriction.

The required externally visible behavior is specified by Communication Initializatio... (req~dt-deferred-initialization), Variant Detection (req~dt-variant-detection), and ECU States (req~dt-ecu-states). This ADR decides how authority and ownership are divided to implement those contracts.

4.6.3. Decision

Communication lifecycle changes have one public authority: the communication plugin selected at startup. The plugin decides policy, including whether a request is authorized to activate communication. It delegates accepted work to a framework lifecycle coordinator; consumers do not receive direct transport control.

The framework, rather than the plugin, enforces generic invariants:

  • Lifecycle transitions are serialized

  • Diagnostic use excludes an exclusive disable operation

  • Transport and lifecycle hooks are initialized and deinitialized as one coordinated operation

  • Variant re-detection is an operation on enabled communication, separate from transport activation and lifecycle-hook initialization.

Consumers receive capability-specific views of framework-managed resources. Diagnostic handlers can inspect and acquire communication, while runtime update can hold communication disabled and replace components without using those components for diagnostics. HTTP restrictions use independent owned records, not a shared global flag, so one owner cannot remove another owner’s restriction.

The configured post-update communication mode names the requested end state, regardless of the communication state before the update. Enabled requests activation after the update, while Deferred leaves communication down until activation is requested separately. Releasing the update’s exclusive disable lease only restores the state displaced by that lease; the runtime update does not activate communication directly. Instead, it submits the configured request through the communication authority. The selected plugin remains free to reject activation according to its policy: the default plugin honors the request in Always and OnDemand modes, while Disabled leaves communication down.

Configuration, databases, network-inert communication objects, and routes are prepared at startup. This keeps route topology and dependency wiring independent of runtime communication state while preserving the no-traffic-before-activation property for framework-managed transports.

4.6.4. Rationale

Separating plugin policy from framework invariants allows deployments to choose activation policy without requiring every plugin to reproduce concurrency and cleanup rules. Capability-specific views make accidental misuse of managed resources harder and make ownership visible in API boundaries.

Constructing network-inert components eagerly allows SOVD routes to be derived from loaded diagnostic data. Runtime readiness is then represented by lifecycle and per-ECU state rather than by the presence or absence of handlers and components.

Keeping variant detection separate from lifecycle hooks reflects their different lifetimes: transport-dependent hooks have paired initialization and deinitialization, whereas detection is optional and repeatable while transport remains active.

4.6.5. Alternatives Considered

4.6.5.1. Lazy Component And Route Construction

Constructing the gateway, UDS manager, and ECU routes on first activation would make object existence represent readiness. It was rejected because route and component replacement would become part of every activation path, and metadata derived from already loaded databases would be unavailable unnecessarily.

4.6.5.2. Plugin-Owned Lifecycle Mechanics

Giving plugins raw transport control and requiring them to implement transition and exclusion rules was rejected. Policy is intentionally extensible; safety and ownership invariants must remain consistent across plugin implementations.

4.6.5.3. Shared Flags And Global HTTP Gating

Shared booleans for update state, diagnostic activity, or HTTP availability were rejected because they do not encode ownership. Independent leases, guards, and protection records allow cleanup to affect only the resource owned by that operation.

4.6.5.4. Variant Detection As A Lifecycle Hook

Treating detection as a normal lifecycle hook was rejected because re-detection would either reinitialize unrelated hooks or violate their paired lifecycle.

4.6.6. Consequences

  • Activation policy can vary by startup-selected plugin without moving generic lifecycle invariants into plugin code.

  • Framework consumers have narrower access to managed communication resources.

  • Deferred and eager modes share one application object graph and route model.

  • Runtime readiness cannot be inferred solely from transport state or component existence; lifecycle and per-ECU state remain explicit.

  • Runtime update and other HTTP restrictions require owned cleanup resources.

  • The capability boundary reduces accidental authority but does not isolate malicious or defective in-process plugins.

Exact APIs, state transitions, synchronization, cleanup ordering, and route behavior are documented with the owning implementation and architecture.