synology_apm_repo.sdk.catalog.version module

Version: one db/copy_target_version row (+ _meta when present), its own meta-availability checks, and open_target_db() — the one place this layer does real decrypt work (shared by the Unit Layer’s Device and FS providers). Display/status extraction (_version_epoch/_version_display_name) is a first-class output here too: CLI/TUI show only display_name/subtitle/attrs in the default (non-diagnostic) mode, so this can’t be an afterthought bolted on later.

Encrypted connections: version_spec itself is AES-256-CTR ciphertext (whole-string, standard base64) whenever the connection has a vault key, decrypted with the same DEK as chunk-pool/aHlT encryption before parsing — see parse_version_spec, also used by units.saas.object_name_index. Not documented in docs/ at all (neither this column’s schema nor its encryption).

class synology_apm_repo.sdk.catalog.version.VersionMeta(target_meta_path, meta_filenames, status)

Bases: object

A version’s _meta sidecar, when present: its directory, the filenames it holds, and its own status code.

target_meta_path: str
meta_filenames: tuple[str, ...]
status: int
class synology_apm_repo.sdk.catalog.version.Version(version_id, version_uid, workload_id, connection_config_id, target_type, target_id, saas_stream_uuid, saas_snapshot_uuid, saas_version_id, deleted, display_name, meta)

Bases: object

One db/copy_target_version row (+ _meta when present).

version_id: VersionId
version_uid: VersionUid
workload_id: WorkloadId
connection_config_id: ConnectionConfigId
target_type: str
target_id: TargetId
saas_stream_uuid: StreamUuid
saas_snapshot_uuid: SnapshotUuid
saas_version_id: SaasVersionId
deleted: bool
display_name: str
meta: VersionMeta | None
synology_apm_repo.sdk.catalog.version.resolve_meta_filename(meta, name, *, ref=None)

Confirm name (e.g. "target.db") is one of this version’s own meta_filenames — the copy_meta_file/<dir> directory’s authoritative, write-time-recorded file list (FORMAT-SPEC.md: version-meta-mapping) — and return it unchanged.

Never a directory scan — unlike the dedup layer’s own per-generation files (.buk, db/<name>, …; see storage/seqid.py’s resolve_seq_file), files under copy_meta_file are written once by the backup agent and never rewritten by the dedup layer.

Raises:

NotFoundError – name was never registered for this version.

synology_apm_repo.sdk.catalog.version.resolve_copy_meta_dir(version, repo_root)

The copy_meta_file/<dir> this VM/FS version’s own meta artifacts (target.db, version.db.zst) live under, derived from copy_target_version_meta.target_meta_path joined onto repo_root (empty when a store is rooted directly at the vault dir, non-empty when the repository was discovered from a parent directory — Session.discover).

Raises:

NotFoundError – version has no copy_target_version_meta row at all (no meta directory ever landed for it).

async synology_apm_repo.sdk.catalog.version.open_target_db(repo, version, meta_dir)

Resolve and open <meta_dir>/target.db into an opened SqliteSource — the identical sequence units.device and units.fs each need before going on to interpret target.db’s own tables their own way. May be aHlT-enveloped and have a real -wal/-shm sidecar (FORMAT-SPEC.md: copy_meta_file-layout); SqliteSource. from_enveloped_store handles both. A different addressing scheme than DedupRepo.db’s own db/<name> auto-detection (name-alias resolution plus generation-selection for OBJECT_STORE): copy_meta_file entries are written once by the backup agent and never rotated, so this resolves the physical filename directly against the version’s own recorded meta_filenames instead.

rebuild_target.db (§6.4) is never read through this function.

async synology_apm_repo.sdk.catalog.version.versions(repo, workload, *, include_deleted=False)

Newest-first by real backup time (_version_epoch, the same field/fallback _version_display_name uses, so sort order and displayed timestamp always agree). table.select() carries no ORDER BY of its own — row order is an implementation detail, not a chronological guarantee — so sorting happens here. A version whose timestamp can’t be resolved sorts last, ties broken by version_id descending (the best available recency proxy once the real timestamp is unusable).

class synology_apm_repo.sdk.catalog.version.ParsedVersionStatus(status=None, start_time=None, end_time=None)

Bases: object

version_spec.status, narrowed to exactly the fields _version_epoch/_version_display_name/the browsable-status filter (_BROWSABLE_VERSION_STATUSES) read — a type-checked replacement for passing a raw dict[str, Any] around, so mypy enforces “call _parse_version_status first” as a real requirement instead of a documented-only convention. Field names match version_spec.status’s own JSON keys.

status: object = None
start_time: object = None
end_time: object = None
synology_apm_repo.sdk.catalog.version.parse_version_spec(version_spec_raw, version_uid, vault_key)

Decrypt (whenever vault_key is given) and JSON-parse one copy_target_version.version_spec column value — the shared decrypt-then-parse step this module’s own status filter and units.saas.object_name_index’s connector-recorded index both need.

Decrypts unconditionally whenever vault_key is given, never by probing the raw column first (§5.1: encryption is a per-connection state, not per-row).

Returns None on any failure — undecryptable or unparseable — never raises; each caller applies its own conservative default.