summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* feat(codes): add EAN/UPC, Code 128, Code 39, ITF and Codabar encoderscirakg9 days6-0/+661
| | | | | | | | Check digits added, verified, fixed or off; canonical UPC-E zero suppression; Code 128 sets B and C with zxing's switching rules; module rows match zxing-cpp (Code 128 by length, the tie-breaking differs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: record M5 results; bump to 0.5.0v0.5.0cirakg9 days6-5/+111
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(import): cover parsers, importer and a seeded fuzz corpus; import 100 ↵cirakg9 days23-5/+1050
| | | | | | entries in the UI flow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(settings): apply the Import form from the phone and show resultscirakg9 days13-16/+411
| | | | | | | | Import group in the app settings; the processor runs after the first frame and on settings changes, clears the fields, writes the status, remembers form hashes and opens the results screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(import): parse otpauth URIs and unencrypted Aegis JSON in resumable stepscirakg9 days8-0/+1609
| | | | | | | | | | Streaming JSON tokenizer with depth and length limits and native skipping of long strings; Aegis reader for database versions 1-3 with groups and encrypted-export detection; otpauth parser with ';' separators and Steam; import job with Replace mode, duplicate and replacement checks, a sealed multi-part buffer and a report. Google Authenticator exports deferred. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(storage): add keyed secret fingerprints to record headerscirakg9 days4-1/+53
| | | | | | | | An 8-byte HMAC of kind, type and secret (key derived from the device key) in header tag 13 lets imports find duplicates of locked entries while the watch is locked. Vault gains anyHeader() and storage(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: record M4 results and simulator findings; bump to 0.4.0v0.4.0cirakg9 days7-20/+132
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(ui): drive the simulator with a scripted flow and check every screencirakg9 days79-32/+808
| | | | | | | | | tools/ui_flow.py clicks buttons and taps from the device files, waits for DIAG shown lines and compares 10 screens per watch with goldens on four test and three spot-check devices. Adds the fixture-wrap generator, UI logic tests and driver tests; the launcher opens apps from their glance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(ui): add the list, OTP detail, PIN entry, menu, info screens and glancecirakg9 days23-16/+2575
| | | | | | | | | | | | List with live codes and countdowns, adaptive rows and lazy headers; OTP detail with ring or bar, next code and HOTP next; PIN keypad or button selector with create, unlock, change, lockout display and pending promotion; native menu; glance with the entry count; self-test after the first frame; option properties with defaults. Codes are computed one per timer event, apart from drawing, for the watchdog. A UI-test build (uitest.jungle) starts with fake entries, PIN 123456 and a frozen clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* perf(crypto): XOR PBKDF2 blocks as 32-bit words and step 100 iterationscirakg9 days7-76/+76
| | | | | | | | 200 byte-wise iterations in one event tripped the 120,000-bytecode watchdog on the Forerunner 255S profile. Word-wise XOR makes PBKDF2 2.3x faster (22 ms per 1000 iterations in the simulator). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: document the storage format and record M3 results; bump to 0.3.0v0.3.0cirakg10 days12-4/+218
| | | | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(storage): cover records, vault, PINs, lockout and migrationscirakg10 days7-1/+1065
| | | | | | | | | | 34 new tests (65 per device): round trips per entry type, every tampered byte, swapped records, the pending queue, the entry cap, a full store at 67 fill levels, the lockout schedule on a fake clock including restarts, erase, PIN change and reset, auto-lock wiping, and v0 to v1 migration. Adds an in-memory store with a size limit and storage benchmarks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(storage): add the encrypted vault, PIN keys, lockout, session and ↵cirakg10 days12-0/+1605
| | | | | | | | | | | | | | migrations Records are one ByteArray each: a readable TLV header plus an encrypt-then-MAC box whose aad binds the entry ID and the header. The device key seals unlocked entries and pending items; a random master key, wrapped under a PBKDF2 PIN key, seals locked ones. Wrong PINs are counted before the check, with delays on the trusted clock and an uptime fallback. Bytes.toUtf8 validates UTF-8 first, because the native conversion crashes on invalid input. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: record M2 results and bump version to 0.2.0v0.2.0cirakg10 days7-4/+84
| | | | | | | | | CHANGELOG 0.2.0; PERFORMANCE (simulator benchmarks and what they mean for the watch); TESTING (vector sources, M2 results, watchdog caveat); FEASIBILITY (verified: no native HMAC-SHA1, AES-256 works, Long semantics); README status and targets; developer-guide Monkey C facts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(spike): add the M1 settings spike app and make targetscirakg10 days37-5/+861
| | | | | | | | | | A separate throwaway app (own app ID, no permissions) that shows what the Garmin Connect app delivers per settings field and writes values back, to measure the undocumented settings limits on the real phone and watch. Includes length-marked test strings, `make spike` / `make spike-sim`, `make vectors`, and step-by-step instructions in docs/SETTINGS_SPIKE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: add cross-checked crypto/OTP vectors, unit tests and stricter screenshotscirakg10 days14-2/+1193
| | | | | | | | | | | | | - gen_vectors.py: RFC/FIPS/NIST vectors recomputed with Python's stdlib (openssl for AES) before use, plus seeded cases around SHA padding boundaries, 2038 and 2100; generates test/data/Vectors.mc. - 31 Monkey C tests (hashes, HMAC, PBKDF2, HKDF, AES, sealed records incl. every-byte tamper detection, Base32 errors, 100 OTP and 12 Steam vectors, clock, jobs) and a benchmark; pass on all four test devices. - Screenshot tolerance 0.01 %: one changed character no longer passes. - Golden images updated for version 0.2.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(otp): add Base32 decoding, HOTP, TOTP and Steam Guard codescirakg10 days2-0/+198
| | | | | | | | Base32 accepts any case, spaces, hyphens and missing padding, and reports the exact position of a bad character. TOTP uses 64-bit time, so codes stay correct after 2038. Steam Guard is a separate, optional code type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(crypto): add SHA-512, HMAC, PBKDF2, HKDF, AES-256 records and self-testcirakg10 days10-0/+923
| | | | | | | | | | | | | | | | - Sha512: FIPS 180-4 in Monkey C (no native SHA-512), rotations inlined with precomputed masks; constants derived from the primes, not typed. - Hmac: RFC 2104 over SHA-1/256/512 (native HMAC only supports SHA-256). - Kdf: resumable PBKDF2-HMAC-SHA256 job with calibration bounds (2,000-200,000 iterations) and HKDF-SHA256. - Aes: CBC with PKCS#7 over the native cipher; AES-256 chosen. - SealedBox: encrypt-then-MAC records (HKDF-split keys, length-prefixed aad, constant-time tag check before decryption). - SelfTest: known-answer tests for every primitive at start-up. - Bytes (wipe, constant-time equal), Clock (2038-safe widening, trusted clock), Jobs (bounded steps against the watchdog, timer runner). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: add developer, testing and performance guides; record M0 resultsv0.1.0cirakg11 days7-8/+238
| | | | | | | | | | | | - DEVELOPER_GUIDE: workflow, how the tooling works (verified simulator behaviour), conventions and how to add devices. - TESTING and PERFORMANCE: test layers, M0 results and measured numbers. - FEASIBILITY: what M0 verified (watchdog 120k/240k, 10 MB storage in device profiles, unreliable monkeydo exit code, icon sizes). - README status, new make targets and layout; CHANGELOG 0.1.0. - Author/Summary headers on every document, including the original brief. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(app): add minimal watch app with smoke test and per-size iconscirakg11 days29-0/+381
| | | | | | | | | | The M0 placeholder app: AppBase entry point, home screen with name and version, debug-only diagnostics (start-up time, memory) and a unit test that runs in the headless simulator. Builds with strict type checking and zero warnings for all 72 products; icons.jungle gives every product a launcher icon of its exact size. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(tools): add screenshot, budget and product checks; enforce file headerscirakg11 days21-81/+844
| | | | | | | | | | | | | | | | | | - sim_screenshot.py finds the device drawing in the simulator window, crops the screen and compares it with approved golden images. - check_budgets.py reads key=value DIAG/HARNESS lines (the simulator console escapes quotes, so JSON was dropped). - ciq_test_report.py accepts SDK 9.2.0's real summary line `PASSED (passed=N, failed=N, errors=N)`; a captured log is a fixture. - gen_products.py checks all manifest products are watches with API 5.0+ and at least 512 KB for apps. - lint_project.py rule HDR001: every file carries the Author/Summary header (JSON keys, PNG text chunks; generated package-lock exempt). - make_icon.py --all draws one icon per launcher size in use. - Golden screenshots for fr255s, venusq2, fr70 and fr965. - 44 tests, warnings as errors, ruff and mypy --strict clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build: complete the Docker pipeline for build, test, screenshots and packagingcirakg11 days20-5/+437
| | | | | | | | | | | | | | | - Container scripts now run from the mounted project (no image rebuild per script change): build-app.sh (strict -l 3, warnings fail), run-unit-tests.sh, screenshots.sh, app-diag.sh (perf/memory), lint.sh, package.sh and sim-vnc.sh (noVNC on 127.0.0.1:6080). - Headless simulator helpers: wait for port 1234, remove the stale single-instance lock (~/Sim-dev) that made later starts hang, show the simulator log on failure. - New targets: screenshots-approve, icons; `make lock` re-adds the requirements header; pytest treats warnings as errors. - Author/Summary headers on every build file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(tools): add test-log judge, docs and policy checks with testscirakg11 days12-0/+890
| | | | | | | | | | | | | | | - ciq_test_report.py: decides pass/fail from Run No Evil output instead of monkeydo's unreliable exit code; writes JUnit XML. - check_docs.py: offline check of relative links and GitHub anchors. - lint_project.py: project rules (headers, no logging outside Diag, no secret-like literals, no network APIs or permissions). - check_budgets.py with budgets.json: perf and memory gates. - make_icon.py: reproducible launcher icon. - 31 pytest tests, including Hypothesis fuzzing of the log parser and integration checks against the real docs and sources; ruff and mypy (strict) clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build: add Docker-only Makefile, SDK setup and product manifestcirakg11 days9-0/+558
| | | | | | | | | | | | | | | | | | - Makefile: every target runs in a container as your UID/GID, with no capabilities, a read-only root filesystem, only the project folder mounted and no network except for image builds and `make sdk`. Serial even under `make -j`. `make nuke` removes containers, images, the dedicated buildx builder and .cache/ after confirmation. - sdk-setup.sh: agreement acceptance pinned to the hash you read, password login (never stored), SDK 9.2.0 and device download, and the login token deleted afterwards. - gen-key.sh: RSA-4096 developer key into .cache/keys, never overwritten, with backup instructions. - manifest.xml: watch-app, minApiLevel 5.0.0, no permissions, and the 72 watches with API 5.0+ and at least 512 KB for apps. - .gitignore, lint configs and CHANGELOG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(docker): add pinned dev and docs imagescirakg11 days7-0/+4375
| | | | | | | | | | | | | | | | | garmin-otp/dev: Ubuntu 22.04 (pinned by digest; the simulator needs WebKitGTK 4.0), apt packages from a dated snapshot.ubuntu.com mirror, OpenJDK 17, Xvfb/openbox/noVNC for the headless simulator, the connect-iq-sdk-manager CLI v0.8.4 checked against its release SHA-256, and Python tools installed from a hash-locked requirements file. garmin-otp/docs: Node 22 (pinned by digest), Debian snapshot packages, markdownlint-cli2 and mermaid-cli from package-lock.json, and the headless Chrome build pinned by Puppeteer. Locks only use releases published before 2026-10-01. The Garmin SDK, device files and the developer key are never baked into an image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: record final decisions, test watch and SDK login detailscirakg11 days2-47/+58
| | | | | | | | | | | - README: Forerunner 70 is the test watch, the phone is Android, Docker access is settled; how `make sdk` logs in and why the browser login can't be used; the new `make products` and `make lock` targets. - FEASIBILITY: final decisions D1-D5. - Space out table separator rows and turn bold-only lines into headings so markdownlint passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Inital commit.cirakg11 days3-0/+1480