synology_apm_repo.sdk.api.key_manager module¶
KeyManager: the encryption-key state machine for one opened
Repository, part of the Repository Layer (the Session/
Repository/Catalog split CLI/TUI code imports directly). Owns
exactly the state KeyStatus depends on (keys/key_verification/
encrypted) and the pure KeyStatus resolution logic.
- class synology_apm_repo.sdk.api.key_manager.KeyStatus(value)¶
Bases:
EnumThe same four states the
doctorcommand reports, as a proper type instead of a raw dict.NOT_ENCRYPTED/VERIFIED/INVALIDare only reachable once this repository is known to be encrypted (or known not to be) — never a guess.NO_KEY_PROVIDEDmeans “encrypted, no key tried yet”, not “unknown either way” —Session.discover/Session.openalready resolve that up front for every repository opened without a key (seeKeyManager.is_encrypted). The one caseNO_KEY_PROVIDEDcan still mean “genuinely couldn’t tell” is that resolution itself coming backNone— the repository’s own encryption-key record being entirely absent, which shouldn’t happen for a properly initialized repository.- NO_KEY_PROVIDED = 'no_key_provided'¶
- NOT_ENCRYPTED = 'not_encrypted'¶
- VERIFIED = 'verified'¶
- INVALID = 'invalid'¶
- class synology_apm_repo.sdk.api.key_manager.KeyManager(keys, key_verification, *, encrypted=None)¶
Bases:
objectOne
Repository’s own encryption-key state: the pure state itself, not theverify()/adopt()/record()orchestration around it (Repository.set_key()’s job).- property keys: KeyMaterial | None¶
Read by
Repository._open_catalog_resourcesto open/reopen each catalog’s ownDedupRepounder whichever key is currently adopted.Noneuntil key material has actually been supplied — at construction, or via a lateradopt()(only reached once aset_key()attempt verifiesok; a rejected attempt never touches this).
- property verification: KeyVerification | None¶
The GCM-unwrap verification result, or
Nonewhen no key was ever provided.statuscollapses this to one of four coarse states; this is the detail behindINVALID/VERIFIED(gcm_ok) — and, since GCM tag success is already cryptographic proof the key unwraps this repository’s one wrapped-VaultKey record (which never changes after first initialization), already the whole answer to “is this key correct” on its own.
- property is_encrypted: bool | None¶
Whether this repository is actually encrypted — a plain, no-I/O property, resolved from
encrypted(seeKeyStatus) or, once a key has been tried,not keys.is_no_encryption.Trueeven when the key turns out to be wrong — “is encrypted” and “is the key correct” are different questions; seeverificationfor the latter.Noneonly when the underlying probe genuinely couldn’t tell (the repository’s own encryption-key record entirely absent) — never once a key has been tried.
- require_verified()¶
Raise before any catalog I/O if this repository is confirmed encrypted and its key hasn’t been verified yet — gating this at the SDK level is what lets every consumer (CLI, TUI, a smoke-test tool, …) get it for free, without an equivalent client-side check of its own.
Deliberately narrower than
status is KeyStatus.NO_KEY_PROVIDEDalone: that state also covers the rare caseis_encrypteditself couldn’t resolve toNone. Blocking on a genuinely unknown encryption status would be presumptuous — this only blocks onceis_encryptedis confidentlyTrue.Never called by
Repository.catalogs()before it lists what’s found: those rows are plaintextconnection_configdata needing no key, so the key prompt only appears once the user actually opens a catalog and itsworkloads()/versions()call this instead.
- async verify(store, layout, key_string)¶
Builds
KeyMaterialfromkey_stringand verifies it againstlayout’s own key-probe location. Pure — doesn’t touch this manager’s own state;Repository.set_key()decides what happens with the result (adopt()/record()below), since that decision also depends on whether every already-open catalog successfully reopens under the new key, which this method knows nothing about.Deliberately cheap — no Pool scan; see
dedup.keysfor why the GCM-unwrap layer alone is sufficient.
- adopt(keys)¶
Commits
keysas this manager’s own key material immediately — called byRepository._reopen_catalogs_under_new_keyright before it starts reopening each already-open catalog, soRepository._open_catalog_resourcespicks up the new key for those reopens (and for any not-yet-opened sibling’s own eventual first open) rather than the stale one. Deliberately leavesstatus/verificationuntouched —record()updates those once the reopen sweep, whose own per-catalog success/failure has no bearing on whether the key itself was correct, has run to completion.
- record(keys, verification)¶
Records
verification’s outcome and recomputesstatus— called byRepository.set_key()once its own reopen sweep (ifverification.oktriggered one) has finished, regardless of whether every catalog reopened cleanly:statusmust still distinguish “never tried” (NO_KEY_PROVIDED) from “tried and failed” (INVALID) even when a rejected key never reachedadopt()at all, sokeys— the just-tried key material, not necessarilyself.keys— is taken as an explicit parameter rather than read back off this instance.