From e3cc458d3b9aadb9459b51ef0120621408093f38 Mon Sep 17 00:00:00 2001 From: cirakg Date: Tue, 20 Oct 2026 02:43:08 +0200 Subject: docs: record M6a (linear barcodes) results Co-Authored-By: Claude Opus 5.5 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'README.md') diff --git a/README.md b/README.md index 5d3dff3..a9ec6af 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A Garmin Connect IQ watch app that shows one-time passwords (TOTP, HOTP, and optional Steam Guard codes) and stores barcodes and QR codes (loyalty cards, tickets) to show at a scanner. Everything lives encrypted on the watch. There is no cloud, no backend and no analytics, and the app requests no permissions, so it cannot use the network. -> **Status: M5 (import) done; M1 (settings spike) ready for your phone test.** The plan below was approved on 2026-10-18. M0 built the Docker toolchain and pipeline, M2 the crypto and OTP core, M3 the encrypted vault ([docs/SECURITY.md](docs/SECURITY.md)) and M4 the screens. M5 added import: `otpauth://` links and unencrypted Aegis JSON pasted into the new Import group of the phone settings, parsed on the watch with a streaming JSON tokenizer. It also detects duplicates, supports multi-part pastes and shows a results screen. It's tested with fixtures, a seeded fuzz corpus, and a 100-entry import through the settings path on seven simulated watches. Google Authenticator exports are deferred. Next is M6, barcodes. The settings spike (`make spike`, [docs/SETTINGS_SPIKE.md](docs/SETTINGS_SPIKE.md)) waits for your test. The Phase 0 research, with sources, is in [docs/FEASIBILITY.md](docs/FEASIBILITY.md); the daily workflow is in [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md). +> **Status: M6a (linear barcodes) done; M6b-M6d (QR, Data Matrix, PDF417, Aztec) next; M1 (settings spike) ready for your phone test.** The plan below was approved on 2026-10-18. M0 built the Docker toolchain and pipeline, M2 the crypto and OTP core, M3 the encrypted vault ([docs/SECURITY.md](docs/SECURITY.md)), M4 the screens and M5 import (`otpauth://` and Aegis JSON via the phone settings). M6a added the code screen and the EAN-13, EAN-8, UPC-A, UPC-E, Code 128, Code 39, ITF and Codabar encoders. They're checked against zxing-cpp reference rows and decoded at 1 to 3 px per module, and a screenshot of the code screen decodes on seven simulated watches. The settings spike (`make spike`, [docs/SETTINGS_SPIKE.md](docs/SETTINGS_SPIKE.md)) waits for your test. The Phase 0 research, with sources, is in [docs/FEASIBILITY.md](docs/FEASIBILITY.md); the daily workflow is in [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md). "OTP Wallet" is a working title. @@ -567,7 +567,7 @@ Imported entries behave exactly like manual ones. You rename, regroup, move, loc ### 12.2 Rendering - **Area**: 2D codes use the largest centred square (round screens) or rectangle. Linear codes and PDF417 use the widest horizontal band. -- **Module size**: the largest whole number of pixels per module that fits, including the quiet zone (QR 4 modules, Data Matrix 1, PDF417 2, linear codes 10). The minimum is 2 px to start with. Scan tests in M6 may raise it, or allow 1 px for linear codes on 218 px screens. +- **Module size**: the largest whole number of pixels per module that fits, including the quiet zone (QR 4 modules, Data Matrix 1, PDF417 2, linear codes 10). The minimum is 2 px for 2D codes. Linear codes may use 1 px: an EAN-13 needs that on a 218 px screen, and the Forerunner 255S screenshot decodes at 1 px. Your phone and real scanners still need to confirm it (manual checklist). - **Colours**: always black modules on a white area that includes the quiet zone, whatever the theme. - **Human-readable text**: digits under linear codes when enabled and there's room. - **Brightness**: on AMOLED watches the app asks for full brightness while a code is shown, for up to about a minute. That's the burn-in protection limit; a tap boosts it again. On MIP watches the backlight is turned on. @@ -587,7 +587,7 @@ Linear: EAN-13 needs 113 modules, which means 1 px per module on a 218 px screen ### 12.4 How each symbology is proven scannable -1. **Reference comparison**: Python reference encoders in Docker (zxing-cpp's writer, segno for QR with forced version and mask, and others) generate expected bar patterns and matrices for fixed parameters. The watch encoder must match them exactly wherever the output is deterministic: all linear codes, QR with forced version and mask, and Data Matrix in ASCII mode. +1. **Reference comparison**: Python reference encoders in Docker (zxing-cpp's writer, segno for QR with forced version and mask, and others) generate expected bar patterns and matrices for fixed parameters. The watch encoder must match them exactly wherever the output is deterministic: the EAN/UPC family, Code 39, ITF, Codabar, QR with forced version and mask, and Data Matrix in ASCII mode. Code 128 is the exception, because it has several equally short encodings. zxing-cpp 3 writes through zint, which breaks those ties differently from the zxing rules the watch uses. For Code 128 the module count must match (it did for 5,000 random strings), and the code must decode (check 2). 2. **Decoding**: the simulator tests dump every encoder output. It's rendered at each device's module size and decoded with zxing-cpp, which reads all 12 symbologies. The decoded text must equal the input, for hundreds of seeded random payloads per symbology. 3. **Screenshots**: simulator screenshots of the code screen on Forerunner 255S, Venu Sq 2 and Forerunner 965 must decode with zxing-cpp. 4. **Real world** (manual checklist): your phone's camera, plus any real shop scanner you can try, indoors and outdoors, on MIP and AMOLED. -- cgit v1.2.3