# Changelog All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Versions stay at 0.x until milestone M8; each milestone raises the minor version. ## [Unreleased] Milestone M6 in progress (released as 0.6.0 when all four parts are done). ### Added - M6a, linear barcodes (`source/codes/`): EAN-13, EAN-8, UPC-A and UPC-E, with check digits added, verified, fixed or off, and canonical UPC-E zero suppression; Code 128 (sets B and C); Code 39 with an optional mod-43 check character; ITF with an optional check digit; Codabar with start and stop characters. - The code screen: black on white, the largest whole module size, human- readable text, and a full-backlight request. - Reference rows from zxing-cpp (`tools/gen_code_vectors.py`, `make codes`). Barcodes from the unit tests are decoded with zxing-cpp in every test run (`tools/check_codes.py`), and the UI flow decodes a screenshot of the code screen. ## [0.5.0] - 2026-10-20 Milestone M5: import. You can now add entries by pasting `otpauth://` links or an unencrypted Aegis JSON export into the new Import group of the app settings. ### Added - `source/import/`: - A streaming JSON tokenizer: strict, with depth and length limits; skips icons natively; reports incomplete input. - The Aegis reader: database versions 1-3, groups, encrypted exports refused, duplicate fields rejected. - The `otpauth://` parser: run-together URIs, `;` separators, Steam forms, issuer mismatch notes. - The import job: Replace mode, the duplicate and replacement checks, a multi-part buffer sealed with the device key (32 KB, 24 h), and a report. - `source/settings/`: - The settings processor: the Import form, applied after the first frame and on every settings change. It clears the fields, writes the status, remembers form hashes and opens the results screen. - The results store; the list shows "Results ready" until they're read. - The Import group in the phone settings (8 text fields, mode, "Require PIN", "Import now", result). - An 8-byte keyed secret fingerprint in every record header, to find duplicates of locked entries while locked (docs/SECURITY.md). - Seeded fuzz corpus (`tools/gen_fuzz_corpus.py`, `make corpus`); 29 Monkey C and 5 Python tests. The UI flow imports 100 entries through the settings form and checks the peak memory. ### Changed - Info screens space out their items; the results screen is titled "Results". ### Deferred - Google Authenticator `otpauth-migration://` exports (README 11.1): the importer explains that they aren't supported yet. ## [0.4.0] - 2026-10-19 Milestone M4: the screens. The app is usable in the simulator with demo entries; adding real entries comes with M5 (import) and M7 (settings). ### Added - List of entries with live codes, countdowns, lock and barcode icons, and groups. Rows adapt to narrow screens, and headers are read only for the visible rows. - OTP detail: large grouped code, countdown ring (bar on rectangular screens), next code in the last 5 seconds, HOTP "next" with the counter, entry ID. - PIN screen: touch keypad or button digit selector. It covers create (twice, with a warning below 6 digits), unlock and change. Wrong PINs vibrate, and the lockout wait is shown. Pending locked entries are promoted after unlocking. - Menu: lock now, set/change/reset PIN, settings results, entry IDs, clock status, about. Debug builds add demo entries, a performance overlay and an on-watch benchmark. - Glance with the number of entries; the crypto self-test on first start and daily; auto-lock while a locked entry is open. - Option properties with defaults (`resources/settings/properties.xml`). - UI-test build with fake entries, PIN and a frozen clock. A scripted UI flow (`tools/ui_flow.py`) checks 10 screens on each of seven simulated watches. Also new: `tools/gen_fixture_wrap.py`, and 7 Monkey C and 6 Python tests. ### Changed - PBKDF2 XORs 32-bit words: 2.3× faster, and 100 iterations per job step, because 200 tripped the watchdog on the Forerunner 255S. - Codes are computed in their own timer events, at most one SHA-512 code per event. - `make screenshots` runs the scripted flow; goldens are now `test/golden//.png`. Start-up budgets are set from the M4 measurements. ## [0.3.0] - 2026-10-19 Milestone M3: storage, keys and PIN logic. Nothing user-visible yet; the screens come with M4. ### Added - Storage (`source/storage/`): the vault (ordered entries, add, update, move, remove, HOTP counter), the deterministic TLV codec, the record format (readable header plus an encrypt-then-MAC box bound to the entry ID), the device key and the PIN-wrapped master key, resumable PIN derivation, the wrong-PIN lockout (trusted clock with an uptime fallback, optional erase after 10 failures), the session with auto-lock and key wiping, the pending queue for locked entries, schema migrations, the 150-entry cap and clean store-full errors. - `Bytes.toUtf8` with strict UTF-8 validation. - `docs/SECURITY.md`: the stored byte formats and what each protection is tested by. - 34 Monkey C tests (65 in total per device) and storage benchmarks. ### Changed - The PIN wrap and the lockout state are stored under their own keys (`w`, `lk`) instead of inside the metadata (README 6.2 updated). ## [0.2.0] - 2026-10-18 Milestones M1 (prepared; your phone test pending) and M2: crypto and OTP core. Nothing user-visible yet; the home screen still shows only name and version. ### Added - Crypto (`source/crypto/`): SHA-512 in Monkey C (FIPS 180-4), generic HMAC (RFC 2104) for SHA-1/SHA-256/SHA-512 plus native HMAC-SHA256, resumable PBKDF2-HMAC-SHA256 with calibration, HKDF-SHA256, AES-CBC with PKCS#7 (AES-256 chosen), SealedBox encrypt-then-MAC records, and a start-up self-test. - OTP (`source/otp/`): Base32 decoding with exact error positions, HOTP, TOTP (64-bit time, correct after 2038) and Steam Guard codes. - Utilities: constant-time comparison and wiping (`Bytes`), the 2038-safe clock and trusted-clock check (`Clock`), resumable jobs with a timer runner (`Jobs`). - `tools/gen_vectors.py` and `make vectors`: official RFC/FIPS/NIST vectors, each recomputed with Python's standard library or openssl before use, plus seeded cases (SHA padding boundaries, 2038, 2100, all digit counts). - 31 Monkey C unit tests and a benchmark, passing on all four test devices. - M1 settings spike: a separate test app (`spike/settings/`), `make spike`, `make spike-sim`, test strings and `docs/SETTINGS_SPIKE.md`. ### Changed - Screenshot checks are now strict: at most 0.01 % of pixels may differ (one changed character used to pass under the old 0.5 % tolerance). - SHA-512 and PBKDF2 inner loops optimised (37 % and 42 % faster in the simulator) without changing results. ## [0.1.0] - 2026-10-18 Milestone M0: scaffolding. Not useful on a watch yet; the app shows only its name and version. ### Added - Project plan (`README.md`), Phase 0 feasibility findings with what M0 verified (`docs/FEASIBILITY.md`), developer guide, testing and performance documents. - Docker images with pinned versions: `garmin-otp/dev` (Ubuntu 22.04 snapshot, Java 17, headless simulator stack, hash-locked Python tools, checksum-verified SDK manager CLI) and `garmin-otp/docs` (Markdown lint and Mermaid rendering). - `Makefile` running every step in hardened containers: no capabilities, read-only root filesystem, only the project folder mounted, no network outside image builds and `make sdk`, serial even under `make -j`. - `make sdk` (agreements, login, SDK 9.2.0, device files for 72 watches, token deleted afterwards) and `make key` (RSA-4096 developer key). - Build pipeline with strict type checking and warnings as errors, per-size launcher icons for all 72 products, unit tests in the headless simulator on four devices, golden-image screenshot tests, start-up and memory budgets, and the signed `.iq` package. - Python tools with 44 tests: test-log judge, screenshot checker, budget checker, product rule checker, Markdown link checker, project linter (code rules and the Author/Summary header rule) and icon generator. - A minimal watch app (home screen with name and version) and a smoke test.