AuditChainWalker
AgentPrism.Core.dllWalks an ordered list of audit entries and reports the chain status. Shared by InMemoryAuditLog and the SQL providers so the two verify algorithms can never drift apart.
public static class AuditChainWalkerInheritance
Section titled “Inheritance”Inherited Members
Section titled “Inherited Members”object.GetType(), object.MemberwiseClone(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()
Methods
Section titled “Methods”Verify(IReadOnlyList<AuditEntry>, bool)
Section titled “ Verify(IReadOnlyList<AuditEntry>, bool)”Verifies an ordered (oldest first) list of entries belonging to one tenant.
public static AuditChainVerification Verify(IReadOnlyList<AuditEntry> entries, bool hasLowerBound = false)Parameters
Section titled “Parameters”entries IReadOnlyList<AuditEntry>
The entries, ordered oldest to newest (created_at, then id).
hasLowerBound bool
true when the query that produced entries had a lower
date bound (AuditChainQuery.After was set) — meaning an entry may exist
before entries[0] that this call cannot see, so nothing can be
concluded about the very first entry’s AuditEntry.PreviousHash.
false (the default) means the query covered the tenant’s whole
history, so entries[0] IS the tenant’s genesis entry and its
AuditEntry.PreviousHash must be null.
Returns
Section titled “Returns”The verification result.
Remarks
Section titled “Remarks”Three checks, in this order:
- Self-consistency. Each entry’s stored AuditEntry.Hash is recomputed from its own content and its own stored AuditEntry.PreviousHash. A mismatch means the row was altered (any field, including
PreviousHashitself) after it was written — AuditChainStatus.Broken. This pass runs first and wins over the next two: an altered row also breaks the link to its neighbor, but “the row was altered” is the more specific and more useful diagnosis. - Genesis check. Only when
hasLowerBoundis false:entries[0] must have a null AuditEntry.PreviousHash. A non-null value here means the tenant’s true first entry (or entries right after it) were deleted — also AuditChainStatus.Gap. Without this check, deleting a chain’s oldest row is invisible: every SURVIVING row is still internally self-consistent and still correctly linked to its own surviving neighbor. - Link consistency. Only once every entry is self-consistent: entry
i’s AuditEntry.PreviousHash must equal entryi-1’s AuditEntry.Hash. A mismatch means a row between them is missing — AuditChainStatus.Gap.