Project skeleton: Gradle 9.4.1 wrapper, AGP 9.2.1, Compose, manifest with reminder permission set

Milestone 1 of the build brief. Version catalog pins verified against
Maven Central / Google Maven on 2026-06-10; Kotlin held at 2.3.10 to
match AGP 9.2's bundled KGP (built-in Kotlin) because KSP has no
Kotlin 2.4 release yet. compileSdk 37 (forced by core-ktx 1.19),
targetSdk 35 per brief. allowBackup=false + full dataExtractionRules
opt-out; own encrypted backup comes in milestone 5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-06-10 13:31:39 +02:00
commit 7256c49112
21 changed files with 845 additions and 0 deletions

66
CLAUDE.md Normal file
View file

@ -0,0 +1,66 @@
# «Med det samme» — Claude Code project memory
Local-first Android medication reminder. My personal MyTherapy replacement: no ads,
no account, no analytics, no cloud service of yours. Single user, single device.
Reminders are the entire point — reliability beats polish wherever they trade off.
The name says the brief: nag me to take the dose *now*.
- Package / applicationId: `no.naiv.meddetsamme`
- Display name: `Med det samme` (in `strings.xml`, referenced from the manifest)
- minSdk 26, targetSdk 35, JVM 17, Kotlin + Compose (Material3)
- Stack: Room (+KSP), WorkManager, OkHttp, security-crypto, kotlinx-serialization.
Gradle Kotlin DSL + version catalog. No AWS SDK, no DI framework.
<!-- Personal prefs (24h, concise, explain-why, Linux-assumed) may already be in my
global ~/.claude/CLAUDE.md. If so, trim the Working agreement here to avoid drift. -->
## Working agreement
- Senior dev, Linux host. Be concise; explain *why* for non-obvious choices in a line
or two (XAI, not essays). 24h clocks everywhere.
- Never claim it builds without running the build. Verify; don't assert.
- Verify current stable library versions yourself before bumping — don't trust memory.
- Smallest change that works. No speculative abstraction.
- Ask before anything irreversible (schema migrations, data deletion).
- This is a medication app: wrong schedule/dose math is a real harm. Keep schedule
logic pure and unit-tested before anything depends on it.
## Decisions — don't relitigate (flag and wait if you think one's wrong)
1. Native, not PWA — PWA notification reliability is unacceptable for meds.
2. Exact alarms (`USE_EXACT_ALARM`), always gated on `canScheduleExactAlarms()` with an
inexact fallback; `setExactAndAllowWhileIdle` so Doze doesn't eat doses.
3. Re-arm every alarm on `BOOT_COMPLETED` + `MY_PACKAGE_REPLACED` (state is wiped then).
4. Surface a one-time battery-optimisation exemption prompt — biggest cause of dropped
reminders on aggressive OEMs.
5. No Google Auto Backup (`allowBackup="false"`, excluded from cloud-backup + transfer).
6. Own backup: versioned JSON → encrypted → S3-compatible PUT to self-hosted **Garage**,
path-style, hand-rolled SigV4. One serializer for export, import, and auto-backup.
7. Crypto target is **age** (passphrase/scrypt) so backups are `age -d`-decryptable and
never lock me into this app. JCE AES-GCM is the baseline behind an interface; verify
age against the age test vectors before trusting it.
8. **FEST, not Felleskatalogen**, and **not** as a live API: its open Rekvirent extract
is a SOAP/WCF M30 XML dump. The phone reads a slim pre-flattened JSON synced from my
server (that job lives outside this repo) and does autocomplete offline.
9. Refill is **derived** from inventory + consumption. Prescription renewal
(`rxExpiryEpochDay`, `refillsRemaining`) is tracked **separately** from stock.
## Load-bearing — change with care
- The reminder subsystem is the reliability core. After any change, re-verify: alarms
re-arm on boot/update, escalation cancels on Taken, the next occurrence is always
armed, Taken decrements inventory.
- Escalation contract: due dose → PENDING log + notify, re-nag every 10 min (cap ~6 /
~1 h) until Taken or Snooze; Snooze pushes the next nag 15 min and stays PENDING.
- The S3 SigV4 signer: if a PUT fails it's almost always clock skew or a non-path-style
endpoint, not the maths. Don't "fix" the signer first.
- The schedule engine is pure — add tests here before touching the math.
## Out of scope — don't add without asking
Caregiver/"Team" alerts, multi-profile, Health Connect, streaks/gamification,
injection-site tracking, symptom/mood diary. (Modelling "trackable" generically is fine
if cheap; build no diary UI.)
## Commands
- Build debug: `./gradlew assembleDebug`
- Unit tests: `./gradlew test`
- Lint: `./gradlew lint`
<!-- Once a README exists, add: See @README.md for architecture detail. -->