* feat: add integrated device leasing
* fix: keep metro bearer token out of generated proxy profile
The proxy connect profile is written to disk as a non-secret remote config,
but it unconditionally copied `metroBearerToken` into that file, leaking the
secret at rest. Mirror the cloud path, which keeps `daemonAuthToken` in-memory
only: the token still flows through this connect via the returned flags, and
later commands re-supply it via AGENT_DEVICE_METRO_BEARER_TOKEN. Extend the
non-secret-profile test to assert the bearer token is absent from disk.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPa5Z9GBkeqoxVctC85N7e
* fix: always release device lease on session close
releaseSessionLease + sessionStore.delete ran only on the happy path, after
several awaits (app-log/perf/snapshot teardown, platform close dispatch,
runner stop) that can throw. A failed close therefore stranded the device
lease until the inactivity expiry. Wrap teardown in try/finally so ownership
is always freed; the original error still propagates after finally.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPa5Z9GBkeqoxVctC85N7e
* fix: reconcile integrated device leasing
* docs: simplify remote lease guidance
* refactor: satisfy leasing fallow checks
* fix: harden integrated device leasing
* refactor: deepen device lease lifecycle
* refactor: centralize lease scope projection
* fix: harden proxy lease e2e flow
* fix: address lease review feedback
* refactor: tighten lease release cleanup
* fix: simplify proxy startup output
* fix: harden cloud lease identity
* fix: color proxy startup output
* fix: simplify proxy tunnel placeholder
---------
Co-authored-by: Claude <noreply@anthropic.com>
* test: migrate test app to expo dev client
* docs: align test app device targeting
* docs: clarify dev client setup tradeoffs
* docs: remove stale sdk reference
* feat: expose web network dump through agent-browser
* fix: reduce web network mapper complexity
* fix: gate web network headers by include mode
* test: assert compact web network summary
* refactor: simplify web network dump mapping
* refactor: trim web network coverage
* chore: remove test-only dead exports
Remove 13 production exports that were consumed only by their own unit
tests, along with those tests. Found via a fallow production-vs-default
unused-export differential (exports unused by production but kept "live"
by a test), then each candidate was reachability-traced and the verdict
adversarially re-verified to confirm zero production use (internal,
re-export, registry, or dynamic dispatch).
Removed exports + their dedicated tests:
- backend.ts: hasBackendCapability, hasBackendEscapeHatch (+ orphaned
BACKEND_CAPABILITY_ESCAPE_HATCH_METHODS) — cascade from runtime change
- runtime.ts: assertBackendCapabilityAllowed
- command-catalog/capabilities: (kept — see below)
- commands/cli-grammar/common.ts: commandNameSet (no test; pure dead)
- compat/maestro/support-matrix.ts: MAESTRO_COMPAT_UNSUPPORTED_CAPABILITIES
- core/dispatch-resolve.ts: resolveIosDevice
- daemon-client.ts: openApp (standalone fn; Backend.openApp untouched)
- daemon/daemon-command-registry.ts: listDaemonHandlerCommands
- daemon/post-gesture-stabilization.ts: capturePostGestureStabilizedSnapshot
- platforms/android/scroll-hints.ts: annotateAndroidScrollableContentHints
- platforms/ios/runner-session.ts: stopRunnerSession
- platforms/ios/runner-xctestrun-products.ts: xctestrunReferencesExistingProducts
- replay/script.ts: parseReplayScript
- utils/cli-option-schema.ts: getOptionSpecForToken
- utils/finders.ts: findNodeByLocator
Tests whose real subject is live code (handler routing, snapshot status,
writeReplayScript, maestro doc-sync) were rewritten to drop the dead
symbol while keeping coverage, not deleted.
typecheck, lint, and the unit suite (2568 tests) pass; fallow
production unused-exports drops 231 -> 218 with no new dead code.
* test: restore replay script parser coverage
* test: re-point replay parser cases to parseReplayScriptDetailed
Address review on #836: parseReplayScript was a thin wrapper, but the
parser it drove (parseReplayScriptDetailed) is live via
compat/replay-input.ts and compat/maestro/export-flow.ts. Restore the
record/screenshot/snapshot/gesture/type parsing assertions deleted with
the wrapper, re-pointed to parseReplayScriptDetailed(...).actions, so
.ad parser regressions (--hide-touches/--fullscreen/--force-full,
gesture positionals, --delay-ms) stay covered.
* Revert "test: re-point replay parser cases to parseReplayScriptDetailed"
This reverts commit 20a01e8641.