Initialize Android NTP app framework
android-apk / debug-apk (push) Has been cancelled

This commit is contained in:
2026-07-09 15:44:22 -08:00
commit bfb027fcd2
33 changed files with 1196 additions and 0 deletions
@@ -0,0 +1,17 @@
# ADR 0001: Native Android local-first app
## Decision
Build v1 as a native Kotlin Android app using Jetpack Compose, Room, and direct UDP NTP probes.
## Rationale
- The app needs low-friction device-side network diagnostics.
- No backend is required for saved servers, profiles, local history, comparison, or export.
- Local-only storage avoids telemetry and customer data exposure.
## Consequences
- APKs can be built locally or in Gitea Actions.
- Gitea runners must have Android build tooling or install it during the workflow.
- Release builds require signing keys managed through secrets, not committed files.
@@ -0,0 +1,37 @@
# ADR 0002: Android system time update capability
## Question
Can NTP Check update the Android device system time?
## Finding
For a normal Play/user-installed Android app: **no**. Android protects system clock changes behind privileged APIs/permissions. An app can measure offset and show guidance, but it cannot directly set wall-clock time unless it is installed with elevated trust.
## Practical options
1. **Normal app behavior for v1**
- Probe NTP servers.
- Show estimated device offset.
- Warn when local clock appears wrong.
- Provide a button to open Android Date & Time settings.
- No special permissions beyond `INTERNET`.
2. **Device-owner / enterprise-managed device**
- Some Android management APIs allow a device owner/profile owner to control certain time/timezone policies depending on Android version and ownership mode.
- This requires provisioning the app as a device policy controller, not a typical install.
3. **Privileged/system app or custom ROM**
- A system-signed or `/system/priv-app` application can use privileged permissions such as `android.permission.SET_TIME`.
- This is not available to ordinary APK installs.
4. **Rooted device helper**
- A rooted-device mode could call shell commands such as `date`/`toybox date`, but this is out of scope for v1 and has safety/security risks.
## Decision
V1 will not set Android system time. It will remain a diagnostic/comparison tool and may include an "Open Date & Time settings" action. Any future clock-setting mode must be explicitly separate and gated as enterprise/device-owner, privileged-system, or rooted-device functionality.
## Product implication
Market the app as an NTP testing and comparison dashboard, not as a general Android time synchronization daemon.
+17
View File
@@ -0,0 +1,17 @@
# Start Here
## Project mission
Build a local-first Android NTP app for comparing saved time servers, identifying the best candidate, and exporting troubleshooting evidence.
## Current state
Repository framework, Android skeleton, Gitea APK workflow, and initial phase plan are initialized. Product work should proceed through the phase gates in `project-docs/implementation/phase-plan.md`.
## Read next
1. `AGENTS.md`
2. `project-docs/handoff/01-product-handoff.md`
3. `project-docs/implementation/phase-plan.md`
4. `project-docs/decisions/0001-native-android-local-first.md`
5. `project-docs/decisions/0002-android-system-time-capability.md`
@@ -0,0 +1,27 @@
# Product Handoff
## Core v1 features
- Saved NTP servers: name, hostname/IP, port, notes, enabled state.
- Profiles: Home, Customer A, Customer B, etc.
- One-tap test all.
- Continuous test mode intervals: 1s, 5s, 10s, 30s.
- Per-server status: reachable, timeout, DNS failure, packet error.
- Per-server metrics: RTT, offset estimate, stratum, reference ID, root delay, root dispersion, leap status, precision.
- Sort by offset, latency, stratum, reachability, and health score.
- Highlight disagreement between servers and choose a best candidate.
- Export/share test results as text and CSV.
- Keep short local history per server.
- Dark/light mode.
- Local-only privacy posture with no telemetry.
## Comparison logic
Poll each enabled server and compare reachability, stratum, root distance, offset stability, and median disagreement. Warnings should include unreachable server, high RTT, high root dispersion, unsynchronized stratum, leap warning, offset outlier, and reference ID changes.
## Later features
- SSH mode for Linux/chrony servers: `chronyc tracking`, `chronyc sources -v`, `timedatectl timesync-status`.
- Offset/RTT graphs.
- Alerts for drops or drift.
- CSV/YAML import.
+86
View File
@@ -0,0 +1,86 @@
# Phase Plan
## NTP-P0 — Repository framework and delivery workflow
Goal: initialize the project like the phase-gated Second Brain workflow.
Deliverables:
- Android Kotlin/Compose skeleton.
- Room storage model draft.
- Raw UDP NTP client draft.
- Gitea Actions debug APK workflow.
- Project docs, hard rules, and validation target.
Gate:
- `make validate-structure` passes.
- Repo pushes to Gitea.
## NTP-P1 — NTP probe correctness
Goal: make the raw UDP NTP client reliable and testable.
Deliverables:
- Unit tests for packet timestamp parsing/encoding and warning mapping.
- Probe result model with all required NTP fields.
- Error handling for DNS failure, timeout, malformed packets, and unreachable hosts.
Gate:
- Unit tests pass.
- Manual test against known public NTP servers succeeds.
## NTP-P2 — Saved servers and dashboard MVP
Goal: provide a useful saved server list and one-tap comparison dashboard.
Deliverables:
- Add/edit/delete servers.
- Default server seed only on first run.
- Latest result per server visible on dashboard.
- Sort by latency, offset, stratum, reachability, health score.
- Best candidate calculation.
Gate:
- Debug APK builds.
- Manual emulator/device smoke test passes.
## NTP-P3 — Continuous testing and disagreement detection
Goal: support polling intervals and peer-group comparison.
Deliverables:
- Continuous mode at 1s, 5s, 10s, 30s.
- Offset median and threshold outlier warnings.
- Reference ID change warning.
- Short history retention policy.
Gate:
- Continuous mode stops cleanly when disabled/backgrounded.
- Battery/network behavior reviewed.
## NTP-P4 — Profiles and export
Goal: make the app practical for home/customer troubleshooting.
Deliverables:
- Profile CRUD and server assignment.
- Export/share current results and history as text/CSV.
- Import server list design for later CSV/YAML.
Gate:
- Export contains no hidden telemetry or private app metadata.
- Profile switching works on device.
## NTP-P5 — UX polish and release prep
Goal: prepare signed release builds.
Deliverables:
- Dark/light mode polish.
- Empty/error/loading states.
- Signed release build workflow using Gitea secrets.
- Release checklist.
- Open Android Date & Time settings action if local clock offset warning is present.
Gate:
- Lint/tests/build pass.
- Permission and privacy review passes.
+28
View File
@@ -0,0 +1,28 @@
# Gitea APK Build Runbook
## Can Gitea build the APK automatically?
Yes. Gitea Actions can build Android APKs automatically on push or manual dispatch if an Actions runner is available with Docker or enough tooling to install Android commandline tools.
## Debug APKs
Debug APKs are straightforward and do not need signing secrets. The workflow in `.gitea/workflows/android-apk.yml` builds `app/build/outputs/apk/debug/app-debug.apk` and uploads it as an artifact.
## Release APKs
Release APKs should be added later after creating secrets:
- `ANDROID_KEYSTORE_BASE64`
- `ANDROID_KEYSTORE_PASSWORD`
- `ANDROID_KEY_ALIAS`
- `ANDROID_KEY_PASSWORD`
Never commit keystores or passwords.
## Local fallback
If the runner cannot install Android SDK components or dependency downloads are blocked, build locally with:
```bash
make build-debug
```
@@ -0,0 +1,5 @@
# Phase 0 Open Issues
- Confirm Gitea Actions runner has Android SDK support or can install it with `android-actions/setup-android`.
- Local machine needs a full supported JDK with `javac` (JDK 17 or 21) to build locally; current default Java 26 is unsupported by Gradle 8.10.2, and the Java 21 install appears runtime-only.
- Add release signing workflow after a keystore is created and stored as Gitea secrets.
+12
View File
@@ -0,0 +1,12 @@
# Phase 0 Summary
Initialized the NTP Android project framework with:
- Kotlin/Jetpack Compose Android project skeleton.
- Room data model for profiles, servers, and probe results.
- Raw UDP NTP client draft.
- Initial dashboard scaffold with seeded NTP servers and one-tap test action.
- Phase-gated documentation modeled after Second Brain.
- Gitea Actions workflow for debug APK artifacts.
Status: framework complete; build validation still depends on local/runner Android Gradle tooling.
@@ -0,0 +1,9 @@
# Phase 0 Test Results
## 2026-07-09
- `make validate-structure`: passed.
- `gradle wrapper --gradle-version 8.10.2 --distribution-type bin`: passed after adding Kotlin Compose compiler plugin.
- `./gradlew --no-daemon :app:assembleDebug`: blocked locally because the default Java 26 runtime is unsupported by Gradle 8.10.2.
- `JAVA_HOME=/usr/lib/jvm/java-21-openjdk ./gradlew --no-daemon :app:assembleDebug`: blocked locally because the installed Java 21 environment does not provide `javac` compiler capabilities.
- Gitea workflow added for automatic debug APK builds with JDK 17 and Android SDK setup.