NODEDC_PLATFORM/device-plane/docs/IMPLEMENTATION_BASELINE.md

203 lines
8.0 KiB
Markdown

# Device Plane Implementation Baseline
Status: PostgreSQL, Control Core and Gateway foundation are running healthy on
Synology. The accepted foundation has public ingress and discovery ingest
disabled. The next additive transition enables only an authenticated,
quarantine-only ARUSNAVI B2 discovery path on raw TCP 9921. Command transport
remains disabled.
## Product boundary
The Device Manager user interface is a canonical Foundry Page Library
template. Foundry owns page instances, layout, presentation and an opaque
`device-plane-control` binding. It does not own device records, credentials,
raw protocol or command delivery.
The independent NDC Device Plane owns physical-device state and direct
connections:
```text
Foundry Device Manager Page
|
| device-plane-control (typed server boundary)
v
Device Control Core <-> Device PostgreSQL
|
v
Device Gateway <-> physical devices
```
Engine L2 may consume safe decoded observations and build workflows/Data
Products. It does not own TCP sessions, secrets or the command transport.
## Preserved production path
The existing Gelios -> Engine L2 -> External Data Plane -> Foundry Map path is
outside this implementation slice. Its credentials, workflows, Data Products,
bindings and map presentation must not be changed or restarted by a Device
Plane artifact.
The first B2 pilot adds an NDC server route in parallel and keeps the existing
Gelios route unchanged.
## Source and runtime placement
Source:
```text
platform/device-plane/
packages/device-protocol-contract/
packages/arusnavi-b2-adapter/
services/device-control-core/
services/device-gateway/
docker-compose.device-plane.yml
```
Planned Synology runtime:
```text
/volume1/docker/nodedc-device-plane
```
Planned Compose project and services:
```text
nodedc-device-plane
device-control-core
device-gateway
device-postgres
```
`device-postgres` is a private persistent prerequisite. Application overlays
must never force-recreate it or its volume.
The canonical runner selects only `device-control-core` and `device-gateway`
with `--no-deps`. Its health acceptance is scoped to the selected services and
requires the fail-closed fields to remain disabled. A failed first activation
removes only candidate stateless services and never requests volume removal.
Rollback now records an explicit pre-apply service inventory in the backup;
the existence of the shared Compose file does not imply that Core or Gateway
existed before apply.
The exact foundation recovery validates the failed archive, journal, backup,
partial live source and observed healthy image/container generations. It then
publishes the matching source and performs read-only runtime acceptance. It
does not build, restart, recreate or remove any service.
## Network boundary
The accepted foundation publishes no device port. The reviewed pilot transition
publishes `9921/TCP` from Device Gateway after a port-collision check and keeps
health endpoints loopback-only.
`device.nodedc.ru` is a DNS name, not an HTTP/TCP mode. The same name may later
serve an HTTPS Control API on 443 and the B2 raw TCP protocol on 9921.
DSM HTTP/HTTPS Reverse Proxy is not a raw TCP ingress and must not be configured
as `443 -> 9921`.
The artifact never changes DSM firewall, DSM Router Configuration, DNS or a
physical router.
## Identity and onboarding
An IMEI is a claimed protocol identifier, not proof of tenant ownership.
- An unknown connection produces a quarantine-only discovery.
- A discovery never receives commands.
- Pilot claim requires an explicit platform-admin action.
- Production assignment requires authoritative pre-enrollment or an audited
inventory import.
- First-claim-wins by IMEI is forbidden.
The ARUSNAVI Web account login/password is used only by the human operator to
configure the additional device route. It is not a Device Plane credential.
## Protocol evidence
The official B2 material proves:
- four simultaneous monitoring server routes;
- `INTERNAL`, `EXTERNAL`, `USER_AG` and EGTS variants;
- INTERNAL server-side identification by modem IMEI;
- server route fields for DNS/IP, TCP port, protocol and optional ID;
- SMS/TCP command families and a six-digit device access password.
The official ARUSNAVI INTERNAL protocol sheet now provides the first read-path
framing contract:
- HEADER2 for GPRS is `FF 23` followed by an eight-byte little-endian IMEI;
- the server confirms HEADER2 with a bounded `SERVER_COM` carrying Unix time;
- a PACKAGE begins with `5B`, carries a package number in `01..FB`, contains
one or more length-framed PACKET records and ends with `5D`;
- every PACKET checksum is verified before acknowledgement;
- every valid PACKAGE is acknowledged by package number;
- without acknowledgement the tracker repeats the transmission.
The pilot codec implements only that verified read/acknowledgement subset. It
does not decode telemetry tags, export command builders or accept arbitrary
server commands. An IMEI parsed from a valid HEADER2 remains a claimed
identifier and never proves tenant ownership.
## Command boundary
Outbound command transport is disabled in this baseline. No command builder is
exported.
Later lifecycle:
```text
draft -> planned -> awaiting_confirmation -> queued -> dispatched
-> acknowledged | failed | expired | unknown
```
`send` is not success. An `unknown` result forbids automatic retry.
Erase, factory reset, firmware/custom firmware, physical outputs and arbitrary
raw TCP remain forbidden until separate reviewed acceptance slices.
## Implemented local foundation
- Provider-neutral discovery, contour and opaque Foundry-binding contracts.
- B2 model profile with four parallel routes and INTERNAL/IMEI evidence.
- PostgreSQL migration for model profiles, contours, quarantine discoveries,
claimed devices, Foundry bindings and append-only audit events.
- Core health endpoint and an authenticated quarantine-ingest boundary that is
disabled unless explicitly enabled with file-backed secrets.
- Gateway discovery-only HEADER2/PACKAGE state machine with bounded buffers,
handshake timeout, concurrent/per-source session limits and per-source
connection rate limits.
- Authenticated Gateway-to-Core discovery ingest. Core HMAC-hashes the full IMEI
and persists only its digest, masked view and verified framing evidence.
- Only HEADER2 and valid PACKAGE acknowledgements are emitted; no command
builder or command transport is present.
- Recursive rejection of secret-like fields, raw payloads and command-shaped
input in presentation contracts.
- Automated contract, adapter, migration, Core and Gateway tests.
- Additive `component=device-plane` runner registry with exact roots, builds,
services, allowlist/denylist, runner-owned secrets, health contracts and
automatic source/runtime rollback.
- Deterministic data-only artifact builder and positive/negative regression
tests.
- Compose foundation with a private internal network, preserved PostgreSQL
volume, file-backed database password and loopback-only health publishing.
- Exact one-time PostgreSQL bootstrap descriptor, deterministic builder and
absence preflight: an existing database container or volume fails closed,
and rollback never removes the volume.
## Next source slice
1. Add the versioned B2 discovery-ingress descriptor and runner acceptance
contract without weakening foundation/recovery acceptance.
2. Build a deterministic data-only app-overlay and promote the runner extension
through the standalone root administrative gate.
3. Plan/apply the exact discovery-ingress artifact and independently prove:
Core/Gateway/PostgreSQL health, PostgreSQL generation preservation,
`0.0.0.0:9921` publication, verified framing, quarantine-only Core ingest and
disabled command transport.
4. Only after runtime acceptance, allow TCP 9921 in DSM firewall and configure
WAN-to-NAS TCP forwarding. Keep the HTTP(S) Reverse Proxy out of this path.
5. Add the NDC route to one approved B2 free server slot while preserving
Gelios, then prove HEADER/discovery/PACKAGE acknowledgement. Claim and
tenant assignment remain a later explicit platform-admin operation.