Files
pikasTech-HWLAB/docs/m3-hardware-loop.md
T
2026-05-22 18:06:24 +00:00

137 lines
5.5 KiB
Markdown

# M3 Hardware Trusted Loop Local Contract
This contract smoke proves the local M3 wiring path for:
```text
box-simu-1 DO1 -> box-simu-2 DI1
```
The fixture is `fixtures/mvp/m3-hardware-loop/topology.json`. It contains two
`hwlab-box-simu` resources, two `hwlab-gateway-simu` sessions, and one
`hwlab-patch-panel` status object. The active wiring config has one exclusive
connection from `res_boxsimu_1:DO1` to `res_boxsimu_2:DI1`.
Run the smoke locally:
```sh
node scripts/m3-hardware-loop-smoke.mjs
```
## What It Checks
- DEV-only topology with two boxes, two gateways, and one active patch panel.
- Patch-panel-only propagation; box local loopback is not accepted as a
cross-device substitute.
- Direct local call into the existing patch-panel model routes
`box-simu-1 DO1` to `box-simu-2 DI1`.
- An unwired local signal does not cross devices.
- The expected audit event includes the L0 audit fields:
`auditId`, `traceId`, `actorType`, `actorId`, `action`, `targetType`,
`targetId`, `serviceId`, `environment`, and `occurredAt`, plus project,
gateway session, operation, outcome, and metadata fields.
## Boundary
This is a local contract smoke only. It does not deploy DEV or PROD services,
does not connect to real hardware, does not read secrets or tokens, and does
not write `audit_events` rows to a database. The audit event in the fixture is
an expected record shape for the future real flow.
The later real DEV M3 path must replace the in-process direct call with live
service boundaries: cloud request validation, gateway session ownership,
patch-panel state application, real or simulator box observation, persisted
audit events, and evidence records. That future work must preserve the same
wiring contract and must keep routing decisions under `hwlab-patch-panel`
ownership instead of mutating another box directly.
## L2 Local Runtime Smoke
Issue 53 adds a runnable localhost-only L2 simulator contract:
```sh
npm run l2:smoke
```
The smoke starts two `hwlab-box-simu` instances (`box-a`, `box-b`) and two
`hwlab-gateway-simu` instances (`gateway-a`, `gateway-b`) on ephemeral
localhost ports. It verifies:
- box ports for `AI1`, `AO1`, `DI1`, `DO1`, and `FREQ1`;
- internal port API writes for patch-panel-owned delivery;
- gateway register, heartbeat, capability report, and invoke forwarding;
- multi-instance identity separation for `box-a`/`box-b` and
`gateway-a`/`gateway-b`;
- HWLAB JSON-RPC error codes for missing gateway registration and unavailable
capabilities;
- returned audit and evidence object shapes.
This smoke is still not a DEV deploy or PROD deploy. It proves the minimum
runtime surface that later M3/M5 live checks can call. Cross-device propagation
is not implemented as box-simu loopback; the only accepted cross-device owner
remains `hwlab-patch-panel`, which calls the box internal port API.
## DEV Runtime Smoke
Use the no-write plan first:
```sh
node scripts/dev-m3-hardware-loop-smoke.mjs --dry-run
```
The dry-run plan writes `reports/dev-gate/dev-m3-hardware-loop.json` by
default, records `dryRunPlan.evidenceLevel: "DRY-RUN"`, lists the live write
preconditions, enumerates the endpoints that a later live run would call, and
keeps `liveOperation.status: "not_run"`. It does not call DEV endpoints, does
not send `/ports/write` or `/signals/route`, and cannot be promoted to
`DEV-LIVE`.
Use this command only for the approved DEV simulator runtime window:
```sh
node scripts/dev-m3-hardware-loop-smoke.mjs --live --confirm-dev --expect-non-prod
```
The legacy `--confirmed-non-production` flag is accepted as compatibility, but
new handoffs should use `--expect-non-prod`. The script refuses the default
mode and refuses `--dry-run` combined with `--live`.
The live smoke writes `reports/dev-gate/dev-m3-hardware-loop.json`. It first
checks the frozen DEV endpoint, `http://74.48.78.17:16667`, and stops at the
first critical blocker from `docs/dev-acceptance-matrix.md`. When DEV ingress
is not observable, the report is `blocked` and the script does not run the live
`do.write true -> di.read true` operation.
If DEV ingress is reachable, the script requires explicit direct DEV simulator
targets through these environment variables:
```text
HWLAB_DEV_BOX_SIMU_1_URL
HWLAB_DEV_BOX_SIMU_2_URL
HWLAB_DEV_GATEWAY_SIMU_1_URL
HWLAB_DEV_GATEWAY_SIMU_2_URL
HWLAB_DEV_PATCH_PANEL_URL
```
Those targets must be two distinct HWLAB DEV simulator services for each
simulator kind, plus one HWLAB DEV patch panel, not UniDesk substitutes. The
script then checks two box simulators, two gateway simulators, active
patch-panel wiring for
`res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1`, a live direct
call that reads `DI1=true`, and returned operation, trace, audit, and evidence
identifiers. Fixture-backed local M3 output is never accepted as live DEV
evidence.
## Read-Only Continuation Evidence
When DEV ingress is blocked, continuation work may still record read-only
evidence. The smoke report includes a static comparison of
`deploy/k8s/base/workloads.yaml` against the M3 requirement for two
`hwlab-box-simu` instances and two `hwlab-gateway-simu` instances. This is not
live runtime proof. The checked-in DEV manifests are source-ready only when
`node scripts/validate-dev-m3-cardinality.mjs` passes: two `hwlab-box-simu`
replicas with `boxsimu_1,boxsimu_2`, two `hwlab-gateway-simu` replicas with
`res_boxsimu_1,res_boxsimu_2`, and one `hwlab-patch-panel`. If the live runtime
still lacks the required simulator cardinality, the fix is a separate
authorized DEV deploy or runtime task, not a mutation inside the M3 evidence
collection task.