# @motebit/verify

The canonical `motebit-verify` command-line tool. A single binary that verifies any signed motebit artifact — identity files, execution receipts, credentials, presentations — including credentials carrying hardware-attestation claims under any of the four canonical sovereign-verifiable platforms (Apple App Attest, Android Hardware-Backed Keystore Attestation, TPM 2.0, WebAuthn).

Network-free. No relay contact, no external service, no cloud dependency. Every trust anchor is pinned in the installed package.

```bash
npm install -g @motebit/verify
motebit-verify example        # verify the bundled sample — no artifact needed
motebit-verify cred.json      # verify your own
```

`motebit-verify example` verifies a sample receipt shipped inside the package, so the tool proves itself the moment it's installed:

```
VALID (receipt)
  task:    69755e82-5c11-47f4-9768-c9fc275f6c93
  motebit: 93d0bd7c-d233-845e-946d-60aff1dcfb69
  signer:  did:key:z6MknTDuE9nStgifh9bzrGNC8AcsxKSoyikuanL4z8jNN6gm
  binding: sovereign · motebit_id commits to the key (offline, no operator)
```

Point it at your own artifact and the output looks the same, dispatched on the artifact type:

```
VALID (credential)
  issuer:   did:key:z6MkhaXgBZDvotDkL5257...
  subject:  did:key:z6MkhaXgBZDvotDkL5257...
  expired:  no
  hardware: secure_enclave ✓
```

## What it verifies

| Artifact                    | Detection                                                       |
| --------------------------- | --------------------------------------------------------------- |
| `motebit.md` identity files | YAML frontmatter + Ed25519 proof                                |
| Execution receipts          | Signed JSON, signer keys chain                                  |
| Tool-invocation receipts    | Signed JSON — the "auto" band of the governance triad           |
| W3C VerifiableCredentials   | `eddsa-jcs-2022` proof, hardware-attestation channel if present |
| VerifiablePresentations     | Signed envelope + every embedded credential                     |
| Skill envelopes             | Signed `skill-envelope.json` (skills-v1)                        |

Point it at a skill **directory** (containing `SKILL.md` + `skill-envelope.json`) and it runs the full envelope-signature + body-hash + per-file-hash cross-check over every file the envelope declares.

Hardware-attestation channel covers every currently-shipped platform:

| Platform                     | Adapter                            | Trust anchor                                                                                                                                                      |
| ---------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `secure_enclave`             | `@motebit/crypto` (built-in)       | ECDSA-P256 signature; self-asserted SE public key                                                                                                                 |
| `device_check`               | `@motebit/crypto-appattest`        | Pinned Apple App Attestation Root CA                                                                                                                              |
| `tpm`                        | `@motebit/crypto-tpm`              | Pinned Infineon / Nuvoton / STMicro / Intel PTT vendor roots                                                                                                      |
| `android_keystore`           | `@motebit/crypto-android-keystore` | Pinned Google Hardware Attestation roots (RSA + ECDSA P-384)                                                                                                      |
| `webauthn`                   | `@motebit/crypto-webauthn`         | Pinned Apple / Yubico / Microsoft FIDO roots                                                                                                                      |
| `play_integrity` _(removed)_ | _(no adapter wired)_               | Removed 2026-05-03. Credentials carrying this platform fail-closed. Use `@motebit/crypto-android-keystore` instead — see `docs/doctrine/hardware-attestation.md`. |

Unknown platform → named error, fail-closed. Missing adapter context → named error, fail-closed. Never silent acceptance.

## Usage

```bash
motebit-verify <file>                     # auto-detect, print human-readable
motebit-verify <file> --json              # structured JSON output
motebit-verify <file> --expect credential # pin expected artifact type
motebit-verify <file> --clock-skew 30     # allow N seconds of clock drift
motebit-verify <file> --strict            # also verify an ExecutionReceipt's result_hash
                                          #   equals SHA-256(result) — reject a signed
                                          #   receipt whose hash doesn't bind its own result

# Platform overrides (defaults match motebit's canonical identifiers)
motebit-verify <file> \
  --bundle-id com.example.app \
  --android-attestation-application-id ./app-id.bin \
  --rp-id example.com

# State exports — verify a relay-asserted content-artifact manifest against the bytes it covers
motebit-verify content-artifact export.json --manifest <header-or-path>
motebit-verify content-artifact export.json --manifest manifest.json --producer-key <hex>  # pin the relay
motebit-verify content-artifact export.json --manifest manifest.json --expect settlement-summary

# Governance triad — verify a human-consent decision (the "approve" band)
motebit-verify approval-decision decision.json
motebit-verify approval-decision decision.json --producer-key <hex>   # pin the approver
motebit-verify approval-decision decision.json --expect-verdict approved
```

### State exports — `content-artifact`

`motebit-verify content-artifact <body-file> --manifest <header-or-path>` verifies the `X-Motebit-Content-Manifest` a relay emits on every state-export endpoint against the response-body bytes it covers — a two-step check: SHA-256 content-hash recomputation, then Ed25519 signature verification against the manifest's declared producer key. `--manifest` accepts either the base64url header value or a path to a JSON manifest file (auto-detected). `--producer-key <hex>` pins the expected signer offline — pair it with the key from `/.well-known/motebit-transparency.json` so a relay key swap is rejected with `producer_key_mismatch` instead of silently verifying a new producer. `--expect <type>` narrows to a member of the closed `ContentArtifactType` registry in `@motebit/protocol`. For the in-browser, live-fetch side of the same verification, see [`@motebit/state-export-client`](https://www.npmjs.com/package/@motebit/state-export-client).

### The governance triad — approve / deny / auto

`motebit-verify approval-decision <file>` verifies a signed `ApprovalDecision` — **proof of permission before a gated act** (the "approve" band). The deny band (`ExecutionReceipt{status:"denied"}`) and auto band (`ToolInvocationReceipt`) verify through the ordinary receipt path. A verified `ApprovalDecision` is **signature-authentic against a key you pin, not authority-bound** — pin the approver with `--producer-key`; verifying against the embedded key alone is circular. Full model, the binding-ladder placement, and the **browser path** (`import { verifyApprovalDecision } from "@motebit/crypto"` — zero-dep, no server): see [the governance-triad guide](https://docs.motebit.com/docs/developer/governance-triad).

> **`@motebit/verify` vs `@motebit/verifier` vs `@motebit/crypto`.** This package (`verify`) is the **CLI binary** a human installs. [`@motebit/verifier`](https://www.npmjs.com/package/@motebit/verifier) is the **browser-safe library** (file I/O + formatting; also re-exports `verifyApprovalDecision`). [`@motebit/crypto`](https://www.npmjs.com/package/@motebit/crypto) is the **zero-dependency primitive** that carries the actual verify/sign functions — import it directly for browser/client-side verification.

**Verifying `android_keystore` credentials requires `--android-attestation-application-id`.** The flag's value is a path to a binary file containing the raw bytes of the leaf cert's `attestationApplicationId` extension — operators capture this once at build time (deterministic from the registered Android package name + signing-cert SHA-256) and commit the file alongside other pinned config. Without the flag, the Android Keystore arm is intentionally unwired (passing a placeholder would false-reject every real claim); the dispatcher reports `"verifier not wired"`.

Exit codes:

- `0` — artifact verified (including hardware-attestation channel)
- `1` — artifact detected but signature / hardware channel invalid
- `2` — usage or I/O error

## Programmatic use

The CLI is a thin wrapper — every capability is available programmatically:

```ts
import { verifyFile } from "@motebit/verifier"; // Apache-2.0 library (file I/O + formatting)
import { buildHardwareVerifiers } from "@motebit/verify"; // Apache-2.0 CLI + programmatic adapter bundle

const result = await verifyFile("cred.json", {
  hardwareAttestation: buildHardwareVerifiers(),
});
```

`buildHardwareVerifiers()` with no arguments uses motebit's canonical defaults (`com.motebit.mobile` bundle, `motebit.com` RP ID, pinned Apple/Google/FIDO/TPM roots). To verify credentials minted by a fork, a federation peer, or a custom build, pass a `HardwareVerifierBundleConfig`:

```ts
import { readFileSync } from "node:fs";
import { buildHardwareVerifiers } from "@motebit/verify";
import { verifyFile } from "@motebit/verifier";

const result = await verifyFile("cred.json", {
  hardwareAttestation: buildHardwareVerifiers({
    // Apple App Attest — non-motebit iOS build
    appAttestBundleId: "com.example.app",
    // Android Keystore — raw attestationApplicationId bytes from the
    // leaf cert, computed once at build time from (packageName, signing-cert SHA-256)
    androidKeystoreExpectedAttestationApplicationId: readFileSync("./app-id.bin"),
    // WebAuthn — relying-party domain
    webauthnRpId: "example.com",
    // Optional — override any pinned root set (test fabrications, federation peer roots, etc.)
    appAttestRootPem: customAppleRootPem,
    androidKeystoreRootPems: [customGoogleRoot1, customGoogleRoot2],
    webauthnRootPems: [customYubicoRoot],
    tpmRootPems: [customInfineonRoot],
  }),
});
```

Every field is optional and falls back to the motebit-canonical default. The Android Keystore arm is wired only when `androidKeystoreExpectedAttestationApplicationId` is supplied — there is no canonical default for the leaf-cert package binding, by design.

## The three-package lineage

This package sits at the top of a deliberate three-layer split — the same shape long-lived tool lineages use (git / libgit2, cargo / tokio, npm / @npm/arborist):

```
@motebit/verify     Apache-2.0  the CLI motebit-verify + bundled adapters  (the tool — this package)
@motebit/verifier   Apache-2.0  library: verifyFile, verifyArtifact, formatHuman
@motebit/crypto     Apache-2.0  primitives: verify, sign, suite dispatch
```

All three are Apache-2.0 with explicit patent grant — the full verification surface ships under the permissive floor. The BSL line stays at `motebit` (the operator console) and everything below it, where the motebit-proprietary judgment actually lives.

- Install **`@motebit/verify`** when you want the command-line tool with every platform bundled. One install, verify anything offline, no license friction in CI pipelines.
- Install **`@motebit/verifier`** when you're writing TypeScript code that needs to read + verify motebit artifacts programmatically and want the dep-thin library without the bundled platform adapters.
- Install **`@motebit/crypto`** when you want the primitives — the verify dispatcher, sign APIs, suite registry — to build your own verification tooling from scratch.

## Superseding the deprecated `@motebit/verify@0.x`

The original `@motebit/verify@0.7.0` was a zero-dep MIT library with a single `verify()` function. It was deprecated and split:

- **The `verify()` library primitive** moved to [`@motebit/crypto`](https://www.npmjs.com/package/@motebit/crypto). Now Apache-2.0 (upgraded from MIT — adds an explicit patent grant), same zero deps, same function shape, plus full sign / verify / cryptosuite support.
- **The file-reading + human-formatting helpers** live at [`@motebit/verifier`](https://www.npmjs.com/package/@motebit/verifier). Apache-2.0, thin layer above `@motebit/crypto`.
- **The `motebit-verify` CLI — the tool most users actually wanted when they typed `npm install @motebit/verify`** — is now this package, shipped on the 1.x line. Runs offline. Verifies every motebit artifact. Bundles every hardware-attestation platform.

If you were on `@motebit/verify@^0.7.0`, migration depends on what you were using:

| You were using                                               | Migrate to                                                                              |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| The `verify()` function in TypeScript                        | `import { verify } from "@motebit/crypto"` — same shape, more features                  |
| `verifyFile()` / `formatHuman()` / programmatic CLI wrappers | `import { ... } from "@motebit/verifier"`                                               |
| Running `motebit-verify` on the command line                 | `npm install -g @motebit/verify` on the 1.x line — same command, full platform coverage |

## Related

- [`@motebit/verifier`](https://www.npmjs.com/package/@motebit/verifier) — Apache-2.0 library underneath this CLI (`verifyFile`, `verifyArtifact`, `formatHuman`)
- [`@motebit/crypto`](https://www.npmjs.com/package/@motebit/crypto) — Apache-2.0 primitives (`verify`, `sign`, suite dispatch; zero monorepo deps)
- [`@motebit/crypto-appattest`](https://www.npmjs.com/package/@motebit/crypto-appattest) — Apple App Attest adapter bundled into this CLI
- [`@motebit/crypto-android-keystore`](https://www.npmjs.com/package/@motebit/crypto-android-keystore) — Android Hardware-Backed Keystore Attestation adapter bundled into this CLI
- [`@motebit/crypto-tpm`](https://www.npmjs.com/package/@motebit/crypto-tpm) — TPM 2.0 EK chain adapter bundled into this CLI
- [`@motebit/crypto-webauthn`](https://www.npmjs.com/package/@motebit/crypto-webauthn) — WebAuthn packed-attestation adapter bundled into this CLI
- [`@motebit/state-export-client`](https://www.npmjs.com/package/@motebit/state-export-client) — browser-safe sibling: verifies the same content-artifact manifests over live fetch (this CLI is the file-on-disk path)
- [`motebit`](https://www.npmjs.com/package/motebit) — reference runtime and operator console

## License

Apache-2.0 — see [LICENSE](./LICENSE) and [NOTICE](./NOTICE).

"Motebit" is a trademark. The Apache License grants rights to this software, not to any Motebit trademarks, logos, or branding. You may not use Motebit branding in a way that suggests endorsement or affiliation without written permission.
