Skip to content

feat(device): add configurable automatic lock and Vault Format 2 (#140) - #152

Merged
miso-develop merged 30 commits into
mainfrom
task/140-device-auto-lock
Sep 16, 2026
Merged

miso-develop merged 30 commits into
mainfrom
task/140-device-auto-lock

Conversation

@miso-develop

@miso-develop miso-develop commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Parent spec: #137
Closes #140

Summary

  • add Vault Format 2 PT2/AAD2 support while preserving byte-for-byte Format 1 read/runtime compatibility
  • enforce F1->F1, F1->F2, F2->F2 canonical update compatibility and reject F2->F1 downgrade / unknown newer formats fail-closed
  • derive authenticated auto_lock_days from the Vault, track the original monotonic UNLOCKED start, and enforce 1..31-day continuous-session expiry through the explicit Lock security boundary
  • advertise supported_vault_formats: [1, 2] in Protocol v2 hello without changing Protocol 2 or Storage Schema 2
  • add native/interoperability/runtime/security-contract coverage for Format 1/2 and automatic-lock boundaries

Review rework

Review finding from Issue #140 comment 5701446229 is fixed at exact head 1375cac4f6a2c412d776879a424f9a59806fdacf.

  • VMK re-key boundary still destroys the resident VMK immediately and transitions Runtime to LOCKED.
  • Re-key now retains only bounded non-secret automatic-lock continuity state (auto_lock_days and the original monotonic unlocked_since_ms) while VMK access is absent.
  • Successful authenticated re-key installs the new VMK and candidate policy without restarting the continuous-UNLOCKED lifetime; expiry remains based on the original T0.
  • If the original deadline is already reached when re-key commits, Protocol v2 immediately routes through the same lock_security_boundary() used by automatic expiry and explicit device.lock.
  • Failed/ambiguous re-key remains fail-closed; post-commit ambiguity clears unlock-session state and enters the existing error boundary.
  • Existing physical confirmation/session flow, pending VMK zeroization, Vault Format transition/downgrade guards, and Protocol 2 / Storage Schema 2 contracts are unchanged.

Verification

Exact review head: 1375cac4f6a2c412d776879a424f9a59806fdacf

  • Foundation / native Vault + runtime tests — Foundation #752 SUCCESS
  • VMK re-key boundary regression, including T0 preservation — Foundation #752 SUCCESS
  • Vault runtime security contract and Protocol-v2 contracts — Foundation #752 SUCCESS
  • ESP-IDF 5.5.5 build/package and dependency lockfile validation — Foundation #752 SUCCESS
  • Security workflow including automatic-lock Protocol-v2 contract — Security #755 SUCCESS
  • Issue 117 Screen Snapshot diagnostics profile — fix(web): support current Google Authenticator migration exports #129 SUCCESS

main advanced through Web PR #150 while this rework was running. PR #150 changed Web-only files; there is no changed-file overlap with this Device rework, and PR #152 is mergeable against current main.

Security review

  • No real secrets, credentials, QR migration data, user Recovery Packages, private dumps, or secret-bearing logs/artifacts are included.
  • SECURITY.md and, when Vault/unlock/recovery behavior changes, docs/SECRET_VAULT.md were reviewed.
  • VMK, Passphrase-derived KEK, BUK, unlock/session keys, plaintext TOTP/Wi-Fi data, and decrypted Vault material are neither persisted nor logged outside their approved boundary.
  • Browser persistence/export and crash/core/RAM/NVS/Flash dump paths were reviewed when applicable.
  • Any security-sensitive path changed here was reviewed for logging, persistence, export, network, lock/unlock, recovery, and update/reset regressions.

Implementation scope is Device only. Web #141 and Device UI #148 are intentionally unchanged. Implementation Agent will not merge this PR.

Copy link
Copy Markdown
Owner Author

HANDOFF

FROM: implementation
TO: review
DOMAIN: device
ISSUE: #140
PR: #152
STATE: READY_FOR_REVIEW
BLOCKING: no

Exact review head: 579347e7e9a53884425b7b405a32ed8f772f8cf1

Foundation #743, Security #746, and Issue 117 Screen Snapshot #123 are all SUCCESS on this head. PR is Ready for Review and remains open/unmerged.

Please independently review against #140 / Decision #138 and record the Review disposition.

@miso-develop miso-develop left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review disposition: REWORK_REQUIRED

Reviewed exact head 579347e7e9a53884425b7b405a32ed8f772f8cf1 independently against Issue #140 and Decision #138.

Blocking finding — VMK re-key restarts the automatic-LOCK lifetime

Issue #140 requires one fixed maximum continuous UNLOCKED lifetime and explicitly requires that user/device/Web activity not restart or extend that timer.

At this head, the normal vault.update path correctly preserves the original unlocked_since_ms_, but the VMK re-key path does not:

  • Runtime::enter_vmk_rekey_boundary() aliases enter_recovery_boundary(), which clears unlock-session state and enters LOCKED.
  • Runtime::rekey_encrypted_vault(...) then calls clear_unlock_session_state() and begin_unlock_session(policy, now_ms) after the re-keyed generation commits.
  • CanonicalVmkSink::install_rekeyed_vault(...) supplies the current monotonic now_ms.

Therefore a Web-originated VMK rotation resets unlocked_since_ms_ to the re-key completion time. Example: with a 1-day policy, unlock at T0 and rotate the VMK at T0+23h; the implementation gives another 24h from re-key completion instead of retaining the original T0 maximum-lifetime origin.

This violates the Task contract that Web activity must not restart/extend the automatic LOCK lifetime.

Required completion condition

Preserve the original automatic-LOCK session origin/policy across a successful VMK re-key so the operation cannot extend the active session lifetime. Add a regression that starts an enabled session at T0, performs VMK re-key later in that same session, and proves expiry is still calculated from T0 (including an already-due case if applicable).

Do not weaken the existing VMK-rekey security boundary/zeroization, physical confirmation, Vault Format transition, or fail-closed behavior while fixing this.

Other reviewed areas

No additional blocking finding was identified in the reviewed Format-1/Format-2 framing/AAD separation, format-transition matrix, unknown-format fail-closed handling, monotonic normal expiry, committed setting-change handling, shared explicit/automatic Lock boundary, or exact-head CI evidence.

Exact-head CI independently confirmed: Foundation #743 SUCCESS; Security #746 SUCCESS; Issue 117 Screen Snapshot #123 SUCCESS.

@miso-develop
miso-develop marked this pull request as draft September 16, 2026 17:19
@miso-develop
miso-develop marked this pull request as ready for review September 16, 2026 17:32

Copy link
Copy Markdown
Owner Author

HANDOFF

FROM: implementation
TO: review
DOMAIN: device
ISSUE: #140
PR: #152
STATE: READY_FOR_REVIEW
BLOCKING: no

Exact head: 1375cac4f6a2c412d776879a424f9a59806fdacf

Review finding 5701446229 is fixed: successful VMK re-key no longer restarts the automatic-LOCK lifetime. The re-key boundary still wipes the resident VMK and enters LOCKED, preserves only non-secret T0/policy continuity, and successful re-key applies the authenticated candidate policy against the original T0. An already-reached deadline immediately routes through the existing shared lock_security_boundary().

Exact-head CI: Foundation #752 SUCCESS; Security #755 SUCCESS; Issue 117 Screen Snapshot #129 SUCCESS. Foundation includes VMK re-key/runtime/Protocol regressions and ESP-IDF 5.5.5 build/package/lockfile validation.

Please independently review this exact head. Implementation must not merge.

@miso-develop miso-develop left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review disposition: READY_FOR_INTEGRATION

Independent re-review completed at exact head 1375cac4f6a2c412d776879a424f9a59806fdacf against Issue #140 / Decision #138 and the prior blocking finding recorded in Issue #140 comment 5701446229.

Prior blocker resolution

The VMK re-key path no longer restarts the automatic-LOCK lifetime:

  • Runtime::enter_vmk_rekey_boundary() requires an active unlocked session, wipes the resident VMK immediately, and moves Runtime to LOCKED while preserving only the bounded non-secret automatic-lock policy/original monotonic session origin.
  • Runtime::rekey_encrypted_vault() validates and atomically commits the candidate envelope, installs the new VMK and authenticated candidate policy, and deliberately does not call begin_unlock_session(...) or replace unlocked_since_ms_; successful re-key therefore retains the original T0.
  • Re-key failure paths keep Runtime locked without restoring the old resident VMK. Post-commit ambiguity enters the existing error/clear boundary.
  • After successful vault.rekey, Protocol v2 immediately reevaluates runtime_.automatic_lock_due(now_ms) and routes an already-due session through the same lock_security_boundary() used by automatic expiry and explicit device.lock.

The new regressions cover a 1-day session re-keyed immediately before expiry, proving expiry remains based on T0, plus the exact-deadline case. Source-contract coverage also verifies that the VMK re-key boundary is the only trust-root boundary retaining T0/policy and that normal Lock/recovery/fatal paths still clear the complete unlock-session state.

Regression / security review

No new blocking or non-blocking code finding was identified. The rework preserves the previously reviewed PT1/AAD1 and PT2/AAD2 compatibility, F1/F2 transition rules and F2->F1 downgrade rejection, unknown-format fail-closed behavior, monotonic timer basis, full explicit/automatic Lock cleanup boundary, physical-confirmation/session flow, pending-VMK zeroization, Protocol 2, and Storage Schema 2.

Verification

Independently confirmed for exact head 1375cac4f6a2c412d776879a424f9a59806fdacf:

  • Foundation #752: SUCCESS, including VMK re-key boundary regression, Vault runtime security contract, Protocol v2 contracts, ESP-IDF 5.5.5 build/package, CI distribution validation, and dependency-lock validation.
  • Security #755: SUCCESS.
  • Issue 117 Screen Snapshot #129: SUCCESS.
  • PR #152 remains open, non-draft, unmerged, and currently reports mergeable=true / mergeable_state=clean.

Current main advanced after the exact-head pull-request CI merge ref was created. The newer main delta consists of the merged Web automatic-LOCK work and .agent contract updates; it has no Device/product-file overlap with this rework. Because Foundation #752 was evaluated against the earlier base merge ref, Integration must still perform its normal latest-main/check/dependency verification before merge. This is an integration-readiness note, not a Review blocker.

@miso-develop
miso-develop merged commit 5a0242d into main Sep 16, 2026
5 checks passed
@miso-develop
miso-develop deleted the task/140-device-auto-lock branch September 16, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task][Device] Implement configurable automatic LOCK policy

1 participant