# Echolot — context for Claude Code This repo is the **capability prober** for the Echolot project: an F/OSS Android app for detecting and debugging local network issues (target audience: network engineers). The prober validates the no-root feasibility matrix on real hardware before the production app is built. ## Project facts - **Name:** Echolot. Domain echo-lot.app. URI scheme `echolot://`. Namespace `app.echo_lot.*` (hyphen→underscore; appIds/packages can't contain hyphens). Prober appId: `app.echo_lot.prober`. - **Stack:** native Kotlin + Jetpack Compose. No Flutter (all value is in platform APIs; Flutter would be a Dart skin over a full Kotlin app + F-Droid build friction). - **Tiers:** `app` (no root), `shizuku` (ADB-shell privileges via wireless pairing, shipped in v1), `root` (future module). Every result records which tier produced it. - **License:** code is **GPL-3.0-or-later** (`LICENSE`), the specs in `docs/` are **CC-BY-4.0** (`docs/LICENSE`). New source files get the two-line SPDX header the existing ones carry. The server, when it lands, is GPL too — not AGPL (see `docs/build-status.md` for the reasoning). ## Design docs (source of truth, in `docs/`) - `docs/feature-catalog-and-feasibility.md` — full feature list + no-root feasibility matrix. - `docs/measurement-schema.md` — the archived/exportable measurement JSON format (observation vs finding separation, two-clock rule, columnar trains, anonymization types). - `docs/probe-protocol.md` — client↔server wire protocol (pinned-TLS control plane, binary UDP data plane with anti-amplification HMAC, STUN, canary DNS reference records). - `docs/build-status.md` — running log of decisions, what is delivered, and the next steps. The three specs are draft-complete and user-reviewed; treat them as the contract. `build-status.md` is the mutable one — update it as work lands. Keep prober result IDs aligned with the measurement-schema test-type registry. ## Layout Monorepo. The prober is one deliverable; the Go server and the production app land as siblings. ``` docs/ design docs (above) — apply repo-wide, not just to the prober echolot-prober/ the capability prober (self-contained Gradle build) app/src/main/java/app/echo_lot/prober/ MainActivity.kt Compose host, runs probes sequentially probe/ Probe interface + all app-tier probes + OS ABI helper shizuku/ AIDL UserService + ShizukuRunner (shell command exec) export/Report.kt JSON report + share intent ui/ProberScreen.kt result cards colored by verdict ``` ## Conventions - Every probe returns a `ProbeResult` — never throws to the caller (MainActivity wraps anyway). - Uncertain OS API paths (getsockoptInt, recvmsg, nat64Prefix) are reached via reflection/runCatching and reported, not assumed — the prober's purpose is to discover what exists. - Hardcoded Linux sockopt ABI numbers live in `OsAbi.kt` with rationale; do not "fix" them to OsConstants names that don't exist. ## Build From `echolot-prober/`: `./gradlew :app:assembleDebug` (needs local Android SDK; set `sdk.dir` in `echolot-prober/local.properties`). The Gradle build is rooted there, not at the repo root. First build downloads AGP/Compose/Shizuku from Google Maven + Maven Central. ## Likely next steps 1. Run on physical devices; collect JSON reports across Android versions/vendors. 2. If `trace.errqueue_reachable` is PARTIAL, add the C-over-JNI errqueue shim (recvmsg + cmsg parse) as a `:native` module and a real `traceroute.udp4` probe. 3. Fold the confirmed capabilities + Shizuku dump-format samples back into the production `core-probe` / `core-shizuku` modules.