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>
66 lines
3.9 KiB
Markdown
66 lines
3.9 KiB
Markdown
# «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. -->
|