# `mix mob.attest`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mix/tasks/mob.attest.ex#L1)

Compare a connected device's loaded modules against this build.

    mix mob.connect --no-iex      # set up the tunnel first
    mix mob.attest
    mix mob.attest --json
    mix mob.attest --app my_app   # only this application's modules

## Why

`mix mob.deploy` reports what it did, not what is now true. The case this
was written for: two bundle ids diverged, the BEAM push addressed one app's
container while another app was running, and it **succeeded** — a tick, no
error, and the app carrying on with the old code. Both containers existed, so
every step was honest about itself and the run as a whole was a lie.

`module_info(:md5)` on the device is the same digest `:beam_lib.md5/1` gives
for the local `.beam`. Comparing them catches a push that never landed, landed
in the wrong place, or landed and was never loaded.

## Options

  * `--app NAME`  — narrow to one application. The default is everything
                    `mix mob.deploy` pushes, which is the only scope that
                    cannot drift from what was actually shipped
  * `--node NAME` — attest one node instead of every connected one
  * `--cookie C`  — use this cookie instead of the app's private one
  * `--json`      — machine-readable result on stdout, progress on stderr

## Exit status

Non-zero when any module on the device differs from this build, or when the
check could not run — a check that could not run must not report success.

Modules the device has not loaded yet are reported and are **not** a failure.
Interactive BEAM loads a module when something first calls it, so most of a
bundle is legitimately unloaded at any moment.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
