Files
trail-mate/docs/engineering/linux-peer-directory.md
T
Trail Mate Dev 6e613e382e Add CM0 Linux support and share device services across platforms
Compose the CM0 fullscreen application and standard Debian package, align the
Cardputer Zero shell, and share protocol, configuration, audio and storage
services with embedded targets through existing platform seams.

Add the paginated on-device TMAP creator using Center's published producer,
private workspace recovery and direct keyboard shortcuts. Preserve unfinished
management work behind its existing opt-in capability.

Include native, ARM and shared-core regression fixtures, integration records,
packaging helpers and dependency/license updates. Keep local build trees,
device credentials, produced packages and validation logs outside version control.

Validation before integration: ESP stack hygiene, Reticulum scope guard, staged
whitespace checks and GitNexus scope audit. Prior device/build evidence and
remaining hardware/package boundaries are recorded in the acceptance documents.
2026-10-29 10:29:29 +08:00

69 lines
3.8 KiB
Markdown

# Native peer directory ownership
## Shared data, native concurrency
`LinuxPeerDirectory` implements the existing `IMeshPeerDirectory` port around
one `MeshPeerDirectoryCore`. Its format, protocol partitions, identity keys,
fact-merging rules and local flags remain owned by that core. Native callers
serialize memory operations through a short recursive mutex; no blob I/O runs
under that mutex. Read-only visitor reentry is allowed, while mutation or flush
from a visitor returns Busy instead of invalidating its scan or deadlocking.
One storage thread loads the existing blob, encodes persistence snapshots and
saves them. Startup `begin()` waits for initial loading. Runtime `record()`
acknowledges admission to the in-memory owner and schedules persistence; it
does not assert a durable observation. Administrative mutations retain an
explicit persistence barrier before returning, and `flush()` waits for a fresh
attempt covering its target revision. These administrative/startup barriers
can wait for storage and are not frame-loop query operations.
The storage thread allocates its encoded byte buffer outside the mutex, copies
a coherent core revision under the mutex and performs the physical write after
unlocking. It acknowledges a revision only after the port accepts that write.
Concurrent newer observations stay dirty and are encoded again. Save failure
retains dirty memory and retries with a bounded pause; a later explicit barrier
does not reuse an earlier failed attempt as its result. Shutdown rejects new
mutations and attempts the newest admitted snapshot, including updates that
arrived during an older in-flight write. A failed volume cannot create an
endless shutdown retry loop.
Core policy mutations apply in memory before persistence. An I/O error is
reported by the barrier; it does not roll back that in-memory user decision.
Callers must distinguish accepted policy from durable storage rather than
assuming an error restores an older policy. This preserves the existing core
merge model without introducing another policy table or optimistic UI owner.
## File effects
The native composition still supplies the existing resolved storage path and
logical `mesh/peers.bin` file.
The resolved path is pinned before its storage thread starts, so shutdown I/O
does not depend on the lifetime of a global path-configuration object.
Linux publication uses an exclusively created,
descriptor-relative temporary file, synchronizes file contents, atomically
renames it over the target and synchronizes the containing directory. It does
not unlink the previous book before publication. Failures retain the previous
target whenever publication has not occurred. A rename followed by failed
directory synchronization reports uncertainty as failure and leaves the core
dirty for retry.
Corrupt and truncated existing snapshots refuse loading and do not accept
ordinary mutations. Missing storage is distinct from a valid loaded book; the
core's canonical codec still validates record shape and CRC. This is not a new
peer-file format or an automatic repair/migration policy.
## Verification
The native regression blocks the actual persistence port while reading and
admitting a newer observation, checks that the newer revision is eventually
saved, verifies explicit barriers, retries a failed revision, preserves local
flags/aliases on runtime updates and rejects visitor mutation. It also stops
with an older snapshot blocked and confirms that the later accepted update is
drained. Reopen and corrupt-blob retention are covered. Source/core units run
with ASan, UBSan and leak checks on native Linux.
Reticulum ingress now uses this port from its protocol worker. The UI contact
service reads the same protected memory owner through its existing contract;
node events do not introduce a second directory or perform background writes
against an unprotected UI-owned core.