Checking integrity

Everything Synck stores is identified by a SHA-256 hash of its exact bytes, and every history rule is checkable. Two commands use that to tell you whether a repository is intact. They run the same checks:

Command Checks
synck fsck The repository whose folder you are in
synck repository verify [DIRECTORY] The repository in DIRECTORY, with or without a checkout

Both only read. Neither repairs anything. Their job is to tell you the truth about what is on disk.

$ synck fsck
{"repo_id":"01a17955-e227-774e-bc2c-4e127ae64aea","terminal_repo_seq":4,"commits":4,"items":3,"blobs":3,"bodies":0}
$ synck repository verify launch-project
{"repo_id":"01a174b7-8a7d-74e0-b0d7-81b1dcfa6ccd","terminal_repo_seq":8,"commits":8,"items":4,"blobs":3,"bodies":3}

What they check

In order:

  1. The database file. SQLite’s own integrity and foreign-key checks, the exact expected schema, and well-formed IDs and timestamps.
  2. The history. Every commit and event, for every item type, is re-validated against Synck’s rules: valid parents, unique names, no folder cycles, consistent item sequences. Every commit ID is recomputed from its content.
  3. Current state. Each item’s state is rebuilt from its history and compared with what is stored.
  4. The history index. The index that makes old states fast to read is checked against the history.
  5. Every stored object. Every file version, message body and attachment in the history’s closure is read back, and its size and SHA-256 are compared with what the history recorded. With chunked storage, every chunk is decompressed and checked too, and each file is reassembled before it is hashed.
  6. Named versions. In a repository with a checkout, every named version is replayed against the file history it labels: it must point at a version that already existed, with matching content and size.

On success, the one-line report counts what was verified: the latest commit number, commits, items, file contents (blobs) and message bodies (bodies). See Verify it first for what each number means. On failure, the command stops at the first problem it finds and names it.

Exit codes

Both commands follow the same convention, which makes them easy to use in scripts and scheduled jobs:

Exit status Meaning
0 Verified
2 Integrity problem: the repository is not what its history says it should be
1 The check could not be completed, for example because a file is missing or unreadable, or the repository is busy
$ synck fsck
synck: integrity error: chunk digest mismatch
$ echo $?
2

Treat any non-zero result as “do not rely on this copy” until you know why. Exit status 2 can also come from a mistyped command line, so look at the message as well as the number.

What the checks prove

A passing check proves that the repository is complete and internally consistent. Nothing has been altered, truncated or lost since the history was written, as far as the history itself can tell.

It does not prove who wrote the history, or that an export was authorized. A hash is not a signature. See What verification does and does not prove.

Neither does it replace a backup. A repository that verifies perfectly is still lost when its disk fails.

When a check fails

  1. Stop writing to the repository. Don’t commit, don’t run cleanup commands, and don’t try to fix the database.
  2. Preserve it as it is. Copy the whole directory somewhere safe, files and all, before you investigate. Even a damaged repository usually contains most of your history.
  3. Never edit .synck by hand, whether it is SQLite rows, object files or config.json. Hand edits make a repository appear consistent while destroying the evidence of what went wrong.
  4. Recover from a good copy. Restore your newest archive that verifies, or ask the producer of a complete repository for a fresh export.
  5. Report it. If you believe Synck itself caused the damage, open an issue at github.com/synergyos/synck with the exact command output.

Rebuilding the history index

The history index is derived data. Synck builds it from the history to make reads of old states fast, and it can always be rebuilt. If fsck reports a problem with the index only, rebuild it explicitly:

$ synck fsck --rebuild-state-index

This deletes the index and reconstructs it from the history, then runs the normal checks. It never changes a commit, an event, an item, a stored object or a file in your folder. It cannot repair the history itself or recreate missing file content. Those can only come from a good copy.