Skip to content

feat: dmtri fix — automated repair of consistency-report inconsistencies - #34

Merged
NikolaosSokos merged 2 commits into
mainfrom
feat/fix-command
Jun 19, 2026
Merged

feat: dmtri fix — automated repair of consistency-report inconsistencies#34
NikolaosSokos merged 2 commits into
mainfrom
feat/fix-command

Conversation

@NikolaosSokos

Copy link
Copy Markdown
Collaborator

Summary

Adds dmtri fix, which turns an eida-consistency report into automated repairs.
Point it at a report (file or URL) and, for each inconsistent stream, it re-runs
the WFCatalog collector and rebuilds the availability view for the exact broken
window — closing the gap where /availability failed to show data that
/dataselect actually returns.

dmtri fix https://.../NOA_2026-06-07_140510.json                       # fix all
dmtri fix https://.../NOA_2026-06-07_140510.json --index 2 --index 16  # specific entries
dmtri fix --verify-only https://.../NOA_2026-06-07_140510.json         # re-check only

How it works

  1. Shells out to eida-consistency explore --json to get structured fixes
    (NSLC + true window + direction + status).
  2. Validates every value against strict allow-lists (the report is untrusted input).
  3. Per stream: wfcatalog_refreshavailability_rebuild, continue-on-error
    (one failed stream is recorded and skipped, not fatal).
  4. Reminds that /availability caches answers ~20 min; --verify-only confirms
    later.

Companion changes in other EIDA repos (required for this to work)

This feature depends on two changes made in sibling repos:

  • eida-consistency — added explore --json, a machine-readable output of the
    inconsistencies and their boundaries (schema v1.0: NSLC, start, end, direction,
    status). dmtri fix consumes this instead of scraping human logs.
  • ws-availability — added the avail-rebuild console script, which rebuilds
    the availability materialized view for a specific NSLC + date range. dmtri
    invokes it over SSH via docker exec fdsnws-availability-cacher avail-rebuild.
    No public mutate route was added to the FDSN service (kept off the public API
    on purpose).

Files

  • src/dmtri/fix.py (new) — command logic, dependency resolution, input
    validation, fix→playbook-vars mapping, chain driver, verify-only.
  • src/dmtri/data/playbooks/fix/availability_rebuild.yml (new) — scoped rebuild,
    command/argv (no shell) for injection safety, with job tracking.
  • tests/test_fix.py (new) — 21 tests.
  • src/dmtri/cli.py, src/dmtri/hooks/hooks.py, src/dmtri/paths.py — wiring
    (subcommand, run_hook rc + exit_on_error, playbook path).
  • README.md — "Fix Inconsistencies" section + eida-consistency prerequisite.
  • .gitignore — ignore demo recordings and AI-assistant folders.

Direction handling (refresh vs clean)

Inconsistencies have a direction, and they are NOT handled the same way:

  • refresh (availability NO / dataselect YES): data is on disk but the
    availability view is stale → rebuild it. This is the safely-automatable case
    and the only one this command acts on.
  • clean (availability YES / dataselect NO): detected and deliberately
    skipped
    . This pattern is predominantly false positives — restricted data
    (eida-consistency#42) and transient service errors (eida-consistency#36) —
    where auto-removing availability records would destroy correct metadata. It is
    reported, not actioned.
  • transient / fixed: skipped (re-test later / already consistent).

Security

The report is fetched from a URL (untrusted) and its values flow into
docker exec / shell-touching playbooks. Defense in depth:

  • _validate_fix rejects anything not matching strict allow-lists (FDSN codes,
    ISO dates) before it can reach a command line.
  • The rebuild playbook uses command:/argv: rather than shell:.
  • Tests prove a malicious report row runs zero playbooks.

Validation

Run against the live NOA node on a real report: all 8 inconsistencies repaired,
every Ansible run reported failed=0 / unreachable=0, and an independent
--verify-only pass afterward reported 8 fixed, 0 still inconsistent.
Full test suite: 61 passing.

Notes / scope

  • v1 is refresh-only by design (see Direction handling above).
  • dmtri fix requires the eida-consistency CLI; it prints exact install/upgrade
    instructions if missing or too old, and stops before touching anything.

Closes #33.

…tency reports

`dmtri fix <report>` reads an eida-consistency report (local file or URL),
finds the inconsistent streams and their day-by-day boundaries, and runs the
repair chain for each: wfcatalog_refresh (re-run the collector) then
availability_rebuild (rebuild the availability view for the exact window).

- fix.py: locate eida-consistency, parse `explore --json`, validate every
  report value against strict allow-lists (the report is untrusted URL input),
  map fixes to playbook vars, drive the chain with continue-on-error.
- playbooks/fix/availability_rebuild.yml: scoped rebuild via
  `docker exec fdsnws-availability-cacher avail-rebuild`, using command/argv
  (no shell) for injection safety.
- hooks: run_hook now returns the rc and takes exit_on_error, so one failed
  stream doesn't abort the batch.
- --verify-only re-checks a report without changing anything.
- README: "Fix Inconsistencies" section + eida-consistency prerequisite.
- tests: 21 tests (parsing, schema guard, date-boundary mapping,
  dependency missing/too-old messages, command-injection rejection).
@NikolaosSokos
NikolaosSokos merged commit 0f2f9a0 into main Jun 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatically fix inconsistencies from a given eida-consistenct report

1 participant