All checks were successful
check / check (pull_request) Successful in 2m13s
ListSnapshots built its table entirely from the local SQLite index. The only remote access, reportRemoteDrift, was gated on AgeSecretKey being non-empty — so on a correctly configured host, which by design holds no private key, `snapshot list` never contacted the destination store at all. A user who lost their local index could not see their own backups, and the "<remote only>" cell the README documents was unreachable dead code. The listing is now the union of the local index and the destination store, with no age_secret_key gate. The manifest is unencrypted, so a host holding only the public key can enumerate what it has backed up: one streamed listing of the metadata/ prefix, then a manifest read per remote key the local index does not already account for, bounded by maxRemoteOnlyRows and run with bounded concurrency. A remote-only snapshot's hostname and name are deliberately NOT recovered. RemoteSnapshotKey is one-way and the manifest stores the hash rather than the human ID, so they are recoverable only from the encrypted per-snapshot database; making them readable from remote storage would undo a deliberate privacy property (#81). Such rows are labelled "<remote only:<12 hex chars>>", carry the real timestamp and compressed size from the manifest, and show "<remote only>" in the two columns that genuinely require the local index. --json carries the full 64-character key in remote_key, and remote_present distinguishes seen (true), missing (false) and not-listable (null). Local records with no counterpart on the destination store are still surfaced as drift, and the remediation hint now names `vaultik prune`, which exists, rather than `vaultik snapshot cleanup`, which does not: CleanupLocalSnapshots is already wired as prune's first pass, and re-adding a second entry point would undo the CLI consolidation. reportRemoteDrift collapses. Its remote-only half is subsumed by the table — those snapshots are rows now, not a footnote count — and its local-only half reads the merge ListSnapshots already computed, so the command lists the destination exactly once per invocation. An unreachable destination stays a warning plus local-only output and a zero exit code, as the doc comment always claimed. In --json mode that warning goes to stderr, because the logger and the UI writer both emit on stdout and would otherwise corrupt the document. Tests cover remote-only rendering, the no-private-key property (a storer that counts prefix listings and records fetched keys, asserting the destination is read and nothing encrypted is touched), graceful degradation on an unreachable destination in both output modes, local-only drift, and an unreadable manifest not hiding other snapshots.