From d537f4e154a40075405b0ab2fed14fbe2eeaac81 Mon Sep 17 00:00:00 2001 From: cirakg Date: Tue, 20 Oct 2026 01:51:05 +0200 Subject: feat(settings): apply the Import form from the phone and show results 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 --- source/app/Fixtures.mc | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'source/app/Fixtures.mc') diff --git a/source/app/Fixtures.mc b/source/app/Fixtures.mc index 0b641ee..8ed35c9 100644 --- a/source/app/Fixtures.mc +++ b/source/app/Fixtures.mc @@ -1,5 +1,5 @@ // Author: cirakg & claude ai -// Summary: Debug-only fake entries for the simulator and screenshots; release builds get empty stubs. +// Summary: Debug-only fake entries (and, in UI tests, a fake import via the settings form); release builds get empty stubs. // // All data is fabricated: the secrets are the RFC 4226/6238 test keys and the // names are made up. The UI-test build (source/util/TestMode.mc) wipes the @@ -52,6 +52,41 @@ module Fixtures { card.payload = Bytes.fromUtf8("0000-1111-2222"); vault.add(card); vault.lock(); + if (TestMode.ON) { + startImport(); + } + } + + // UI-test build: an Aegis import of 100 entries through the settings + // form, the same path as the phone: 97 new, one duplicate of GitHub, one + // error and one skipped type. The results screen opens when it's done. + function startImport() as Void { + var rfcKey = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"; // lint: allow-literal (RFC 4226 test key, = GitHub's) + var proton = "KRSXG5BAKNSWG4TFOQQEWZLZEBEGK4TF"; // lint: allow-literal (fake: Base32 of "Test Secret Key Here") + var json = "{\"version\": 1, \"header\": {\"slots\": null, \"params\": null}, \"db\": {\"version\": 3, \"entries\": [" + + aegisEntry("totp", "Proton", "zoe@example.com", proton, 6) + "," + + aegisEntry("totp", "GitHub copy", "alice@example.com", rfcKey, 6) + "," + + aegisEntry("totp", "Broken", "x", proton, 9) + "," + + aegisEntry("motp", "Legacy", "y", rfcKey, 6); + // 96 more, so the flow imports 100 entries through the paced job. + // Fake 16-character Base32 secrets built from alphabet letters (cheap: + // Base32-encoding 96 secrets in this one event would trip the watchdog + // on the Forerunner 255S). + var abc = Base32.ALPHABET; + for (var i = 0; i < 96; i++) { + var secret = "MFRGGZDF" + abc.substring(i / 32, i / 32 + 1) + abc.substring(i % 32, i % 32 + 1) + "MZTWQ2LK"; + json += "," + aegisEntry("totp", "Site " + i, "user" + i + "@example.com", secret, 6); + } + json += "], \"groups\": []}}"; + Application.Properties.setValue("impText1", json); + Application.Properties.setValue("impMode", 0); + Application.Properties.setValue("impLocked", false); + Application.Properties.setValue("impApply", true); + } + + function aegisEntry(type as String, issuer as String, name as String, secret as String, digits as Number) as String { + return "{\"type\": \"" + type + "\", \"name\": \"" + name + "\", \"issuer\": \"" + issuer + + "\", \"info\": {\"secret\": \"" + secret + "\", \"algo\": \"SHA1\", \"digits\": " + digits + ", \"period\": 30}}"; } function otp(name as String, account as String, group as String, type as Number, algorithm as Number, -- cgit v1.2.3