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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
<!--
Author: cirakg & claude ai
Summary: Your step-by-step guide to everything left before 1.0.0: the settings spike, the on-watch tests with a debug build and the Store beta, and what to send back.
-->
# Your steps to 1.0.0
Everything that can be checked in Docker is done (0.9.0, `make ci` green). Round 1 (parts 3 and 4) is done; round 2 below covers its fixes. What's left needs your phone, your Forerunner 70 and your Garmin account. This page puts all of it in one order. It replaces reading the [real-watch checklist](TESTING.md#real-watch-checklist) item by item; every checklist item is covered here.
**Rules for every step:** use only fake or test accounts and the fake secrets on this page. Never type a real secret into the app, the forms or the test pages.
Total time: about 2.5 to 3 hours, which can be split across days at any part boundary.
| Part | What | Time |
| --- | --- | --- |
| 1 | Preparation on the computer | 10 min |
| 2 | Garmin developer account | 10 min |
| 3 | Settings spike (M1) | 30 min |
| 4 | Debug build over USB: benchmark, demo entries, scanning | 40 min |
| 5 | Store beta 0.7.0, then the update to 0.8.0 | 20 min |
| 6 | Phone forms, glance, brightness on 0.8.0 | 45 min |
| 7 | Uninstall check and clean-up | 10 min |
| 8 | Send me the results | 5 min |
## Round 2: version 0.9.0 (after your results of 2026-10-21)
Your first round (parts 3 and 4, and 5.2) is recorded: the spike in [SETTINGS_SPIKE.md](SETTINGS_SPIKE.md#results), the benchmark in [PERFORMANCE.md](PERFORMANCE.md), and the fixes in the [changelog](../CHANGELOG.md) (0.9.0). Do this round next; then continue with the parts of round 1 you haven't done (5.3 onwards), on 0.9.0 instead of 0.8.0.
1. **Spike test C, split.** Send yourself `spike/settings/test-strings/index.html` again (it has new strings). Paste each of `C1` to `C8` and `aegis-json` into Text 2 of Settings Spike and save. Note which ones the phone refuses. This decides whether Aegis JSON can be imported at all.
2. **Build:** `make build DEVICE=fr70` and `make package` (gives `build/package/otp-wallet-0.9.0.iq`).
3. **Update the Store beta.** Upload `otp-wallet-0.9.0.iq` as a new version of OTP Wallet and update it on the watch. Menu, **About** must say 0.9.0. Your entries must still be there.
4. **Your old 6-digit PIN.** Open `TestLocked`. The keypad shows an OK key this one time: enter your old PIN and OK. The watch then asks for a new 4-digit PIN twice (use `1357`). After that the keypad has no OK key, and the 4th digit enters the PIN.
5. **PIN keypad.** Leave the app, open `TestLocked` again, enter `1357`: it opens on the 4th digit. Try a wrong PIN: "Wrong PIN" at the 4th digit, no more digits than dots. Note whether the keys are easy to hit now.
6. **Touch scrolling.** Swipe up and down on the entry list and on a text screen (menu, **About** or **Settings results**): they scroll. Note whether a short swipe scrolls too much or too little.
7. **Require PIN from the phone:** part 6.6 (rewritten: turn on **Apply**; a Require PIN sent while the PIN isn't entered now applies when you next enter it).
8. **QR progress.** Add a QR card (part 6.4 "Big QR") and open it the first time: the percentage should start low and rise steadily. Note the time.
9. **Auto-lock on a barcode.** Lock a barcode card with Require PIN, open it, wait longer than **Lock after**: the card closes.
Send the results of this round in the same form as part 8 ("OK" where it worked).
## What you need
- The computer, with Docker running: `sudo systemctl start docker` (it is off after a reboot).
- Your Android phone with **Garmin Connect** and the **Connect IQ Store** app, signed in to your Garmin account, paired with the Forerunner 70.
- The Forerunner 70's USB cable.
- An authenticator app on the phone (Aegis, or the one you use) to compare codes. You'll add a fake test entry to it and delete it at the end.
- A barcode scanner app on the phone that reads QR, Data Matrix, PDF417 and Aztec, for example the zxing-based "Barcode Scanner" or "Binary Eye".
- A stopwatch (the phone's clock app).
- Something to write the results in: a text file is fine. Part 8 has the template.
### The fake test data
| Name | Value |
| --- | --- |
| Test secret A | `JBSWY3DPEHPK3PXP` |
| Test secret B | `GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ` |
| Test PIN | `1357` (any 4 digits you don't use elsewhere) |
| Test EAN-13 | `5901234123457` |
Two `otpauth://` links for the import test (fake accounts, secret A and B):
```text
otpauth://totp/TestOne:alice@example.com?secret=JBSWY3DPEHPK3PXP&issuer=TestOne
otpauth://totp/TestTwo:bob@example.com?secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&issuer=TestTwo&digits=8
```
A text of 300 characters for the large-QR timing (one line):
```text
Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789. Fake QR test text 0123456789.
```
Get these onto the phone the same way as the spike strings in part 3 (email them to yourself, for example).
## Part 1: preparation on the computer
In the project folder:
1. Back up the developer key **before the first upload**. Copy the folder `.cache/keys/` to an encrypted place (a password-manager attachment or an encrypted USB drive). Once an app is uploaded with this key, every update must be signed with it; without it you'd have to start over with a new app and lose the data on the watch.
2. Build what you'll upload and sideload:
```sh
make spike
make build DEVICE=fr70
make package
```
3. Check that these files exist:
- `build/spike/settings-spike.iq`: the spike, for part 3.
- `build/debug/fr70.prg`: the debug build, for part 4.
- `build/package/otp-wallet-0.7.0.iq` and `build/package/otp-wallet-0.8.0.iq`: the Store betas, for part 5. The 0.7.0 file is the old one from M7; `make package` only rebuilds 0.8.0. If 0.7.0 is missing, tell me and we'll test the update differently.
## Part 2: Garmin developer account
1. Open <https://developer.garmin.com/connect-iq/> and sign in with your normal Garmin account.
2. Accept the Connect IQ developer agreement if asked.
3. Find the developer dashboard ("Upload an app" / "My apps"). You'll upload two apps there: Settings Spike in part 3 and OTP Wallet in part 5. Both are **beta apps**: only your account can see them.
Garmin renames these pages sometimes; if a label differs, look for "beta" in the upload form.
## Part 3: the settings spike (M1)
This measures what Garmin Connect allows in the settings forms (field lengths, characters, write-back). The full instructions are in [SETTINGS_SPIKE.md](SETTINGS_SPIKE.md); this is the short order.
1. **Upload:** in the dashboard, upload `build/spike/settings-spike.iq` as a **new app**, tick **Beta App**, name it "Settings Spike", fill in any short description and category. Wait until it shows as available (usually minutes).
2. **Install:** on the phone, open the Connect IQ Store app, find Settings Spike under your apps, install it on the Forerunner 70.
3. **Start it** on the watch from the apps list. It shows "Settings spike", "Changes seen: 0" and eight empty fields.
4. **Test strings:** send `spike/settings/test-strings/index.html` to the phone (email it to yourself) and open it in Chrome. Each string has a Copy button.
5. **Run tests A to H** from the table in [SETTINGS_SPIKE.md](SETTINGS_SPIKE.md#step-5-the-tests), with the spike open on the watch. The settings are in Garmin Connect: Forerunner 70, Connect IQ apps (or Activities & Apps), Settings Spike, Settings. Save after each change and read the watch.
6. **Write down** each result in the Results table of that page, or in your notes. Include the date, phone model, Garmin Connect version (Settings, About) and watch firmware.
7. Leave the spike installed until part 7; it doesn't interfere with OTP Wallet.
## Part 4: debug build over USB
The debug build has fake demo entries and the on-watch benchmark. It gets no phone settings, so it's only for these tests. Do this part **before** installing OTP Wallet from the Store, and remove it at the end of the part, so the two never sit on the watch at the same time.
### 4.1 Copy it to the watch
1. Connect the watch to the computer with the USB cable.
2. Open it in your file manager. Newer Garmin watches appear as an MTP device ("Forerunner 70", then "Internal Storage").
3. Copy `build/debug/fr70.prg` into the folder `GARMIN/APPS` (on some watches `GARMIN/Apps`).
4. Eject the watch and unplug it. The app "OTP Wallet" appears in the watch's apps list.
The watch installs the app and then removes `fr70.prg` from `GARMIN/APPS`, so the file isn't there afterwards. The app's storage shows up as `fr70.DAT`, `fr70.IDX` and `fr70.IMT` in `GARMIN/APPS/DATA`, and `fr70.SET` in `GARMIN/APPS/SETTINGS`. A sideloaded app never appears in the Connect IQ Store app.
If the watch doesn't show up in the file manager, stop and tell me. Don't install anything on the computer for this without us talking first.
### 4.2 Benchmark
1. Open OTP Wallet, open the menu (hold MENU, or long-press the screen), choose **Debug: benchmark**.
2. Wait until it finishes ("Takes a few seconds").
3. Take a photo of the screen, or write down every line (scroll if needed).
### 4.3 Demo entries, codes and PIN
1. Menu, **Set PIN**: enter the test PIN. Then menu, **Debug: demo entries**. The list fills with fake entries (GitHub, Google, Bank, VPN, Steam, Library and five cards). Bank is the locked one: if it isn't in the list, it is waiting for the PIN; choose menu, **Phone changes**, **Confirm all** and enter the PIN.
2. Check the list, open GitHub: the code in large digits and the countdown ring. In the last 5 seconds the next code shows too.
3. Open VPN (HOTP) and tap the code (or START): the next code appears.
4. Open Bank: the PIN keypad. Type with your finger: is it easy to hit the keys?
5. Enter a wrong PIN: the watch vibrates. Enter wrong PINs until five are wrong: the watch makes you wait 30 s.
6. Unlock with the right PIN, press BACK until you leave the app, start it again, open the locked entry: it must ask for the PIN again.
7. In the glance loop (scroll up or down from the watch face), the OTP Wallet glance shows the number of entries.
8. Menu, **Clock status**: the clock should say it is synced. Note what it shows.
### 4.4 Scanning the demo cards
Open each card and scan it with the phone's scanner app, indoors and outdoors (in daylight). If you can, try a shop scanner too. For each, note: reads / reads with effort / doesn't read.
| Card | Type | Note also |
| --- | --- | --- |
| Gym card | EAN-13 | |
| Member QR | QR | Roughly how long the first opening takes ("Encoding…"); the second opening should be instant |
| Parcel | Data Matrix | |
| Ticket | PDF417 | |
| Rail pass | Aztec | |
While a card is open: the screen should go to full brightness (the Forerunner 70 has an AMOLED screen) and stay bright for about a minute; a tap renews it. Check this in a dim room.
### 4.5 Remove the debug build
1. On the watch, remove OTP Wallet: highlight it in the apps list, hold UP (MENU) and choose **Remove**. This worked on the Forerunner 70 (2026-10-21). If the apps list has no such option, look under **Settings**, **Activities & Apps** (or **Apps**).
2. Connect the watch over USB and delete its leftover storage: `fr70.DAT`, `fr70.IDX` and `fr70.IMT` in `GARMIN/APPS/DATA`, and `fr70.SET` in `GARMIN/APPS/SETTINGS`. Leave every other file alone: files with 8-character names such as `G7AA3237.*` belong to apps installed from the Store (Settings Spike and others).
3. Eject, unplug, and check that OTP Wallet is gone from the apps list.
## Part 5: Store beta, and the update from 0.7.0 to 0.8.0
To check that an update keeps your data, you install 0.7.0 first, put test data in, then update to 0.8.0.
### 5.1 Install 0.7.0
1. In the dashboard, upload `build/package/otp-wallet-0.7.0.iq` as a **new app**, tick **Beta App**, name it "OTP Wallet".
2. On the phone, in the Connect IQ Store app, install OTP Wallet on the Forerunner 70.
3. Start it: it is empty and asks nothing yet.
### 5.2 Put test data in
1. Watch: menu, **Set PIN**, the test PIN.
2. Phone: Garmin Connect, Forerunner 70, Connect IQ apps, OTP Wallet, **Settings**.
3. **Add OTP** form: Issuer `TestOne`, Account `alice@example.com`, Secret: test secret A. Turn on **Add this entry**, save. Keep OTP Wallet open on the watch while saving.
4. Add a second one the same way: Issuer `TestLocked`, Secret: test secret B, **Require PIN to display** on.
5. **Add code** form: Card name `Test QR`, type QR, contents `Fake QR test text`. Save.
6. On the watch, open `Test QR` once (it gets encoded and cached).
7. Note the order of the entries in the list.
### 5.3 Update to 0.8.0
1. In the dashboard, open the OTP Wallet app and upload `build/package/otp-wallet-0.8.0.iq` **as a new version of it** (not as a new app).
2. Update it on the watch from the Connect IQ Store app (or wait for the automatic update).
3. Open OTP Wallet. Menu, **About** must say 0.8.0. Check:
- The three entries are there, in the same order.
- `TestLocked` asks for the PIN and the test PIN opens it.
- `Test QR` shows "Encoding…" once (the cache format changed in 0.8.0), and opens instantly the next time.
## Part 6: phone forms, glance and brightness on 0.8.0
Keep OTP Wallet open on the watch while you save forms, unless a step says otherwise. For each form, note the **Result** field on the phone (close and reopen the settings to see it) and the **Settings results** screen on the watch.
### 6.1 Codes match the authenticator
1. In your phone authenticator app, add a test entry manually with test secret A (TOTP, SHA1, 6 digits, 30 s).
2. Compare it with `TestOne` on the watch over two or three periods: the codes must be the same.
### 6.2 Add OTP form
1. You did this in 5.2. Now send the same form again unchanged: turn **Add this entry** on again and save. The result must be "Already added".
2. Note whether the form's fields were emptied on the phone after the first save.
### 6.3 Import form
1. Paste the two `otpauth://` links from the top of this page into **Text, part 1** (one per line).
2. Turn on **Import now**, save.
3. Check on the watch: `TestOne` is reported as a duplicate, `TestTwo` is imported with 8 digits.
4. Note whether the text field was emptied on the phone.
### 6.4 Add code form
1. Add an EAN-13 with the test EAN-13 (`5901234123457`), card name `Test EAN`. Scan it from the watch with the phone.
2. **Large code timing:** add a QR named `Big QR` with the 300-character text from the top of this page. On the watch, open it and time the "Encoding…" with the stopwatch. Open it again: instant. Scan it: the scanner must show the whole text.
### 6.5 Manage entry form
The entry IDs are in the About group on the phone, or in **Entry IDs** on the watch menu.
For every Manage entry change: fill in the entry ID and the action, then turn on **Apply** and save. Without Apply the watch ignores the form.
1. Rename `TestTwo` to `Renamed`.
2. Move `Renamed` to position 1.
3. Delete `Renamed`.
4. Check after each: the watch list changes.
### 6.6 Locked entry changes need the PIN
1. Close OTP Wallet on the watch and start it again, so the PIN isn't entered yet. With Manage entry, action **Require PIN** on `TestOne`, **Apply** on, save. The Result says "Locks when you next enter your PIN on the watch".
2. On the watch, open `TestLocked` and enter the PIN. `TestOne` now requires the PIN too (it shows the lock mark; reopen the app to check that it asks for the PIN).
3. While the PIN is still entered, a Require PIN applies at once: try it on another entry if you like.
4. Then send **Don't require PIN** for `TestOne`. The watch must **not** apply it by itself, even while the PIN is entered.
5. On the watch: menu, **Phone changes**, **Confirm all**, enter the PIN. Now it applies.
### 6.7 Options
1. Change **Theme** to Light and **Code size** to another size, save: the watch changes as soon as the phone saves.
2. Set them back.
3. Does the **About** catalog (up to 800 characters) show completely on the phone?
### 6.8 Glance code
1. Make sure `TestOne` doesn't require the PIN (after 6.6 it doesn't).
2. Manage entry: `TestOne`, action **Mark as favourite (glance)**. Save.
3. Options: turn on **Show the favourite code in the glance**. Save. Open OTP Wallet once, then leave it.
4. In the glance loop: OTP Wallet shows `TESTONE`, the code and a bar counting down. The code matches the app and your authenticator.
5. Turn the option off on the phone and save, **without** opening the app: the glance must go back to "N entries".
6. Turn it on again, open the app once. Then set **Require PIN** on `TestOne` and open the app: `TestOne` must leave the glance.
### 6.9 Brightness
1. In a dim room, open `Test EAN`: the screen goes to full brightness and stays bright for about a minute. Tap: it renews.
2. Options: turn **Full brightness while showing a barcode** off, save, open the barcode again: it stays at your normal brightness now.
3. Turn it back on.
### 6.10 Auto-lock and passcode
1. Unlock `TestLocked`, then wait without touching the watch longer than **Lock after** (1 min by default): it must lock again.
2. If you use a watch passcode (system lock), note whether OTP Wallet behaves normally with it.
## Part 7: uninstall check and clean-up
1. In the Connect IQ Store app, uninstall OTP Wallet from the watch.
2. Install it again (0.8.0). Start it: it must be empty, with no entries and no PIN.
3. Uninstall Settings Spike from the watch. You can delete its beta from the dashboard.
4. Delete the test entry from your phone authenticator app, and the test strings and links you emailed yourself.
5. Keep OTP Wallet installed if you want to start using it; it's 0.8.0 until I tag 1.0.0 (then you'll upload that as a new version).
## Part 8: send me the results
Copy this, fill it in and paste it in the chat. "OK" is enough where everything worked; describe anything else. Photos of the screen help where something looks wrong.
```text
Phone, Garmin Connect version, watch firmware:
PART 3 SPIKE
A longest field complete / above that:
B largest total:
C characters missing or blocking:
D status visible on phone / password cleared:
E changes while open / while closed:
F password: arrives / masked:
G time short / longest:
H number field validation:
Other:
PART 4 DEBUG BUILD
Benchmark lines (or photo):
Demo list, codes, ring, HOTP next:
PIN keypad feel / wrong PIN vibrate / 30 s wait:
Locked again after leaving:
Glance shows entry count:
Clock status:
Scans (indoors / outdoors / shop): Gym card, Member QR, Parcel, Ticket, Rail pass:
Member QR first opening time:
Full brightness on barcode:
PART 5 UPDATE
Entries, order and PIN kept after 0.7.0 -> 0.8.0:
Test QR re-encoded once, then instant:
PART 6 ON 0.8.0
Codes match authenticator:
Add OTP: result / fields emptied / repeat says Already added:
Import: result / text emptied:
Test EAN scans:
Big QR encoding time / scans complete:
Manage: rename, move, delete:
Locked change waits for Confirm all + PIN:
Theme / code size change at once:
About catalog complete on phone:
Glance: code + countdown / option off hides it / locked leaves it:
Brightness on / off option:
Auto-lock / passcode:
PART 7
Reinstall starts empty:
```
When I have this, I'll put the numbers into PERFORMANCE.md and the spike results into the design, fix anything that failed, and tag 1.0.0. Anything that can't be fixed goes into the known limitations in the [user guide](USER_GUIDE.md#known-limitations).
|