# Echolot — build status & next steps Last updated: 2026-07-29. ## Decided - Name **Echolot**; domain echo-lot.app; 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. - Tiers: `app` (no root), **`shizuku` in v1** (wireless-ADB pairing), `root` future. - **License (decided 2026-07-30):** all code **GPL-3.0-or-later**; the specs in `docs/` **CC-BY-4.0**. Rationale: the moat is the no-root platform research, which is trivially liftable into a proprietary repackage — copyleft is the only option that prevents that, and the F-Droid / network-engineer audience reads GPL as a trust signal rather than friction. The specs go permissive on purpose: a wire protocol only becomes a standard if anyone can implement it. **Not AGPL for the server** — the ASP loophole it closes is speculative here, while blanket corporate AGPL bans would hit exactly the enterprise network teams most likely to self-host. Sole copyright holder, so relicensing the server to AGPL later stays possible. Open: substitute a real legal copyright holder for "Echolot contributors" in the SPDX headers. ## Specs (in `docs/`, alongside this file) - `feature-catalog-and-feasibility.md`, `measurement-schema.md`, `probe-protocol.md`. Considered draft-complete and reviewed by the user. ## Capability prober — DELIVERED (as zip, 2026-07-29) Full Kotlin/Compose project scaffolded: `app.echo_lot.prober`, minSdk 26 / target+compile 35, AGP 8.7.3, Kotlin 2.0.21, Compose BOM 2024.10, Shizuku api+provider 13.1.5, kotlinx-serialization. Probes implemented: `link.snapshot`, `icmp.ping4/6` (unprivileged ICMP datagram), `sockopt.matrix` (TTL/TOS/RECVERR/MTU_DISCOVER), `trace.errqueue_reachable`, `multinetwork.request_and_bind`, `local.mdns_discover`, `peer.ble_advertise`, `shizuku.command_battery` (ip neigh / ip -6 route / ip addr / ip monitor / dumpsys network_stack DHCP+IpClient / dumpsys wifi). JSON export via share intent; results carry verdict + raw evidence. Could NOT be compiled in the cloud sandbox: dl.google.com (Google Maven) and services.gradle.org are proxy-blocked, and no device is reachable for on-device runs. Build + iterate locally (Android Studio / Claude Code). Wrapper is pinned to Gradle 8.14.3. ## Website — `web/` (2026-07-30) Single-page site for echo-lot.app on Cloudflare Workers: static `public/` from the edge, a small Worker for the stable short URLs (`/apk`, `/apk.sha256`, `/fdroid`, `/source`) and `/api/latest`. Version info is resolved from the Gitea releases API at request time (edge-cached 5 min), so tagging a release is the only publish step — the homepage shows the latest version/date/size via progressive-enhancement JS and falls back to pre-release copy otherwise. Auto light/dark via `prefers-color-scheme`: dark = sonar display, light = chart-recorder printout, same amber-accent token system. Deploy: `npx wrangler deploy` from `web/`, or CI via `.gitea/workflows/deploy-site.yml` (needs `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` secrets); full story in `web/README.md`. Open: favicon/wordmark are placeholders until the branding assets land (in progress in a parallel session). ## Branding — `assets/branding/` (2026-07-30) Identity chosen: the **Focus** mark — a quiet lattice of nodes with exactly one under examination (amber) inside teal viewfinder brackets. Tone is surgical measurement, not scanning (sonar-sweep visuals and the "sound out your network" tagline were explicitly rejected); tagline is **"measure, don't guess"**. Palette: abyss `#071522`, tile `#0E2433`, instrument teal `#35E0C4`, finding amber `#FFB454`, foam `#E8F4F2` — teal is always the instrument, the single amber point is the finding. The wordmark is hand-drawn monoline SVG paths (zero font dependency); the second "o" is the signature teal ring + amber ping. Assets: `icon.svg` (+ `icon.png` 512² — Gitea avatars reject SVG), `icon-adaptive-{foreground,background}.svg` (108dp adaptive-icon layers, art inside the 66dp safe circle), `wordmark-on-{dark,light}.svg`, `banner.svg` (1200×300, wired into the repo README), `social-preview.svg`/`.png` (1280×640, for the Gitea/GitHub social-preview slot). The website's placeholder favicon/wordmark can now be replaced from these. ## Next steps 1. Build locally, run on several physical devices (varied Android versions/vendors), collect the JSON reports — especially the real per-device Shizuku dump formats. 2. If `trace.errqueue_reachable` = PARTIAL, add a C-over-JNI errqueue shim (`recvmsg`+cmsg parse) as a `:native` module and a real `traceroute.udp4` probe. 3. Start the Go server skeleton (enrollment + profile + sessions + UDP echo with observation blocks + canary-DNS reference records) per probe-protocol.md. 4. Fold confirmed capabilities into the production `core-probe` / `core-shizuku` modules.