Implement AUDIT-WP-0007 hash-chain integrity.
Accept now extends a single-schema chain. Verify walks it; a rewritten payload_hash is a break. Tamper evidence is that detector plus an external chain-head attestation, not WORM.
This commit is contained in:
parent
5faede18fc
commit
5fd04e2095
17 changed files with 696 additions and 29 deletions
|
|
@ -201,11 +201,57 @@ def test_health_passes_on_a_live_backend(backend):
|
|||
backend.health()
|
||||
|
||||
|
||||
def test_chain_links_and_verify_is_clean(backend):
|
||||
from audit_core.integrity import GENESIS
|
||||
|
||||
first = make_event("chain-1")
|
||||
second = make_event("chain-2")
|
||||
backend.accept(first, digest(first))
|
||||
backend.accept(second, digest(second))
|
||||
report = backend.verify_chain()
|
||||
assert report.intact is True
|
||||
assert report.events >= 2
|
||||
assert report.first_break is None
|
||||
assert report.head != GENESIS
|
||||
replay = backend.accept(first, digest(first))
|
||||
assert replay.duplicate is True
|
||||
assert backend.verify_chain().events == report.events
|
||||
|
||||
|
||||
# --- postgres-specific guarantees -------------------------------------------
|
||||
|
||||
pg_only = pytest.mark.skipif(not HAVE_PG, reason="needs PostgreSQL")
|
||||
|
||||
|
||||
@pg_only
|
||||
def test_rewritten_payload_fails_verify_postgres():
|
||||
"""Superuser rewrite is the evidence the trigger never gave us."""
|
||||
from audit_core.postgres_backend import PostgresAuditBackend
|
||||
|
||||
schema = f"conf_{uuid.uuid4().hex[:12]}"
|
||||
backend = PostgresAuditBackend(PG_URL, schema=schema)
|
||||
try:
|
||||
event = make_event("break-1")
|
||||
backend.accept(event, digest(event))
|
||||
other = make_event("break-2")
|
||||
backend.accept(other, digest(other))
|
||||
assert backend.verify_chain().intact is True
|
||||
with backend.pool.connection() as conn:
|
||||
conn.execute(f'ALTER TABLE "{schema}".events DISABLE TRIGGER events_append_only')
|
||||
conn.execute(
|
||||
f'UPDATE "{schema}".events SET payload_hash = %s WHERE event_id = %s',
|
||||
("deadbeef" * 8, "break-2"),
|
||||
)
|
||||
conn.execute(f'ALTER TABLE "{schema}".events ENABLE TRIGGER events_append_only')
|
||||
report = backend.verify_chain()
|
||||
assert report.intact is False
|
||||
assert report.first_break == "break-2"
|
||||
finally:
|
||||
with backend.pool.connection() as conn:
|
||||
conn.execute(f'DROP SCHEMA IF EXISTS "{schema}" CASCADE')
|
||||
backend.close()
|
||||
|
||||
|
||||
@pg_only
|
||||
def test_replay_reconciles_rather_than_duplicating():
|
||||
"""Replay must never mint a second custody record for one source event."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue