summaryrefslogtreecommitdiff
path: root/Garmin OTP Prompt.md
blob: 3121bb6119ac60a9144a9b83a268d765cce05bef (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Prompt: Garmin Connect IQ OTP Authenticator and Code Wallet

Copy everything below the line into your coding model (Claude Code works best, since it can run Docker and files).

---

## ROLE

You are a senior embedded and Garmin Connect IQ engineer (Monkey C), a security-minded developer, and a technical writer. You work carefully, verify claims against the official Garmin documentation, and never invent APIs. If an API, permission or device capability is not documented, you say so explicitly and propose an alternative instead of guessing.

## GOAL

Build a **Garmin Connect IQ watch app** that works as an **OTP authenticator** (TOTP and HOTP) and also as a **wallet for other barcode and QR codes** (loyalty cards, tickets, etc.).

- All data is stored **on the watch**. No cloud, no backend, no analytics, no network calls.
- Configuration and import are done through **Garmin Connect IQ app settings** (the settings screen in the Garmin Connect / Connect IQ phone app).
- The watch UI must be **very simple and very fast**.

## HARD REQUIREMENTS

1. **TOTP and HOTP** per RFC 6238 and RFC 4226. Support SHA1, SHA256 and SHA512, 6 to 8 digits, and custom periods (default 30 s). Optionally support Steam Guard style codes as a clearly separated, optional feature.
2. **Import from Aegis Authenticator** (Aegis vault JSON export):
   - Support the **plain-text** export.
   - Support the **encrypted** export if feasible (scrypt + AES-256-GCM, slots). If it is not feasible on the watch, handle decryption **outside the watch** (see "Import pipeline") and document why.
   - Also accept `otpauth://` URIs (single and bulk, one per line) and `otpauth-migration://` (Google Authenticator export) if feasible.
3. **Generic barcode and QR code storage and display.** Support at least: QR, Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, ITF (Interleaved 2 of 5), Codabar, Data Matrix, PDF417, Aztec. The watch **stores the payload string and symbology** and **renders the code on screen**. State clearly which symbologies you implemented, which are deferred, and how you verified each one is scannable.
4. **Per-entry lock.** Each entry (OTP, barcode, QR) has its own setting "Require PIN to display". Locked entries show a lock icon and no code until unlocked.
5. **Encryption at rest.** Secrets are stored encrypted and are only decrypted in memory after the user unlocks. Locked entries are never decrypted before unlock, and decrypted data is wiped from memory as soon as possible (on screen exit and on timeout).
6. **Simple UX on the watch.** List of entries, tap or select to open, big readable code, countdown ring for TOTP, tap to advance an HOTP counter. No deep menus. Works with touch and with button-only devices.
7. **Fast.** Target: app start to first code visible in under 1 second on a mid-range device for the unlocked entries, and a TOTP refresh with no visible lag. Measure it, report the numbers and document how you measured them.
8. **No bugs.** Every module is covered by tests. Nothing is declared done until tests pass in Docker.
9. **Everything in Docker and fully sandboxed**, see "Docker and sandbox rules".
10. **Comment the code thoroughly** (what, why, edge cases, security notes) and **write documentation**.
11. **Manual entry in the Garmin Connect IQ settings UI**, in addition to the Aegis import. The user must be able to create, edit, reorder and delete entries by hand in the Connect IQ app settings, without any import file. The form must cover everything needed to generate each kind of code:
    - **OTP entries:** type (TOTP, HOTP, optionally Steam), issuer, account label, secret (Base32, validated as it is entered), algorithm (SHA1/SHA256/SHA512), digits (6 to 8), period (TOTP) or initial counter (HOTP), group, and the per-entry "Require PIN to display" switch.
    - **Barcode and QR entries:** name, symbology (QR, Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, ITF, Codabar, Data Matrix, PDF417, Aztec), the payload text/digits, symbology-specific options (for example QR error-correction level, or whether to show human-readable text under a linear barcode), group, and the per-entry "Require PIN to display" switch.
    - **Validation with clear error messages:** check the payload against the chosen symbology (allowed characters, length, EAN/UPC check digits with automatic calculation or correction offered, QR capacity for the chosen error-correction level, Base32 validity for OTP secrets) and report problems in a status message instead of failing silently.
    - If the settings UI cannot create a dynamic list of entries (a typical Connect IQ limitation), design the workable alternative (for example a fixed number of entry slots, or a compact text format for one entry per line with a validated parser), explain the trade-offs, and ask me which to choose before building.
    - Manually entered and imported entries must be stored and behave identically on the watch.
    - **Test this too:** unit tests for the entry form parsing and validation, covering valid and invalid input for every symbology and OTP type, and an end-to-end test that a manually entered entry shows the correct code or barcode on the watch (in the simulator).

## CRITICAL PLATFORM CONSTRAINTS TO INVESTIGATE FIRST

Before writing any plan or code, research and verify each of these against the current official Connect IQ documentation and SDK. Write the findings in a section called "Feasibility findings" with a clear verdict for each (supported / partially / not possible) and a workaround. Do not skip this section. I expect some of my requirements may not be fully possible as phrased, and I want you to tell me honestly.

1. **Garmin device PIN / lock.** I want entries to be unlockable with the Garmin device PIN. Determine whether Connect IQ exposes any API to read, verify, or hook into the device lock or PIN. If it does not (my expectation is that it does not), propose the best alternatives and let me choose, for example:
   - an app-level PIN entered on the watch (digits via touch or buttons) that derives the encryption key;
   - an app-level PIN plus lock on app exit and a timeout;
   - anything else you find that is actually supported.
   Explain the security trade-offs of each, including what happens after too many wrong attempts (lockout, optional wipe, off by default).
2. **Key derivation and crypto.** Check what `Toybox.Cryptography` provides on which API levels and devices (hashes, HMAC, ciphers, key generation) and what is missing. If SHA1, SHA256, SHA512, HMAC, PBKDF2 or AES are not all available, decide between a pure Monkey C implementation (with performance cost measured) and reduced device support. Never invent your own crypto algorithms: use standard, well-known constructions and test them against official test vectors (RFC 6238, RFC 4226, NIST).
3. **Settings capabilities.** Check what Connect IQ app settings can hold (types, length limits, total size, number of items, whether file upload exists). My expectation is that **file upload is not supported**, so design the import pipeline around that (see below).
4. **Storage limits.** Check `Application.Storage` and `Application.Properties` size limits, per-key limits, and behavior across app updates. Design the data model to fit and to be migratable between versions.
5. **Memory limits per device.** Check the app memory budget on the devices you target and design for the weakest one. List the target devices and justify the choice (e.g. recent Forerunner, Fenix, Venu, Vivoactive families), and their API levels.
6. **Rendering barcodes.** The watch has no camera, so codes are never scanned on the watch. They are generated and drawn. Check drawing performance, screen resolution and contrast limits. Large 2D codes (PDF417, Data Matrix, QR with long payloads) may not fit on small round screens, so describe the limits and what the UI does in that case (for example, a warning at import time).
7. **App type.** Decide between a Watch App and a Widget (and glance, if supported) for the fastest access. Justify it.
8. **Privacy of settings.** Check how settings values are stored by the Garmin phone app and Garmin servers. This matters because secrets entered in settings pass through the phone app. Document this honestly in a "Threat model" section, and describe how to minimize exposure (for example, import encrypted data only, and have the watch clear the settings field after import).

## IMPORT PIPELINE (design, then implement)

Because settings have no file upload, propose and implement the best option. Present at least these candidates with pros and cons, then implement the one I approve (ask me with a short question before building):

- **A. Paste into settings.** User pastes text (`otpauth://` lines or a compact JSON) into a settings text field, and the watch parses it on next sync and then **clears the field**. Includes chunking if there is a length limit.
- **B. Offline converter tool (runs locally in Docker, no network).** A small CLI included in the repo, which takes an Aegis export (plain or encrypted, and the vault password for encrypted) and outputs a **compact, already-encrypted import blob** (and optionally a QR or text chunks) that is easy to paste into settings. This keeps plaintext secrets off Garmin's servers.
- **C. Companion approach** if something else is genuinely supported.

The converter must be well tested with sample Aegis files (plain and encrypted, with several entry types: TOTP, HOTP, Steam, different algorithms/digits/periods, groups, icons, notes). Use **fake test data only**, never real secrets.

Also define clearly: duplicate handling, validation errors shown to the user, partial import behavior, and how to remove or edit entries after import.

## SETTINGS (Connect IQ app settings)

Define the settings schema and the XML for it. At minimum:

- Import field(s) and import status/result message.
- Manual entry form(s) for OTP and barcode/QR entries (see hard requirement 11), with a validation status message per entry.
- Global options: auto-lock timeout, PIN mode, clock-skew/time-offset handling, theme/size of the code font, grouping on or off.
- **Per-entry options** (name, issuer, label, type, group, display order, "require PIN", digits/period/algorithm where relevant, counter for HOTP, symbology for codes).
- Explain how per-entry settings are represented if the settings UI cannot create dynamic lists (a typical limitation). Design a workable approach and document it.

## DATA MODEL AND SECURITY DESIGN

Write a design for:

- Entry types and fields (OTP and codes), versioned schema, migration strategy.
- Encryption design: key derivation from PIN or other chosen secret (with a salt, with as many iterations as the device can afford, measured), authenticated encryption, nonce handling, key and plaintext zeroization in memory, and what metadata is stored in plain text (for the list view; e.g. names) and why. Offer an option to also encrypt names.
- Locked versus unlocked entries and how the list screen looks for each.
- Brute-force protection on the watch.
- Time handling for TOTP (UTC, clock source, drift) and what happens when the time is wrong.
- Threat model: what this protects against and what it does not (lost watch, phone compromise, Garmin cloud, malicious app on the phone, etc.).

## ARCHITECTURE

Propose a clear module layout in Monkey C, for example: `crypto/` (hash, HMAC, KDF, cipher wrappers), `otp/` (HOTP, TOTP, Steam), `codes/` (barcode and QR encoders and renderers), `storage/` (encrypted store, migration), `import/` (parsers for otpauth, Aegis, migration), `ui/` (views, delegates, lock screen, list, detail), `settings/` and `util/`. Keep UI code thin and logic testable. Avoid allocations in hot paths. Precompute and cache rendered codes where memory allows.

## DOCKER AND SANDBOX RULES

- **Everything** runs in Docker: SDK download and install, build, unit tests, simulator tests, linting, packaging the `.iq` file, the converter tool, and documentation build. Nothing is installed on my host besides Docker itself.
- Provide a `Dockerfile` (and `docker-compose.yml` if useful) and a `Makefile` with simple targets, for example `make build`, `make test`, `make sim`, `make package`, `make lint`, `make docs`, `make clean`, **`make nuke`** (removes containers, images, volumes and generated files created by this project).
- Use **named volumes or a project-local `.cache/` folder** for the Connect IQ SDK, developer key and caches, so deleting the project folder plus running `make nuke` removes everything.
- The Connect IQ SDK requires accepting Garmin's license and downloading through the SDK Manager. Research how to do this **headlessly in Docker** and what needs my Garmin login or manual acceptance. If anything needs a manual step from me, **stop and ask me clearly with exact instructions**.
- The Connect IQ simulator needs a display. Use a virtual display (e.g. Xvfb) inside the container for headless simulator test runs, and describe how I can optionally see the simulator on my host (e.g. VNC or X forwarding) without installing anything else.
- **Developer signing key:** generate it inside the sandbox, never commit it, put it in `.gitignore`, and document backup and the consequences of losing it.
- Run as a **non-root user inside the container**, no privileged mode, no host networking, mount only the project directory. Pin base image and tool versions where possible.
- If any step needs `sudo` on my host (for example installing Docker or adding me to the docker group), **ask me first**, tell me the exact command and why, and wait for my confirmation. Never run sudo yourself without asking.
- Document how to completely remove everything (a "Uninstall / cleanup" section).

## TESTING

Write the test strategy first, then tests alongside code (not after).

- **Unit tests** with the Connect IQ test framework (`Toybox.Test`) run through the SDK in Docker. Cover: HOTP/TOTP against all RFC test vectors (SHA1, SHA256, SHA512), digit counts, periods, boundary times (period rollover, leap-year dates, year 2038 and later), Base32 decoding (padding, lowercase, whitespace, invalid chars), `otpauth://` parsing (URL-encoded labels, missing issuer, odd parameters), Aegis parsing (plain and encrypted), KDF and cipher against known vectors, encrypted store round-trip, tamper detection, wrong PIN, lockout logic, migration between schema versions.
- **Barcode tests:** for each symbology, compare the encoder output against known-good reference matrices or bar patterns, and (where possible in Docker) decode the rendered output with an open-source decoder such as ZXing or zbar to prove it scans.
- **Converter tool tests:** run with fixtures, including malformed and hostile input.
- **Property or fuzz tests** for parsers where practical (no crashes, no hangs, clear errors).
- **Simulator and UI tests:** screenshot-based checks on at least one round and one rectangular device, plus a button-only device.
- **Performance tests:** measure start-up, TOTP generation, unlock (KDF) time and render time, on simulator and document the limits of simulator timing versus a real watch. Define budgets and fail the build if they are exceeded where measurable.
- **Memory tests:** check peak memory on the weakest target device in the simulator.
- **Static checks:** Monkey C compiler with the strictest type-check level, plus any available linters. Treat warnings as errors where possible.
- Provide a CI-style `make ci` target that runs everything.
- Include a **manual test checklist** for the real watch (sideload steps, things the simulator cannot verify such as real clock, real crypto speed, button feel).

## CODE QUALITY RULES

- Heavy, useful **comments** on every module, class and non-trivial function (purpose, inputs, outputs, errors, security notes), plus inline comments for tricky logic.
- Handle every error path with a clear user-facing message on the watch. No silent failures, no crashes on bad data.
- No secrets in logs. No secrets in source. No debug code left in release builds.
- Small functions, clear names, constants instead of magic numbers.
- Validate all external input (settings values, imported data).
- Keep a `CHANGELOG.md` and use semantic versioning.

## DOCUMENTATION DELIVERABLES

1. **`README.md` (write this FIRST, before any code)** containing:
   - Project overview and scope, what is and is not supported.
   - Feasibility findings (see above) with honest verdicts and the decisions I need to make.
   - Architecture and module diagram (Mermaid is fine).
   - Data model, security and threat model.
   - Import pipeline design.
   - UX design: screens, flows and wireframes in text or Mermaid.
   - Docker and sandbox setup, all `make` targets, cleanup.
   - Detailed **step-by-step build plan** broken into milestones, each with deliverables, tests and a definition of done.
   - Test plan (as above), performance budgets, risk list with mitigations.
   - Target devices and API levels.
2. `docs/USER_GUIDE.md`: install on the watch, import from Aegis, configure per-entry PIN lock, daily use, backup and migration to a new watch, troubleshooting.
3. `docs/DEVELOPER_GUIDE.md`: repo layout, how to build/test/debug in Docker, how to add a new barcode symbology or device, coding conventions.
4. `docs/SECURITY.md`: threat model, crypto choices and parameters, known limitations, how to report issues.
5. `docs/TESTING.md` and `docs/PERFORMANCE.md` with results.
6. In-code documentation as described above.

## WORKING PROCESS

1. **Phase 0, research:** read the official docs, produce "Feasibility findings", and ask me any blocking questions (PIN approach, import approach, target devices, sudo/SDK login steps) in **one short batch**.
2. **Phase 1, plan:** write the complete `README.md` and wait for my approval.
3. **Phase 2, scaffolding:** Docker, Makefile, empty project that builds and runs one trivial test in the sandbox.
4. **Phase 3 onward:** implement milestone by milestone: crypto and OTP core, then storage, then UI, then import, then barcodes, then settings, then polish and performance. After each milestone: run the full test suite in Docker, update docs, and give me a short status report with test results.
5. **Final:** run `make ci`, produce the packaged `.iq`/`.prg`, finalize docs, list known limitations honestly.

## HONESTY AND SAFETY RULES

- Do not claim something works unless you ran it. Show test output.
- If a requirement is impossible or unsafe as stated, say so and offer the closest safe alternative. Do not silently drop or fake a feature.
- Do not use any real OTP secrets or real personal data. Use fabricated fixtures only.
- Ask before any action that touches my host system outside the project folder.

Start with Phase 0 now.