Skip to content

feat(audit): stamp the request id the audit table has always had a column for - #240

Open
LKSNDRTMLKV wants to merge 1 commit into
mainfrom
fix/audit-request-id
Open

feat(audit): stamp the request id the audit table has always had a column for#240
LKSNDRTMLKV wants to merge 1 commit into
mainfrom
fix/audit-request-id

Conversation

@LKSNDRTMLKV

Copy link
Copy Markdown
Member

odal.passport_audit.request_id has existed since migration 0005 and nothing
has ever written to it. Every row on disk has NULL there. This wires it.

Why the id is not threaded through the service layer

PassportAuditEntry is built in eleven places — create, publish, the four
lifecycle transitions, EOL, the three transfer legs, the credentialed read.
Stamping at each of them is eleven identical lines and a twelfth call site
added later that silently writes NULL.

They all funnel through AuditRepository::append, so the id is stamped by a
decorator on the port (dpp_vault::infra::request_stamped_audit) wired in both
composition roots. No service signature moves, and a new call site cannot
forget.

The id reaches the decorator through a task-local scoped by the existing
inject_request_id middleware. That is the only ambient value in the codebase
and it stays that way deliberately: a request id is diagnostic, so a caller
that gets None loses a support handle and nothing else. Nothing decides on
it. The documented limitation — a task-local does not cross tokio::spawn — is
asserted in a test rather than only described.

Why it is not in the chain hash

Two reasons, either sufficient.

The column is thirty migrations old and every existing row has NULL. Folding
it into chain_hash would change the hash input for entries whose entry_hash
is already committed, and verify_audit_chain would report every existing
chain as tampered
.

And it is not a claim about the passport. The chain makes a state change
tamper-evident; a correlation handle for a support conversation describes the
transport that carried it. Signing it would assert something the trail does not
mean.

chain_hash_matches_its_persisted_golden_value now sets request_id to Some
and asserts the same golden hash — set it to None and the test passes
while proving nothing.

skip_serializing_if is load-bearing for the same class of reason: an entry
read back with NULL serialises byte-identically to one written before the
field existed, so no already-signed evidence dossier's content hash moves.
Asserted in an_unstamped_entry_does_not_serialise_the_field.

Checks

fmt-check, clippy -D warnings, all 85 test binaries, openapi-check
(bundles regenerated, Redocly clean), and the nine script gates — debug,
subjects, mod-rs, spec-version, grants, migrations, outbound,
harness, contract-fixture — all pass.

The OpenAPI contract gate is what forced api/ to be updated: the exhaustive
fixture failed to compile until it set the field, then failed until the schema
documented it. Working as designed.

Not in this PR

Cargo.lock on main is patch-polluted — the nine dpp-* core entries carry
no source/checksum, so they were committed with a local
[patch.crates-io] active. Building without the patch rewrites 24 lines. CI
does not build --locked, so nothing catches it. Left out of this diff; worth
its own issue.

Groundwork for #145 — the audit trail can now answer "did my first attempt
land?" for the passport routes, which is diagnosis, not idempotency.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · -1 duplication

Metric Results
Complexity 9
Duplication -1

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@LKSNDRTMLKV LKSNDRTMLKV changed the title Stamp the request id the audit table has always had a column for feat(audit): stamp the request id the audit table has always had a column for Sep 4, 2026
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.

1 participant