# 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. ## DEV Runtime Smoke Use this command only for the DEV simulator runtime: ```sh node scripts/dev-m3-hardware-loop-smoke.mjs --live --confirm-dev --confirmed-non-production ``` The smoke writes `reports/dev-gate/dev-m3-hardware-loop.json`. It first checks the frozen DEV endpoint, `http://74.48.78.17:6667`, 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 HWLAB DEV simulator services, not UniDesk substitutes. The script then checks two box simulators, two gateway simulators, active patch-panel wiring for `box-simu-1 DO1 -> box-simu-2 DI1`, a live direct call that reads `DI1=true`, and returned audit/evidence identifiers. Fixture-backed local M3 output is never accepted as live DEV evidence.