Add the PAM access-audit event store - #8230
Draft
patriksvensson wants to merge 1 commit into
Draft
Conversation
The append-only store the audit trail is written to and read back from: the AccessAuditEvent table and its two stored procedures, a consolidated migration for MSSQL plus generated ones for the EF providers, and the Dapper and EF repositories behind IAccessAuditEventRepository. Rows are self-contained. AccessAuditEvent_Create snapshots the actor, requester, cipher, collection, and rule display names into the row at write time, so the trail read touches no other table and a later rename or delete cannot rewrite history. The subject ids are deliberately not foreign keyed for the same reason -- an event outlives what it references. Only OrganizationId is, so the rows go when the organization does. The EF path resolves those names in C#, because JSON_VALUE -- which the procedure uses to read the cipher name out of its encrypted Data document -- has no portable EF translation. This is the persistence layer only; nothing consumes it yet. The emitter that writes to it and the trail endpoint that reads from it are separate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit d06d9fa)
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #8230 +/- ##
=======================================
Coverage ? 68.64%
=======================================
Files ? 2388
Lines ? 104168
Branches ? 9416
=======================================
Hits ? 71506
Misses ? 30317
Partials ? 2345 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| "[dbo].[AccessAuditEvent_Create]", | ||
| new | ||
| { | ||
| Id = CoreHelpers.GenerateComb(), |
|
|
||
| var row = new EfModel | ||
| { | ||
| Id = CoreHelpers.GenerateComb(), |
|
|
||
| var rule = new AccessRule | ||
| { | ||
| Id = CoreHelpers.GenerateComb(), |
|
|
||
| var rule = new AccessRule | ||
| { | ||
| Id = CoreHelpers.GenerateComb(), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎟️ Tracking
PM-39047
📔 Objective
Adds the append-only store behind the PAM access-audit trail: the AccessAuditEvent
table, its two stored procedures, migrations for MSSQL and the three EF providers,
and the Dapper and EF implementations of IAccessAuditEventRepository.
Nothing calls it yet, and that's deliberate. The emitter that writes events and the
endpoint that reads the trail back are separate PRs. Landing the persistence layer on
its own keeps the schema reviewable without a feature's worth of code wrapped around
it. The parts DB Ops care about are the whole diff here, not a corner of it.
Two design decisions look like mistakes if you don't know the intent:
Rows are self-contained. AccessAuditEvent_Create snapshots the actor, requester,
cipher, collection, and rule display names into the row at write time. Reading the
trail then touches no other table, and a later rename can't rewrite history. The
subject ids are deliberately not foreign keyed for the same reason: an audit event
has to outlive what it references. Only OrganizationId is, so the rows are removed
with the organization.
The EF path resolves those names in C# instead of in the query. The stored
procedure pulls the cipher name out of its encrypted Data document with JSON_VALUE,
which has no portable translation across MySQL, Postgres, and SQLite.
Five DatabaseTheory integration tests cover the round trip. Two of them pin the
design above: GetManyByOrganizationId_SnapshotName_SurvivesEntityDeletion and
..._IsNotRewrittenByRename.