exlab_wizard.sync.verifier#

SHA-256 hash verifier for synced runs. Backend Spec §7.1.4.

After a transport reports success, the job moves to AWAITING_VERIFY. The verifier walks the local subtree, computes a SHA-256 per file, writes the manifest to <run>/.exlab-wizard/checksums.sha256 (one sha256 path line per file), and compares against a remote manifest (or against itself for self-consistency tests).

The on-disk manifest format mirrors the output of the sha256sum UNIX tool: each line has <hex-sha256>  <relative-path>. ingest.json and the cache spec already reference .exlab-wizard/checksums.sha256; this module is the writer.

Functions

format_manifest(manifest)

Return the on-disk text form of a manifest.

parse_manifest(text)

Parse the on-disk text form of a manifest.

Classes

Verifier()

SHA-256 verifier.

VerifyResult(ok[, mismatched, missing, ...])

Outcome of a verifier pass.

class exlab_wizard.sync.verifier.Verifier[source]#

Bases: object

SHA-256 verifier. Backend Spec §7.1.4.

async compute_local_manifest(run_path)[source]#

Walk run_path and compute a SHA-256 per file.

Writes the manifest to run_path/.exlab-wizard/checksums.sha256 as a side-effect (the §7.1.4 contract). Files inside the .exlab-wizard/ cache subtree are excluded so the manifest does not record its own hash.

Parameters:

run_path (Path)

Return type:

dict[str, str]

async verify_against_local(run_path, manifest)[source]#

Re-hash every entry in manifest against the local subtree.

Returns a VerifyResult with ok=True iff every entry in the manifest exists locally with the recorded hash.

Files on disk that are NOT in the manifest are returned in extra for diagnostic logging but do not by themselves cause ok=False; a partial transport that wrote a fresh file would be caught by a later compute_local_manifest pass.

Parameters:
Return type:

VerifyResult

verify_against_remote(local_manifest, remote_manifest)[source]#

Compare a local manifest against a remote-derived manifest.

Pure dict comparison with no I/O. Use after the transport reports success, with remote_manifest derived from a remote hash probe (e.g. rclone hashsum sha256 or ssh ... sha256sum).

  • mismatched: keys present in both with differing hex digests.

  • missing: keys present locally but absent remotely; this is the integrity-in-transit failure mode.

  • extra: keys present remotely but not locally; informational only and does not flip ok.

  • ok = not mismatched and not missing. An empty remote_manifest therefore yields ok=False with every local key listed in missing.

Parameters:
Return type:

VerifyResult

class exlab_wizard.sync.verifier.VerifyResult(ok, mismatched=(), missing=(), extra=(), manifest=<factory>, error_kind=None)[source]#

Bases: object

Outcome of a verifier pass.

ok is True iff every file in the manifest matched. mismatched lists relative paths whose hash differed; missing lists paths in the manifest that no longer exist on disk; extra lists files on disk that were not in the manifest (informational only).

error_kind is set when the remote-hash probe could not complete (the underlying exlab_wizard.sync.transports.TransportError classified the failure as AUTH / NETWORK / UNKNOWN). The queue worker keys off this field to route via the §7.1.5 retry policy: AUTH -> terminal FAILED, NETWORK / UNKNOWN -> backoff retry. None for every non-remote-probe outcome.

Parameters:
error_kind: TransportErrorKind | None#
extra: tuple[str, ...]#
manifest: dict[str, str]#
mismatched: tuple[str, ...]#
missing: tuple[str, ...]#
ok: bool#
exlab_wizard.sync.verifier.format_manifest(manifest)[source]#

Return the on-disk text form of a manifest.

Each line is <hex-sha256>  <relative-path>. Lines are sorted by relative path so the file is reproducible across hosts.

Parameters:

manifest (dict[str, str])

Return type:

str

exlab_wizard.sync.verifier.parse_manifest(text)[source]#

Parse the on-disk text form of a manifest.

Tolerant of single- and double-space separators (sha256sum outputs either form depending on the host). Empty lines are ignored.

Parameters:

text (str)

Return type:

dict[str, str]