# Security

`mm-harness` executes product code, recipes, and optional custom adapters with
the current user's authority. It is a proof tool, not an OS sandbox.

## Trust boundary

- Bundled actions and recipes are trusted package content.
- A configured library cannot declare itself trusted.
- Untrusted plans that request restricted capabilities stop before runtime
  preparation or side effects with `RECIPE_TRUST_REQUIRED`.
- The failure reports blocked nodes, capabilities, source provenance, and one
  exact approval command.
- Approval is bound to the resolved plan, implementation bundle, project root,
  artifact directory, and execution environment.
- Changed code or inputs produce `RECIPE_APPROVAL_MISMATCH`; an old digest does
  not authorize a new plan.

Never construct an approval from memory. Inspect the plan and use the exact
`userAction` emitted by the failed run. Review custom libraries like application
code because approved code retains the user's filesystem, process, and network
permissions.

## Product-state integrity

Proof must come from supported UI, controller, or API paths. Never write DOM,
React/Redux/MobX state, controller internals, or storage merely to manufacture
the claimed result.

Fixture setup is allowed before the proof window when it is explicit in the
trace. Mutating setup must finish with a real read/assert or visible UI
postcondition.

## Signed deeplink boundary

Treat every raw or original URL parameter as attacker-controlled. Route handlers
may receive only canonical parameters authorized by a valid signature and the
link's `sig_params` list. Never add a handler fallback to original parameters,
including for attribution or a destination considered read-only.

Attribution fields such as `utm_*` may pass through only when they are inside
the signed parameter set, explicitly allowlisted for the destination, and
validated for bounded length and character format before use.

A publishable signed-deeplink proof covers the whole ingress boundary:

1. a valid, signed, destination-allowlisted, format-valid, within-limit
   attribution value reaches the destination;
2. an unsigned candidate parameter reaches neither handler nor destination;
3. tampering with a signed value causes authorization failure or interstitial
   demotion, and no candidate parameter reaches handler or destination;
4. malformed `sig_params` and invalid signatures cause authorization failure or
   interstitial demotion, and no candidate parameter reaches handler or
   destination;
5. a signed attribution key outside the destination allowlist does not reach
   the destination or attribution context;
6. signed attribution values with invalid characters or excessive length do
   not reach the destination or attribution context;
7. handler observations for accepted links contain canonical values only.

Opening the same route from inside an already-running app proves downstream
navigation or analytics consumption only. It is not evidence for external link
parsing, signature verification, or canonicalization.

## Wallet fixtures

Each checkout has one canonical fixture:

```text
temp/recipe/runtime/wallet-fixture.json
```

Initialize it explicitly from an approved fixture or choose the disposable
`--dev` option shown in the [README](../README.md). Never fund a dev fixture.

- Never commit a fixture containing a mnemonic or private key.
- Never print, paste, or record mnemonic/private-key material.
- Use funded fixtures only in the intended isolated environment.
- `fixtures set` reads the password from the fixture; do not put it on the
  command line.
- Human and JSON outputs may identify redacted accounts but must not expose
  secret material.

## Evidence and journals

Recipe output may include application logs, screenshots, traces, and custom
action results. Before sharing it:

- verify the artifact manifest contains only intended files;
- search human output, JSON, traces, diagnostics, and reports for credentials;
- confirm screenshots use the declared provider and show no sensitive UI;
- keep task-local artifacts out of source control unless intentionally reviewed.

`mm-harness last --json` stores a redacted resumability record. It is not a
secret store.

## Runtime isolation

Extension uses a checkout-owned Chrome profile and CDP port. Mobile resolves a
checkout-owned simulator/device and Metro port. Core is headless. Parallel
checkouts must not share profiles, runtime directories, process markers, or
evidence directories.

On macOS, Extension Chromium uses a mock keychain so an isolated test profile
does not touch the operator's login keychain. Product configuration and wallet
fixtures remain user-owned; the harness detects missing prerequisites but never
invents them.

## Release checks

Security-sensitive changes require:

1. trust-boundary tests proving rejection occurs before side effects;
2. exact-digest success and stale-digest rejection;
3. redaction tests for arguments, results, journals, and evidence;
4. packed-install provenance with no local links;
5. independent review of the exact diff.

Use [QA](QA.md) for the runnable checklist.
