Surface reconciliation in the dashboard and keep the view read-only
Two gaps in the baseline-reconciliation feature: - The dashboard claimed to summarise acknowledged drift, but renderIntegrity() never rendered it. Add a `recon` chip to the integrity summary and a Reconciliation state-card (accepted/ok/stale counts plus stale items). - A read-only GET /api/integrity could write the store: list() flushed a TTL-lapsed ok->stale transition to disk, violating the read-only dashboard invariant. Add list(persist=False) and use it from the web summary path so staleness is evaluated in memory without touching the file. Covered by a new test asserting integrity_report() never rewrites the store. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
dbbe35b3fc
commit
9cbdb989ac
4 changed files with 49 additions and 8 deletions
|
|
@ -132,6 +132,20 @@ class WebReconciliationBlockTest(unittest.TestCase):
|
|||
self.assertEqual(recon["stale"], 1)
|
||||
self.assertEqual(report["checks"]["reconciliation"], "review")
|
||||
|
||||
def test_integrity_report_never_writes_store(self):
|
||||
# The dashboard is read-only: rendering the integrity view must not
|
||||
# persist a TTL-lapsed ack, even though it now reports it as stale.
|
||||
past = reconcile._utcnow() - __import__("datetime").timedelta(days=1)
|
||||
store = reconcile.ReconcileStore.load(self.cfg)
|
||||
store.accept("listener", "2/b", {"key": "2/b"}, "expired", "luna",
|
||||
expires_at=past) # status persisted as "ok"
|
||||
reconcile.ReconcileStore.invalidate_cache()
|
||||
path = reconcile.ReconcileStore.store_path(self.cfg)
|
||||
before = path.read_bytes()
|
||||
web.integrity_report(self.cfg)
|
||||
self.assertEqual(path.read_bytes(), before,
|
||||
"integrity_report wrote to the reconciliation store")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue