Skip to content

fix(kms-auth)!: make DstackApp allowAnyDevice cover every app epoch - #1568

Merged
kvinwang merged 2 commits into
nextfrom
fix/allow-any-device-global
Nov 12, 2026
Merged

kvinwang merged 2 commits into
nextfrom
fix/allow-any-device-global

Conversation

@kvinwang

@kvinwang kvinwang commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Which hosts may run an app is not a property of a key generation, and a per-epoch switch is easy to misuse: restricting the current epoch leaves any older row that allows any device open to every host, which can still fetch that epoch's keys.

  • setAllowAnyDevice(bool) replaces setAllowAnyDeviceAtEpoch(s) and allowAnyDeviceAtEpoch. Apps predating app epochs already have that selector, so Manage.s.sol:SetAllowAnyDevice uses it on both kinds and takes no epoch.
  • Device ID rows stay per epoch; the check is allowAnyDevice || deviceRow[epoch][deviceId].
  • Drop the unreleased _allowAnyDeviceByEpoch slot (gap +1).
  • IAppEpochManagement swaps the two epoch setters for setAllowAnyDevice; its interface ID becomes 0xc65f31b6.

Breaking only for unreleased API. dstack-auth's allowAnyDevice is already global.

Tests: forge clean && forge test --ffi (111 passed); Halmos (FOUNDRY_DYNAMIC_TEST_LINKING=false): DstackAppSymbolicTest 5/5, DstackAppEpochSymbolicTest 9/9, DstackKmsEpochSymbolicTest 13/13.

Which hosts may run an app is not a property of a key generation, and a
per-epoch switch is easy to get wrong: restricting the current epoch leaves
any older row that allows any device open to every host, which can still
fetch that epoch's keys. Make allowAnyDevice one switch again.

- setAllowAnyDevice(bool) replaces setAllowAnyDeviceAtEpoch(s) and the
  allowAnyDeviceAtEpoch getter. It is the selector apps predating app
  epochs already have, so Manage.s.sol SetAllowAnyDevice calls it on either
  kind and takes no epoch.
- Device ID rows stay per epoch. The decision is now allowAnyDevice or the
  selected epoch's device row.
- Drop the unreleased _allowAnyDeviceByEpoch slot; the gap grows by one.
- IAppEpochManagement swaps the two epoch setters for setAllowAnyDevice; its
  interface ID becomes 0xc65f31b6.

BREAKING CHANGE: unreleased only: setAllowAnyDeviceAtEpoch(s),
allowAnyDeviceAtEpoch and the IAppEpochManagement interface ID.

Signed-off-by: Kevin Wang <wy721@qq.com>
- Correct the AllowAnyDeviceSet NatSpec and the epoch-zero-only notes in
  app-key-epochs.md, which allowAnyDevice no longer follows.
- SetAllowAnyDevice refuses APP_EPOCH and FROM_/TO_APP_EPOCH instead of
  ignoring them, since it changes every epoch.
- Check the legacy-equals-epoch-0 Halmos property with a symbolic
  allowAnyDevice, and that an upgraded any-device app stays open to unlisted
  devices at later epochs.
- Tidy spec and formal-verification wording.

Signed-off-by: Kevin Wang <wy721@qq.com>
@kvinwang
kvinwang merged commit f811fbe into next Nov 12, 2026
22 checks passed
@kvinwang
kvinwang deleted the fix/allow-any-device-global branch November 12, 2026 10:38
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.

1 participant