aeat.core.observability._fingerprint module

Deterministic SHA-256 fingerprints of corpus, db, and certificate state.

Used by run_context() to stamp a recorded RunTrace and by replay_run() to gate read-only replay. A replay refuses when any recorded hash has drifted relative to the current on-disk state.

Auditability is prioritised over time-travel: a drift refusal forces the operator to acknowledge the change rather than silently re-running a recorded command against a moved-on environment.

compute_corpus_sha256(vault_dir, settings, *, env_path=None)[source]

Compute a deterministic fingerprint of .vault/ plus Settings plus the on-disk .env.

The hash folds three inputs so replay’s drift gate catches every channel that can change the effective configuration between record and replay:

  1. The .vault/ spec content — architectural decisions, plans, research, execution records. .vault/data/ is excluded: it hosts the gitignored vaultspec-rag index (Qdrant database files, embeddings cache) which mutates continuously under a live RAG service and is not part of the canonical spec surface a replay needs to gate on.

  2. settings.model_dump_json() — the currently-loaded Settings snapshot (includes env-var-sourced overrides).

  3. The raw bytes of env/.env if present — catches dotfile edits the operator made after process start that won’t be reflected in the already-instantiated Settings().

Combining (2) + (3) is deliberate: (2) alone misses post-startup .env edits; (3) alone misses shell-exported env vars and test-fixture overrides. Together they close the drift hole.

Parameters:
  • vault_dir (Path) – Path to the .vault/ directory.

  • settings (Settings) – Active Settings instance to fold into the hash.

  • env_path (Path | None) – Path to the .env dotfile. Defaults to PROJECT_ROOT/env/.env; passed explicitly by tests so the dotfile channel can be exercised against a temp file without patching the PROJECT_ROOT module constant.

Return type:

str

Returns:

SHA-256 hex digest of the vault tree + Settings snapshot + .env bytes tuple.

compute_db_sha256(var_dir)[source]

Compute a deterministic fingerprint of the local var/ state.

Excludes caches, build artefacts, and self-referencing observability outputs so the hash is stable across observability writes and LLM/status lookups that would otherwise flap on every read. The curated list covers every var/ subdirectory that aeat.core.config.Settings treats as a cache, log, or replay-internal artefact, plus every var/ subdirectory the release / packaging pipeline materialises as a transient virtualenv:

  • var/runs/ — observability’s own output (self-reference).

  • var/browser-traces/ — Playwright session traces.

  • var/llm-cache/, var/llm-usage/, var/llm-run-telemetry/ — LLM prompt cache, usage meters, and run-timing telemetry; drift on every model call.

  • var/status-cache/ — AEAT status-reader cache.

  • var/backups/ — storage layer backups (non-canonical copies).

  • var/packaging-smoke/, var/editable-smoke/ — release pipeline scratch virtualenvs (thousands of site-packages files).

  • var/divergences/, var/i18n/ — release / i18n diff artefacts; not part of the user-state surface.

Core state (var/aeat.db, var/workflow-runs/, var/inbox/, var/drafts/, var/filing-history/, var/justificantes/) is included because changes there represent real state drift that a replay must detect.

Parameters:

var_dir (Path) – Path to the local var/ directory.

Return type:

str

Returns:

SHA-256 hex digest of the curated tree.

read_cert_fingerprint()[source]

Return the SHA-256 fingerprint of the active certificate, or "".

The empty string is the canonical “no certificate bound” sentinel — most CLI paths run without a cert (lookups, planning, replay) and must still produce a valid RunTrace.

Reading the certificate without unlocking it is intentional: the observability layer never asks the operator for a passphrase, so we hash whatever DER bytes are visible on disk. When no path is configured we return "".

Return type:

str