Skip to content

feat(salto): license lifecycle, role listing, PIN-safe modify#18

Merged
jesusVMayor merged 4 commits into
mainfrom
feat/salto-license-lifecycle
Jun 18, 2026
Merged

feat(salto): license lifecycle, role listing, PIN-safe modify#18
jesusVMayor merged 4 commits into
mainfrom
feat/salto-license-lifecycle

Conversation

@jesusVMayor

Copy link
Copy Markdown
Member

Builds on the merged Salto provider (#16) with the lifecycle pieces the PMS integration needs. Salto-only — no change to the base contract or other providers.

Revoke = suspend (per-user license)

Salto bills per subscribed user, so revoke_access no longer deletes: it unsubscribes the guest user (frees the license, disables the PIN) and keeps the user/group/logs. New public delete_grant(ref) does the eventual hard delete, to be called from a retention cron.

Modify keeps the PIN

modify_access patches the time schedule in place (no delete+recreate) so the original PIN stays valid. Salto can't read PINs back, so it returns AccessGrant.pin=None ("unchanged") and the caller keeps its stored PIN. Documented in models.py / base.py.

Roles

role_id is now optional in the constructor and list_roles() exposes the site roles, so the integration can let the operator pick the basic User role (ids are unique per site).

Guards in _do_grant_access

  • Reject a caller-supplied PIN — Salto generates them; custom is premium/unsupported.
  • Reject a missing role_id.

Tests

54 passing (pytest). Added: revoke-suspends, delete_grant (+idempotent), modify pin=None, custom-PIN rejected, role_id required, list_roles.

Salto KS is user-centric and billed per subscribed user, so the grant
lifecycle differs from passcode vendors:

- revoke_access now suspends the guest user (frees the license, disables
  the PIN) instead of deleting; add delete_grant() for the eventual hard
  delete from a retention cron.
- modify_access keeps the same PIN (patches the schedule in place) and
  reports it unchanged via AccessGrant.pin=None, so callers don't wipe the
  stored PIN. Documented across the contract.
- role_id is optional in the constructor and a new list_roles() exposes the
  site roles, so the integration can let the operator pick the basic "User"
  role (ids are unique per site).
- _do_grant_access guards: reject a caller-supplied PIN (Salto generates
  them; custom is premium/unsupported) and a missing role_id.
@jesusVMayor jesusVMayor marked this pull request as ready for review June 16, 2026 13:31
@jesusVMayor jesusVMayor merged commit 8ca2bf2 into main Jun 18, 2026
1 check passed
@jesusVMayor jesusVMayor deleted the feat/salto-license-lifecycle branch June 18, 2026 14:32
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