# «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. ## 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`