mirror of
https://git.churchofmalware.org/leviathan/OVERWATCH
synced 2026-09-24 08:35:03 +00:00
46aa2e55919dc5919e0479934359b8b368156c29
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
46aa2e5591 |
v0.5.15 — second Waze backend: the app protocol, no API key (opt-in)
Until now Waze cost money. The public live-map/api/georss endpoint every
scraper used is fronted by Google's edge and returns HTTP 403 to automated
clients regardless of IP, headers, TLS fingerprint or headless-vs-headful
browser — Waze's own page requests included — so the only way in was OpenWeb
Ninja's hosted feed at roughly $0.005/request.
There is another way in: the protocol the Waze app itself speaks. OVERWATCH
can now register an anonymous Waze account (Waze mints the credentials on
request) and query alerts directly. Free, keyless, live, and polled every 60 s
instead of every 4 min.
It is off by default and stays off until the user picks it, because it is not
a free lunch: the app becomes a Waze client. It holds a Waze account and sends
a position — the protocol layer blurs it by up to 500 m, but it is still
roughly where you are — to a Google service on every poll. In an app whose
whole purpose is knowing who is watching you, that has to be an explicit
choice, so the Settings screen states it in those terms rather than burying it.
OpenWeb Ninja stays the default and is unchanged.
Shape:
- scan/WazeSource.kt is the backend interface. Both clients implement it and
each sets its own poll cadence, so WazeScanner no longer knows or cares
which one it is talking to, and neither leaks into scoring or the UI.
- scan/WazeClient.kt (OpenWeb Ninja) is behaviourally unchanged; its alert and
result types simply moved to the interface.
- scan/wazert/WazeRtFetcher.java is ours: session lifecycle, the encrypted
anonymous account, the per-day registration cap and the backoff.
Vendored, not written here: scan/wazert/*.java and app/src/main/proto/
waze.proto are the Waze RT protocol layer from highway-radar-sabre-plus (MIT),
kept with its licence beside the code. Changed only in the package name, an
OkHttp-to-HttpURLConnection swap so the app takes no new dependency, and the
removal of the report-submission path — OVERWATCH reads alerts and never
reports one, and the codec's report builder is deleted so it cannot.
Protocol behaviour worth recording, all verified live rather than read from
source (2026-09-21, from a Linux host and an Android 16 emulator):
- The session is stateful. /command sends each alert once, then a removal as
an old_command string "RmAlert,<uuid>", not a message type. Treat a response
as a snapshot and the feed goes empty after the first query, so responses
merge into a cache with a 5-minute soft-delete.
- A fresh account's first /command almost always returns an in-band
ServerError{504, "Retry"} inside an HTTP 200. It succeeds on retry, so it is
absorbed rather than counted as a failure.
- Login sets a Waze-Session-Affinity cookie every later request must carry,
and the session idles out after ~100 s.
- Longitude arrives as unsigned 32-bit micro-degrees and must be mapped back
to signed, or the western hemisphere lands on the wrong side of the planet.
- Data volume inverts the usual instinct: ~195 KB for a session's first
response, ~8 KB per query after. Polling faster (60 s, under the idle
timeout) uses less data than polling slowly, because a re-login re-sends the
whole viewport. Hence the cadence.
- Registration is capped per device per day, so the account is persisted
encrypted via SecureStore and reused; a rejected one backs off 30 s → 10 min
instead of spinning the register loop.
Build: applies com.google.protobuf 0.10.0, the first release compatible with
AGP 9 (earlier ones bind to the removed applicationVariants API), with protoc
and protobuf-javalite 4.35.0. On Android the plugin creates no "java" builtin,
so the lite generator is requested via maybeCreate. Costs ~0.6 MB of APK.
Verified end to end on an Android 16 emulator, not just in a harness:
registered an account, logged in, queried, and raised a real detection —
"Police report @ 250m, 16min ago", score 54, YELLOW. Cross-checked against a
live query: the one report inside the 2 km evaluation radius was 58 minutes
old, past the 45-minute cutoff, and the app correctly showed all-clear until
the position moved next to a fresh one.
Also: radio rows in Settings are tappable across their full width instead of
only on the 20 dp circle, which also fixes the theme picker.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RsfSpnwuxCkcXKkD9XH8SR
|
||
|
|
d8c916f25c |
v0.5.14 — smart-glasses identifiers from Nearby Glasses, Sonos mislabel fix
Extends the GLASSES family of the COMMERCIAL source from the identifier set curated by Nearby Glasses (Yves Jeanrenaud, github.com/yjeanrenaud/ yj_nearbyglasses, AGPL-3.0). What is taken is the project's published identifiers — facts about the radio protocol — not its code, and every company id was re-verified against the Bluetooth SIG assigned-numbers registry (4,035 entries) before landing. New coverage: - HeyCyan-SDK primary service UUID 7905FFF0-B5CE-4E99-A40F-4B1E122D00D0, which identifies the Nilox Smart AI Glasses (ALDI/Hofer) and other HeyCyan-based frames. It is fixed on the software side, so it survives the randomised MACs and unstable names that defeat most glasses detection. - Service UUIDs are now read from advertised service-data keys as well as the service list; HeyCyan frames have been seen carrying it either way. - Case-insensitive name tokens rayban / ray-ban / ray ban / heycyan, kept separate from the case-sensitive hint list so short generic words stay strict. - The HeyCyan and Echo AVS service UUIDs join the screen-off ScanFilter set, ahead of the company ids, so glasses can be caught with the phone in a pocket. COMPANY_IDS is reordered glasses-first for the same reason: with the 16-slot cap, what falls off the end is now a fixed home speaker, not a body-worn camera. Verified on Android 16: 19 filters trim to 16, no scan failures. Deliberately not taken: 0x05D6 (Zhuhai Jieli). Nearby Glasses lists it for the Rogbird VisionPro and Rollme VistaView, but it is the id of the Jieli JL70xx Bluetooth chipset found in a huge share of cheap earbuds and speakers; matching it would label every one of them "Smart glasses". Same rationale as the existing TCL exclusion. Documented in MicTargets, README and SOURCES.md. Also fixes a pre-existing mislabel surfaced by the registry check: 0x05A7 is Sonos Inc, not "Yingxin / cheap-spy-cam". It was mapped to HIDDEN_CAM and would have tagged a Sonos speaker as a hidden camera. Sonos stays in scope (the Era/One lines carry always-on microphones) under a new SONOS family that reads "Sonos speaker". Credit added to README (reference repos), SOURCES.md §3.7 and the showcase site. Two small upstream notes recorded for passing back: the CSV's Snap row carries 0x0D53 (Luxottica; the project's code has Snap correctly as 0x03C2), and its scanner reads only the first manufacturer-data entry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
d3e4a1a5cd |
v0.5.12 — decouple scoring from the range control entirely
Reported from a real device: with "show within" at 1100 m the circle was YELLOW on a police report 312 m away scoring 52; dragging to 300 m turned it GREEN and said "All clear". Same spot, same police car. v0.5.10 fixed the widening direction by calibrating the curves, but the narrowing direction was still broken and is worse — a view setting that can hide a live alert, and silently turn the circle green while it does, is a trap rather than a feature. The earlier verification swept the slider at a location where the nearest thing scored 35, so it could not have caught this. Root cause was structural, not calibration: the scanners used the user's setting as their emit cutoff, so it decided what entered the store, and the store decides the tier. Scanners now evaluate at their own fixed radii (DeFlock 1200 m, Waze 2000 m; aircraft already had its own), DetectionEvent carries the distance it was observed at, and the UI filters only what it *draws and lists*. Anything at YELLOW or above is shown regardless of range. Removes the now-dead refresh() paths and the jobs that drove them, since a range change no longer needs to touch a scanner. Verified on device: a camera 285 m away scoring 48 holds the tier at YELLOW from a 200 m view range through 4900 m, both out-of-range alerts stay listed rather than vanishing, and standing 29 m from a camera still reads 89 RED. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RsfSpnwuxCkcXKkD9XH8SR |
||
|
|
76faa840b1 |
v0.5.11 — Android 15/16 + display-cutout compatibility, BLE screen-off fix
Two separate compatibility bugs, both reproduced before fixing. **Edge-to-edge.** Android 15 draws apps edge-to-edge whether or not they ask for anything targeting SDK 35, and the statusBarColor/navigationBarColor theme attributes this app relied on became no-ops at the same time. Reproduced on a fresh Android 16 emulator with a punch-hole cutout: the shipped v0.5.11-1 drew "OVERWATCH" inside the status bar next to the clock, buried the settings gear under the wifi and battery icons where it could not be tapped, and jammed the permission hint into the gesture bar. MainActivity now calls enableEdgeToEdge() explicitly — so the behaviour is the same on older releases rather than shifting under the user on an OS upgrade — and both screens pad themselves with WindowInsets.safeDrawing, which covers the system bars and the cutout. The background still runs edge to edge; only content is held clear. The overlay bubble states LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT rather than relying on it, since a draggable free-floating window could otherwise park under a camera hole. **BLE with the screen off.** Since Android 8.1 the Bluetooth stack stops delivering results for scans started with no ScanFilter once the screen turns off, and a foreground service does not exempt it — it is a stack rule, not a process-lifetime one. This app called startScan(null, ...) while promising to keep watching from a pocket, so BLE detection was silently dead in exactly the case that matters. A ScanFilter cannot express an OUI prefix, so the primary MAC-prefix method genuinely cannot run with the screen off; what can be named precisely still can. The scanner now switches on ACTION_SCREEN_ON/OFF: unfiltered while the screen is on, and a filtered scan (Raven service UUIDs, the XUNTONG manufacturer id, mic-target company ids) while it is off, capped at 16 filters because slots are a hardware resource and a silently empty scan is the worst failure this app has. The drill-down says so rather than hiding it. Verified on Android 16 (API 36) and Android 14: foreground service starts with types=0x18, all five scanners run, screen off logs "filtered scan (16 filters)" and screen on returns to unfiltered, zero scan failures, zero crashes. SOURCES.md gains a platform-constraints section covering these plus the BLE 5-starts-per-30s limit, WiFi scan throttling, and WifiManager.startScan()'s deprecation and planned removal. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RsfSpnwuxCkcXKkD9XH8SR |
||
|
|
19622b87e1 |
v0.5.10 — recalibrate distance curves so range can't move the threat tier
The scores were already absolute, but the tier is max(score) over everything *reported* and the range slider decides what is reported — so the setting still leaked into the alarm. Measured against a real 195-node cache: standing still and dragging the slider from 300 m to 500 m flipped the app from GREEN to YELLOW with nothing physical changing. The fix is calibration, not plumbing. Every curve now crosses below the YELLOW line at roughly the distance the thing stops being able to act on you. A Flock camera reads plates at ~30-50 m, so it is RED on top of it, ORANGE at 100 m, and GREEN by 500 m — still drawn on the map, just no longer an alarm. Waze keeps a wider band deliberately: a police car covers 700 m in under a minute, a bollarded camera never moves. Aircraft are unaffected, since that scanner uses its own ranges rather than the slider. The main-screen slider is relabelled "show within" to say what it actually is — a view control, not a sensitivity control. Verified on device: sweeping 200 m -> 4900 m leaves the tier at GREEN while the reported count goes 0 -> 133, and standing 29 m from a real camera reads 89 RED, then 50 at 252 m and 41 at 373 m. Scores match the falloff formula exactly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RsfSpnwuxCkcXKkD9XH8SR |
||
|
|
da97924ad2 |
v0.5.8 — AIRCRAFT source, wider Overpass query, distance-graded scoring
Adds a sixth source: police and surveillance aircraft overhead, via the free
community ADS-B networks (opendata.adsb.fi, api.adsb.lol fallback, no API
key). Contacts are matched by ICAO 24-bit address against a bundled registry
of 1,971 US law-enforcement airframes generated by scripts/gen-le-aircraft.py
from ADSBexchange's basic-ac-db and committed as res/raw/le_aircraft.csv.
Community feeds are used deliberately: FlightAware and Flightradar24 filter
law-enforcement flights at government request, which is the traffic this
source exists to see. Two parse traps handled — the envelope is {"ac":[..]}
on radius queries but {"aircraft":[..]} on wider ones, and alt_baro is the
string "ground" when parked.
Registry coverage is imperfect, so the scanner also detects loiter/orbit
behaviour (3+ samples over 4+ min within 5 km of their centroid, below
12,000 ft and under 200 kt). Surveillance aircraft circle; airliners and
medevac flights going somewhere do not. Behaviour-only hits are capped at 69
and must be within 8 km, so ordinary traffic never alerts.
Rejected with measurements: plane-alert-db matched 0 of 394 live aircraft
over a 250 nm sweep of DC while 15 helicopters were aloft (only 255 of its
entries are US-registered); registry.faa.gov is Akamai-403 and N-number
keyed; OpenSky's CSV is 94 MB for the same data; EFF's Atlas of Surveillance
has no aircraft identities at all, only a 2022 FAA drone lookup.
Overpass query widened from ALPR-only to man_made=surveillance plus
highway=speed_camera, classified into ALPR / speed camera / generic camera
with separate falloff curves so a shop's CCTV cannot alarm like a Flock
install. Cache key bumped to deflock2_ so v1 ALPR-only entries are not served
for another 24 h.
DeFlock, Waze and aircraft are now scored by continuous distance falloff
rather than flat values. The anchors are absolute metres and deliberately
independent of the detection-radius setting: moving a slider must not move
the threat level.
New SOURCES.md documents every endpoint, identifier and scoring table,
including the sources that were tried and rejected and the measurements that
killed them.
Verified against live traffic: detected San Diego PD's AS50 at 1580 m /
1000 ft scoring 83 (ORANGE) and a San Diego County Sheriff B407 at 11742 m
scoring 44, with the score tracking the helicopter from 81 to 83 as it
closed. Both match the falloff formula exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RsfSpnwuxCkcXKkD9XH8SR
|