mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:27:02 +01:00
The enforcer failed in both directions: nothing blocked at home, and everything blocked at the office. The comparison was never inverted -- `metres <= threshold` was always right. Three separate causes: Only ACCESS_COARSE_LOCATION was declared. Android 12+ fuzzes coarse to a ~1-2 km grid against a 150 m fence, so a fix taken at home routinely landed outside it, read as AWAY, and restored every app the geofence exists to hide. FINE is now declared and self-granted by the device owner, along with coarse and background, re-asserted every pass so a reinstall cannot silently drop it. There were three states but two behaviours. LOCATION_UNKNOWN applies the identical sweep to AT_HOME -- correct fail-closed design, indistinguishable from outside. And nothing ever requested a fix: the pass read whatever another app happened to cache, so at the office with no navigation running the cache was empty. Passes now acquire a fix inside a location-typed foreground service, bounded at 20 s, and treat anything older than 30 min as no fix. That window is deliberately longer than the 15-minute cadence; a shorter one marks the newest cache stale on every pass of an idle phone and blocks everything. None of it was diagnosable. `adb logcat -d -s FocusOwner:V` came back empty while dumpsys showed 82 alarms had fired, and `run-as` is refused on the release build device owner requires. So the pass now writes a ring-buffered JSONL record read back in-app: reason, distance vs the fence, fix age/provider/accuracy, curfew state, and every hidden app with the rule that hid it. Coordinates are never recorded -- a distance is enough to debug a geofence, and this is a home address. Also fixed along the way: - Hysteresis keyed off `isEnforcing`, which is true under AWAY too because YouTube stays hidden, so the threshold was permanently radius+hysteresis. It now keys off whether the previous pass was inside the fence. - The scheduler's curfew-boundary alarms were documented but never scheduled; both callers invoked `scheduleNext()` bare, so 05:00 could land 15 min late. - Installing over the app cancelled its pending alarms, so `adb install -r` silently stopped enforcement until someone opened the app. MY_PACKAGE_REPLACED now re-arms it, verified on device without launching the app. - A wrong-typed log record threw instead of being skipped, and the exception escaped far enough to leave the page stuck busy -- which disables the release-device-owner button, the one control that must work when everything else has gone wrong. - `lib/enforcement.dart` was a second decision layer with no always-blocked concept, cited by KDoc as pinned by a `PolicyParityTest` that never existed. It would have made the new screen report YouTube visible while it is hidden. Deleted; the UI renders the Kotlin record rather than re-deciding. - Anchoring home accepted a stale or unknown-precision fix. A wrong home offsets the fence everywhere and forever, which is what produced a 766 m reading while standing at home. Policy: Play Store is allowed by day (not during curfew) so infakt can be installed and updated; the sweep is default-deny for third-party packages, so anything installed from Play is hidden on the next at-home pass. Tachiyomi's per-source extension apks are covered by a new prefix allowlist rather than an exact list that goes stale whenever an extension is installed. `export.py` stopped subtracting the allowlist from `blockable_system_packages`. Sweepable is not hideable: that list decides which system packages are eligible for a decision, and `isAllowed` is what protects them. Removing an allowed system package from the sweep freezes it in its last state -- it would have stranded Play hidden permanently the moment it was allowlisted. Verified on the Pixel 6a: FINE granted POLICY_FIXED, `applied AT_HOME` with a 0 m distance from a +/-11 m GPS fix, YouTube/Chrome/Firefox absent from `pm list packages -e`, Play Store, infakt, RunnerUp and all five Tachiyomi packages present. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjxL9kdAzZmGqQA5tMNrZ8
43 lines
4.1 KiB
Markdown
43 lines
4.1 KiB
Markdown
# testsAndMisc
|
|
|
|
A collection of personal projects, scripts, and experiments — from a GPS-based phone focus tool to Linux/Arch automation, with CI, linting, and pre-commit hooks across the board.
|
|
|
|
## Highlights
|
|
|
|
### [Phone Focus Mode](phone_focus_mode/)
|
|
|
|
Location-based app restriction for rooted Android. Automatically disables non-whitelisted apps within 500 m of home using ADB + Magisk. Features Haversine distance calculation, hysteresis to prevent toggling, fail-safe unlock, and state persistence. **Bash, Android ADB.**
|
|
|
|
### [Linux Configuration](linux_configuration/)
|
|
|
|
Automated Arch Linux setup: fresh-install scripts, i3 window manager config, LaTeX environment, and system tests. Includes documentation and test result logging.
|
|
|
|
### [Scripts](scripts/)
|
|
|
|
Utility scripts for development workflows — build file validation, secret detection, and custom makepkg helpers.
|
|
|
|
## Repository Layout
|
|
|
|
| Path | Description |
|
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `python_pkg/` | Python packages (each maintained subpackage lives here) |
|
|
| `billsplit/` | Receipt bill-splitting Flutter app — people, groups, per-item assignment, e-paragon import and xlsx export (Dart, 100 % line coverage gate) |
|
|
| `linux_configuration/` | Arch Linux setup, i3 config, system maintenance scripts |
|
|
| `focus_owner/` | Device Owner app enforcing focus mode on the unrooted Pixel 6a — geofence + night curfew, hides apps the phone cannot un-hide (Dart/Kotlin) |
|
|
| `phone_focus_mode/` | GPS-based Android focus enforcer (rooted-era scripts; `config.sh` is still the policy source of truth for `focus_owner/`) |
|
|
| `reverse_survivors/` | Reverse Survivors — React/Vite game where you play the horde against an AI survivor (TypeScript, 100 % coverage gate) |
|
|
| `scripts/` | Workspace-level helper scripts and pre-commit hooks |
|
|
| `docs/` | Reference docs and historical reports |
|
|
| `third_party/` | Vendored upstream skills/agents |
|
|
| `meta/` | Repo-wide tooling: `pyproject.toml`, `requirements.txt`, `.pre-commit-config.yaml`, `run.sh`, `lint_python.sh`, `.fvmrc`. Symlinked into the repo root so tools that auto-discover from root keep working. |
|
|
|
|
Archived / unmaintained projects live in the sibling repository
|
|
[`testsAndMisc-archive`](https://github.com/kuhyx/testsAndMisc-archive).
|
|
|
|
## Tooling
|
|
|
|
- **Python linting**: [Ruff](https://docs.astral.sh/ruff/) with all rules enabled (see `meta/pyproject.toml`)
|
|
- **Dependencies**: `pip install -r meta/requirements.txt` (combined runtime + dev)
|
|
- **CI**: GitHub Actions — lint, build, and test on push
|
|
- **Testing**: pytest (Python), custom shell-based test harness for scripts
|