# @garuda/device-simulator — the device layer

The **swappable boundary** between the engine and the physical world, plus its first implementation.
See **ADR-0006** for the decision and rationale.

## The seam

```
   engine  ──talks only to──▶  Device (interface)  ◀──implemented by──  SimulatedDevice   (today)
                                                                        HardwareDevice    (later — real RFID reader/tunnel)
```

The engine calls `openSession · prepare · read · encode · verify` at the matching **business** states.
The device runs its **own** state machine, *synchronized* with the business workflow:

```
  business:  RECEIVED → SELECTED → DEVICE_READY → SCANNING → RECONCILING → ENCODING → VERIFYING → ACCEPTED → …
  device:      Idle   → Preparing →   Ready    → Scanning →            →  Encoding → Verifying → Complete
```

Both sequences are **derived from the Blueprint** — a config-driven device workflow, just like the business one.
Swapping in the real device layer changes *this package only*; the engine never changes. That is the whole point:
the simulator is the **first implementation of a permanent interface**, not a throwaway stub.

## Files
- `src/device-interface.js` — the `Device` contract + `DEVICE_STATES`. The permanent seam.
- `src/simulator.js` — `SimulatedDevice extends Device`: deterministic, scenario-driven (`happy · short · excess · invalid · writefail · notags · offline`), covers the AC-RT cases. **No per-customer literals** — quantities come from the config the engine passes in; only the abstract scenario shape lives here.

## Run
Driven by the engine harness — `cd ../engine && npm run demo`. The runner injects a `SimulatedDevice`
per scenario and asserts the device state machine completes in lock-step with the business flow.
