Files
trail-mate/docs/specification/CROSS_PLATFORM_PRODUCT_ARCHITECTURE_SPEC.md
T

7.1 KiB

Cross-Platform Product Architecture Specification

This is the top-level architecture baseline for Trail Mate's cross-platform product family. It does not replace the existing incremental migration. It defines the shared language, target structure, and review rules that later LoRa, GPS, BLE, UI, Linux, and embedded work must use.

Phase 1 is architecture baseline work only. It must not extract phone cores, rewrite adapters, change PKI behavior, move large source trees, or turn target manifests into a runtime configuration system.

Core Rule

Target chooses.
Board describes.
Platform adapts.
Runtime schedules.
Capability provides.
Protocol interprets.
UseCase decides.
AppService coordinates.
PresentationModel projects.
Renderer draws.
CompositionRoot wires.

In Chinese project terms:

Target decides the product combination.
Board describes hardware facts.
Platform adapts platform capabilities.
Runtime owns scheduling and race boundaries.
Capability provides a device ability.
Protocol interprets protocol semantics.
UseCase performs business decisions.
AppService coordinates business objects.
PresentationModel projects displayable state.
Renderer only draws.
CompositionRoot only assembles dependencies.

Layer Responsibilities

Layer Owns Must not own
Target Product combination, selected platform, selected board, UI shell, authorities, capability bindings, race policy Hardware pin facts, protocol semantics, business code
Board Hardware facts, pin maps, bus maps, electrical constraints, board bring-up facts Business behavior, protocol interpretation, UI page logic
Platform SDK/OS/framework adapters, driver host integration, storage backend adapters, BLE/serial/SPI/I2C/USB host integration Meshtastic/MeshCore semantics, direct-message policy, PKI policy, UI state
Runtime Task/thread/event-loop ownership, ISR deferral policy, queue ownership, lock policy Business decisions or protocol interpretation
Capability Abstract ability exposed by a board/platform binding, such as LoRa, GPS, BLE, storage, display, input Product policy, protocol semantics, UI layout
Protocol Wire formats, protocol codecs, semantic mapping from protocol frames to domain commands/events Board pins, BLE stack APIs, UI widgets, storage backend details
UseCase Business decisions and invariants Platform API calls, renderer code
AppService Coordination of use cases and domain state behind stable app APIs LVGL, GTK, ASCII, board-specific branches
PresentationModel UI-independent view/workspace state and actions Toolkit objects, terminal handles, hardware access
Renderer Concrete drawing and input event translation for LVGL, GTK, ASCII, CLI, or headless shell Business logic and mutable service ownership
CompositionRoot Wires target manifest, board facts, platform factories, app services, presentation models, and renderers Runtime behavior hidden across random files

Canonical Dependency Direction

Renderer
  -> PresentationModel
    -> AppService
      -> UseCase
        -> Domain / Protocol Core / Ports
          <- Platform Adapter

CompositionRoot
  -> Target Manifest
  -> Board Package
  -> Platform Factory
  -> Runtime Context
  -> AppService / PresentationModel / Renderer graph

Board facts may be consumed by platform factories and composition roots. Shared core code must not include board, platform, or UI headers.

Non-Negotiable Boundaries

Board packages must not know business behavior. A board may say that a radio is an SX1262 on a given SPI bus; it may not say how direct messages, PKI, contacts, or phone protocol responses work.

Platform adapters must not interpret product protocol semantics. A BLE host may own advertising, services, characteristics, callbacks, notify operations, MTU, chunking, and stack-specific lifecycle. It must not own Meshtastic or MeshCore phone protocol behavior.

Radio adapters must not own direct message, PKI, peer key, contact, or phone-core policy. They may send and receive packets and report radio status.

GPS drivers must not directly serve UI, BLE, Mesh, or storage policy. They may provide bytes, fixes, timestamps, diagnostics, or device status through declared capabilities.

Renderers must not own business logic. They consume presentation snapshots and emit UI actions.

App services must not know LVGL, GTK, ASCII, CLI, terminal handles, screen sizes, font objects, or widget classes.

Protocol cores must not know Bluefruit, NimBLE, BlueZ, USB CDC, UART driver objects, board pins, or UI toolkit objects.

Shared core modules must not include platform, board, SDK, or UI toolkit headers.

Target, Board, Platform

These three words are deliberately separate.

Platform is the chip, OS, SDK, and runtime environment family:

esp32
nrf52
linux
test

Board Variant is a concrete hardware variant:

t_lora_pager
t_deck
gat562
uconsole_aio2

Target is the product composition:

esp-t-lora-pager-lvgl
esp-t-deck-lvgl
nrf52-gat562-node
linux-uconsole-gtk
linux-uconsole-ascii
linux-headless

Avoid ambiguous language such as "the ESP32 target" or "the Linux target" when the actual distinction is platform, board, shell, or product target.

Capability and Authority

Capabilities describe available abilities such as LoRa, GPS, BLE, storage, display, input, battery, hostlink, and network.

On dual-MCU targets, a capability may be provided by a wireless companion. That does not move business authority to the companion. For ESP32-P4 plus ESP32-C6 products, P4 owns Trail Mate meaning while C6 owns BLE, ESP-NOW, and Wi-Fi surface mechanics through HostLink C6.

Authorities describe where mutable truth lives. Examples:

identity
peer_key_store
node_store
message_store
location
time
config
device_status
ui_state

Every target manifest must say which execution host owns each authority. If an authority is proxied, the target must say whether the proxy is packet-level, command-level, snapshot-level, or disabled.

Composition Root Rule

Composition roots may contain target-specific decisions. They are the place that connects board facts to platform adapter factories and app services.

Non-composition-root code must not accumulate product selection macros such as BOARD_*, TARGET_*, or CONFIG_IDF_TARGET* unless the file is explicitly a platform build adapter or compatibility wrapper already recorded as a known violation.

Phase 1 Scope

Phase 1 adds:

architecture specification
glossary
target manifest specification and drafts
board package specification and drafts
runtime/concurrency specification
UI presentation specification
core_device vocabulary types
PR review checklist
non-blocking boundary report script
known historical violations log

Phase 1 intentionally does not:

extract MeshtasticPhoneCore
extract MeshCorePhoneCore
rewrite LoRa adapters
rewrite GPS services
rewrite LVGL pages
add GTK or ASCII UI behavior
fix Linux direct message behavior
change PKI behavior
move large source trees
make target manifests runtime configuration
block CI on the new architecture checker