Ctrl K
ComunidadGuías…

docs/backup-maintenance.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Backup maintenance

Keep an independent backup before local repairs. Do not delete conflicting
files, temporary siblings, or the state database to make a warning disappear.

## Choose the operation

| Need | Operation | What can change |
| --- | --- | --- |
| Inspect recorded progress | `kei status` | No repair |
| Check recorded bytes | `kei verify --checksums` | Integrity diagnostics, not restoration |
| Preview missing/truncated state | `kei reconcile --dry-run` | No repair-row changes; owned-state opening can still migrate the database |
| Queue missing/truncated files | `kei reconcile` | SQLite state, not media |
| Replace a recorded truncated file | `kei sync --repair-truncated` | Verified media replacement with explicit consent |
| Refresh provider metadata | `kei sync --refresh-metadata` | Catalogue plus configured local outputs |
| Replace capture timestamps | `kei sync --refresh-metadata --repair-capture-timestamps` | Supported embedded timestamps, including camera values |
| Change folder layout | Edit path configuration, then `kei sync` | Verified local copies; old copies remain |

Automatic path reconciliation after configuration changes is separate from the
`reconcile` integrity command. Neither is a general container-corruption repair.

## Refresh catalogue and configured outputs

Use a separate repair configuration that preserves your existing `data_dir`,
credentials, and download directory. Remove the `albums` and `smart_folders`
keys entirely, even when they contain `all` or `none`: explicit selectors reject
this repair. Also remove date bounds and `recent`/`recent_scope`. This selection
covers all visible libraries and enables the unfiled pass:

```toml
[filters]
libraries = ["all"]
unfiled = true
media = ["photos", "videos", "live-photos"]
```

Choose the libraries you intend to repair. Do not add one-run date or recent
filters. Then run:

```sh
kei sync --config /path/to/repair.toml --refresh-metadata
```

The command refreshes every downloaded version encountered in those libraries
before current resolution, filename, or Live Photo download policy is applied.
It does not download media again. Embedded and sidecar changes follow the
configured metadata writers. Disable embedded outputs if media bytes must stay
unchanged; disable sidecar output too if no local metadata should change.

This is one-shot even when the TOML file sets a watch interval. It rejects
`--dry-run`, `--retry-failed`, `--only-print-filenames`, `--recent`, narrowing
selection, and `service run`. See [Metadata output](metadata.md) for automatic
bounded capture repair, which is different from this explicit full sweep.

### Replace capture timestamps

First enable `metadata.set_exif_datetime = true` in the repair configuration.
Then explicitly authorize replacement:

```sh
kei sync --config /path/to/repair.toml --refresh-metadata --repair-capture-timestamps
```

This can overwrite camera-supplied timestamps. It writes a supported
capture-local timestamp with its matching Apple offset. It requires usable
offset evidence and recorded file/checksum evidence. Unknown provenance,
changed bytes, or unsupported layouts can leave durable repair work pending.
Prepared-output receipts allow a later explicit repair to finish interrupted
state finalization without trusting unrelated bytes. Do not promise that every
historical file can be repaired. Ordinary writes preserve native timestamps.

## Repair a truncated file

Inspect before changing state:

```sh
kei reconcile --dry-run
kei reconcile
kei sync --repair-truncated
```

Reconcile checks recorded paths and metadata-aware sizes, then marks missing or truncated downloads for retry. It reads media and writes repair rows unless `--dry-run` is set. Even a preview opens owned state through the migration-capable opener, so take the cold backup before inspection with a newer binary. The opt-in periodic full reconciliation walk only warns; a separate automatic bounded pre-cycle probe can mark missing/truncated rows failed.

Only explicit repair may replace an existing recorded truncated file. It
requires the durable truncation marker, verifies the new download and configured
metadata writes, and checks the old fingerprint before guarded replacement.
Linux filesystems that reject atomic exchange use the journaled fallback
shown in [Guarded publication](metadata.md#guarded-publication).
A changed target remains a failure rather than permission to overwrite it.
Normal downloads and missing-file retries keep no-overwrite publication.

Truncated-file repair is one-shot and rejects `service run`, `--dry-run`,
`--only-print-filenames`, and `--refresh-metadata`. Unlike metadata refresh,
it can use your current selection. Files excluded by that selection are not a
promise of completed repair. Inspect the result before resuming a service.

## Change the backup layout

Path-setting changes reconcile recorded media through verified local copying.
Old sources remain. Ordinary copies receive capture mtime; a safe same-path
change between equivalent relative and absolute root spellings only changes
catalogue spelling, preserving mtime and existing or absent sidecars.

Eligibility changes, such as date bounds, do not by themselves relocate every
file. Active provider checkpoints remain while replacement inventory proof is
built. Path reconciliation also preserves checkpoints rather than clearing them.

Reconciliation uses retained directory handles, no-follow traversal, checked
file identity, exclusively created temporary files, and no-overwrite publication.
It rejects symlinks, non-regular leaves, unsafe/replaced parents, `..` components,
and a distinct destination hard-linked to its source. Ordinary relative roots
remain supported. These restrictions describe reconciliation, not every command.
On Unix, temporary copies start owner-only; completed copies receive source
permissions. Ambiguous temporary entries remain for inspection.

With sidecars enabled, a valid source packet is copied byte-for-byte, including
custom fields and ownership markers. A missing packet is generated by the normal
metadata planner. Source-read failure stops before an incomplete packet lands.
Migration does not upgrade an existing packet or create original GPS provenance.

Reservations distinguish library, asset, rendition, and provider content.
Equivalent path spellings share ownership. Another owner's reservation can
select a stable identity-suffixed destination. Changed provider content can
receive a new reservation while old and unselected renditions remain protected.
Conflicting bytes never authorize overwrite or a fresh filename on every retry.
Ordinary download collision naming remains unchanged.

Catalogue finalization follows capture mtime, required sidecar work, and final
input validation. A metadata or state-write failure keeps pending work and its
selected destination. A safe retry can finish without copying media again.

### Recover from a blocked move

1. Stop the affected worker and preserve its state and reported conflicting
   paths. Inspect identities and bytes without modifying the originals.
2. Check configured roots, permissions, parent directories, and the reported
   media or sidecar conflict. Remove `..` from reconciliation roots.
3. If a conflicting entry must be moved, first back it up and choose an explicit
   destination outside the planned path. Do not apply blanket deletion commands.
4. Retry the same configuration and inspect the result. The old catalogue path
   remains until all required finalization succeeds.

Blocking failure skips that library's normal source/download/adoption pass and
withholds its checkpoint and the aggregate database precheck token. Selected
smart-folder reconciliation still has the limitation in #770.

## Interpret recovery evidence

A policy-excluded row is not provider-deleted. Pending retries use targeted
provider revalidation and durable identity evidence, with full-enumeration
fallback where needed. Unknown or transient responses retain retry evidence.

Complete enumeration proof plus durable exact retry work can permit zone-token
progress after a transfer failure. Identity, grouping, or state failures without
recovery proof cannot. Aggregate database prechecks have stricter clean-cycle
gates. Zero failed downloads does not establish successful metadata, state,
enumeration, or checkpoint work.

Provider MMCS identity, original-download SHA-256, post-metadata local SHA-256,
and verified `source_checksum` provenance serve different purposes. Historical
download hashes are not proof of unmodified source bytes. Adoption/import have
evidence limits; integrity commands cannot prove completeness against iCloud or
restore damaged media. Never remove temporary files by suffix and age alone:
cleanup requires durable ownership evidence.

## Unresolved provider identities

If logs show `asset_delta_hydration_incomplete`, keep the state database and
media. Kei retains the provider checkpoint so a later cycle can retry the
unresolved records. Other valid assets can still download. Do not reset state
or use a metadata refresh to bypass this guard.

For valid sparse-share records, kei retains per-source retry evidence across
restarts. An unchanged unresolved lookup retries after one hour, then doubles
the delay up to 24 hours. Each library execution selects up to 100 due sparse
source lookups. Exact saved source/master mappings can recover immediately;
malformed or changed evidence does not reuse the negative result. `kei status`
shows how many retained sparse records are unresolved and deferred. A deferred
lookup does not mean that the record was skipped safely or deleted. These
limits reduce repeated lookups; they do not repair a missing provider identity.

Ambiguous metadata-capture identities also retain a retry schedule. Unchanged
ambiguity retries after one hour, doubling up to 24 hours. Changed saved identity
or rendition evidence becomes eligible immediately. Status reports unresolved
identities and deferred retries separately from failed repair attempts.
Deferral keeps the capture revision and checkpoint pending; it is not recovery.

Stable v0.26.0 uses schema 36. Even `kei status` can migrate an owned database. Stop all workers and take a matched cold backup of configuration/state, SQLite companions and media/sidecars before upgrading. Older binaries cannot open schema 36. Rollback requires the complete matched old set and retained old binary. Do not reset state or lower its schema version. See the [v0.26.0 upgrade guide](v0.26.0-upgrade.md).

Kei marks unresolved asset identity cycles incomplete. Status
remains unsafe across restarts and successful syncs in other libraries until
the affected checkpoint can advance safely. Health does not update
`last_success_at` for incomplete cycles. A deployment that previously looked
healthy can therefore start reporting unhealthy without a new transfer error.

For a diagnostic retest, disable automatic restarts driven by `/healthz`.
Keep health monitoring enabled. Do not use this sync-health endpoint as a
Kubernetes liveness probe during the retest. Repeated provider failures can
produce HTTP 503 while the process is still running and able to retry.

Record `kei --version`, the Docker image ID when applicable, `kei status`,
health output, and the aggregate `Asset identity lookup` log lines from one
cycle. Include whether the accounts use a Shared Photo
Library. Redact account details and local paths from other logs. Do not upload
the state database, session files, or raw provider responses.

The diagnostics do not establish why Apple omitted an identity. Ambiguous
metadata-capture matches are a separate condition and remain pending.

## Legacy preservation and hardlinks

Legacy preservation normally refuses files with multiple hard links. The TOML-only
`[download].legacy_preservation_allow_hardlinks = true` setting waives that
link-count check for legacy originals and qualifying current outputs, including
sidecars. When used, it emits one warning per library cycle with the number of
distinct evidence paths whose shared-link check was waived. It assumes you coordinate external tools so they do not change linked
contents, metadata, or kei-managed names during the operation.

This setting does not make kei read-only: distinct original and current paths
can share an inode, and existing identical-file reuse can set timestamps through
aliases even when metadata output is disabled. Repair and recovery behavior is
unchanged. Other preservation checks still apply. Broader hardlink support remains
open in [#884](https://github.com/rhoopr/kei/issues/884).