feat(pin): configurable 4/6/8-digit PIN length (runtime, persisted, change-PIN)
Make the timing-arc PIN length a runtime, per-device setting (default 4,
selectable 4/6/8) so users can raise on-device brute-force resistance
(~2 s/attempt: 4 ~5.5 h, 6 ~23 days, 8 ~years). Closes the practical side of
the counter-rollback residual; the crypto is unchanged (length-agnostic
PBKDF2 takes ptr+len).
- pin_policy: kPinLengthDefault/Max/Options + isValidPinLength/clampPinLength.
- PinEntryUI/renderer: digits_ sized to max 8, runtime activeLen_/pinLength_
drives arc loop, dots, verify; full-capacity zeroization preserved.
- AuthEntryUI::setPinLength seam (no-op for keyboard passphrase).
- Persist as NVS 'pin_len' (kleidos ns); load at boot, apply at PIN_ENTRY.
- Change-PIN wizard: after verifying the current PIN, arc devices pick the new
length (dropdown component + settings-picker input model) before entering the
new PIN; the new length is persisted on a successful re-encrypt.
- Settings SECURITY: PinLength row shows current length + launches change-PIN
(arc devices only; compiled out on keyboard).
- i18n: SetPinLength / PinChangeLength (5 langs).
- Tests: change-PIN 6/8-digit round-trip, PBKDF2 length-agnostic 6/8 derive,
settings-nav SECURITY count + PinLength action.
Claude-Session: https://claude.ai/code/session_01SLSU3WoYEyX1J7qWXxmyKo
Drive the keyboard passphrase editor through ScreenPainter
The keyboard-device master-unlock editor (passphrase_entry_ui, HAS_KEYBOARD:
Cardputer / T-Deck / Gray / CoreS3) repainted the whole screen on every caret
blink — a full 64800-byte blit ~twice a second just to toggle the caret, plus a
full repaint per keypress. Split drawFrame into ScreenPainter regions: the title
+ status band repaint only on a full paint, the "len/max" counter only when the
length changes, and the masked field + blinking caret on every partial pass.
drawFrame takes a fullPaint flag: status changes and the first paint are full;
the caret-blink / length-tick path passes false. lastFieldLength_ gates the
counter region.
Verified on Cardputer (RENDERSTATS + screenshots): render is pixel-correct
(placeholder, focused frame, mask dots, caret, green counter, hint) and the
per-blink blit dropped from 64800 to 8640 bytes (~87%), a keypress from 64800 to
12352 (~81%). Third screen onto the central dirty-only mechanism.
Drive the keyboard passphrase editor through ScreenPainter
The keyboard-device master-unlock editor (passphrase_entry_ui, HAS_KEYBOARD:
Cardputer / T-Deck / Gray / CoreS3) repainted the whole screen on every caret
blink — a full 64800-byte blit ~twice a second just to toggle the caret, plus a
full repaint per keypress. Split drawFrame into ScreenPainter regions: the title
+ status band repaint only on a full paint, the "len/max" counter only when the
length changes, and the masked field + blinking caret on every partial pass.
drawFrame takes a fullPaint flag: status changes and the first paint are full;
the caret-blink / length-tick path passes false. lastFieldLength_ gates the
counter region.
Verified on Cardputer (RENDERSTATS + screenshots): render is pixel-correct
(placeholder, focused frame, mask dots, caret, green counter, hint) and the
per-blink blit dropped from 64800 to 8640 bytes (~87%), a keypress from 64800 to
12352 (~81%). Third screen onto the central dirty-only mechanism.
feat(pin): configurable 4/6/8-digit PIN length (runtime, persisted, change-PIN)
Make the timing-arc PIN length a runtime, per-device setting (default 4,
selectable 4/6/8) so users can raise on-device brute-force resistance
(~2 s/attempt: 4 ~5.5 h, 6 ~23 days, 8 ~years). Closes the practical side of
the counter-rollback residual; the crypto is unchanged (length-agnostic
PBKDF2 takes ptr+len).
- pin_policy: kPinLengthDefault/Max/Options + isValidPinLength/clampPinLength.
- PinEntryUI/renderer: digits_ sized to max 8, runtime activeLen_/pinLength_
drives arc loop, dots, verify; full-capacity zeroization preserved.
- AuthEntryUI::setPinLength seam (no-op for keyboard passphrase).
- Persist as NVS 'pin_len' (kleidos ns); load at boot, apply at PIN_ENTRY.
- Change-PIN wizard: after verifying the current PIN, arc devices pick the new
length (dropdown component + settings-picker input model) before entering the
new PIN; the new length is persisted on a successful re-encrypt.
- Settings SECURITY: PinLength row shows current length + launches change-PIN
(arc devices only; compiled out on keyboard).
- i18n: SetPinLength / PinChangeLength (5 langs).
- Tests: change-PIN 6/8-digit round-trip, PBKDF2 length-agnostic 6/8 derive,
settings-nav SECURITY count + PinLength action.
Claude-Session: https://claude.ai/code/session_01SLSU3WoYEyX1J7qWXxmyKo
feat(pin): configurable 4/6/8-digit PIN length (runtime, persisted, change-PIN)
Make the timing-arc PIN length a runtime, per-device setting (default 4,
selectable 4/6/8) so users can raise on-device brute-force resistance
(~2 s/attempt: 4 ~5.5 h, 6 ~23 days, 8 ~years). Closes the practical side of
the counter-rollback residual; the crypto is unchanged (length-agnostic
PBKDF2 takes ptr+len).
- pin_policy: kPinLengthDefault/Max/Options + isValidPinLength/clampPinLength.
- PinEntryUI/renderer: digits_ sized to max 8, runtime activeLen_/pinLength_
drives arc loop, dots, verify; full-capacity zeroization preserved.
- AuthEntryUI::setPinLength seam (no-op for keyboard passphrase).
- Persist as NVS 'pin_len' (kleidos ns); load at boot, apply at PIN_ENTRY.
- Change-PIN wizard: after verifying the current PIN, arc devices pick the new
length (dropdown component + settings-picker input model) before entering the
new PIN; the new length is persisted on a successful re-encrypt.
- Settings SECURITY: PinLength row shows current length + launches change-PIN
(arc devices only; compiled out on keyboard).
- i18n: SetPinLength / PinChangeLength (5 langs).
- Tests: change-PIN 6/8-digit round-trip, PBKDF2 length-agnostic 6/8 derive,
settings-nav SECURITY count + PinLength action.
Claude-Session: https://claude.ai/code/session_01SLSU3WoYEyX1J7qWXxmyKo
feat(pin): configurable 4/6/8-digit PIN length (runtime, persisted, change-PIN)
Make the timing-arc PIN length a runtime, per-device setting (default 4,
selectable 4/6/8) so users can raise on-device brute-force resistance
(~2 s/attempt: 4 ~5.5 h, 6 ~23 days, 8 ~years). Closes the practical side of
the counter-rollback residual; the crypto is unchanged (length-agnostic
PBKDF2 takes ptr+len).
- pin_policy: kPinLengthDefault/Max/Options + isValidPinLength/clampPinLength.
- PinEntryUI/renderer: digits_ sized to max 8, runtime activeLen_/pinLength_
drives arc loop, dots, verify; full-capacity zeroization preserved.
- AuthEntryUI::setPinLength seam (no-op for keyboard passphrase).
- Persist as NVS 'pin_len' (kleidos ns); load at boot, apply at PIN_ENTRY.
- Change-PIN wizard: after verifying the current PIN, arc devices pick the new
length (dropdown component + settings-picker input model) before entering the
new PIN; the new length is persisted on a successful re-encrypt.
- Settings SECURITY: PinLength row shows current length + launches change-PIN
(arc devices only; compiled out on keyboard).
- i18n: SetPinLength / PinChangeLength (5 langs).
- Tests: change-PIN 6/8-digit round-trip, PBKDF2 length-agnostic 6/8 derive,
settings-nav SECURITY count + PinLength action.
Claude-Session: https://claude.ai/code/session_01SLSU3WoYEyX1J7qWXxmyKo
feat(pin): configurable 4/6/8-digit PIN length (runtime, persisted, change-PIN)
Make the timing-arc PIN length a runtime, per-device setting (default 4,
selectable 4/6/8) so users can raise on-device brute-force resistance
(~2 s/attempt: 4 ~5.5 h, 6 ~23 days, 8 ~years). Closes the practical side of
the counter-rollback residual; the crypto is unchanged (length-agnostic
PBKDF2 takes ptr+len).
- pin_policy: kPinLengthDefault/Max/Options + isValidPinLength/clampPinLength.
- PinEntryUI/renderer: digits_ sized to max 8, runtime activeLen_/pinLength_
drives arc loop, dots, verify; full-capacity zeroization preserved.
- AuthEntryUI::setPinLength seam (no-op for keyboard passphrase).
- Persist as NVS 'pin_len' (kleidos ns); load at boot, apply at PIN_ENTRY.
- Change-PIN wizard: after verifying the current PIN, arc devices pick the new
length (dropdown component + settings-picker input model) before entering the
new PIN; the new length is persisted on a successful re-encrypt.
- Settings SECURITY: PinLength row shows current length + launches change-PIN
(arc devices only; compiled out on keyboard).
- i18n: SetPinLength / PinChangeLength (5 langs).
- Tests: change-PIN 6/8-digit round-trip, PBKDF2 length-agnostic 6/8 derive,
settings-nav SECURITY count + PinLength action.
Claude-Session: https://claude.ai/code/session_01SLSU3WoYEyX1J7qWXxmyKo