Skip to content

fix(audit): export takes correlation_id and refuses a filter it does not declare - #872

Merged
remyluslosius merged 6 commits into
mainfrom
fix/audit-export-filter-parity
Sep 22, 2026
Merged

remyluslosius merged 6 commits into
mainfrom
fix/audit-export-filter-parity

Conversation

@remyluslosius

Copy link
Copy Markdown
Contributor

Summary

CP bugs/doing/OW-064. Contract first.

Contract. api-audit-events-query 1.5.0: C-08 now says the export accepts the same filters as the list (correlation_id added) and rejects an undeclared query parameter with 400 request.unknown_parameter naming it; the strictness is confined to the export route by founder decision and is not a server-wide policy. AC-17 covers parity, the refusal, and the list's unchanged leniency. api/openapi.yaml: getAuditEventsExport declares correlation_id and a 400 envelope response; generated Go and TypeScript follow.

Code. audit_export_handler.go copies correlation_id into the list query and, before any work, checks the raw query string against auditExportParams (the declared set) in request order, answering request.unknown_parameter with the first unknown key. GET /api/v1/audit/events is unchanged.

Tests.

  • TestAPI_AuditEvents_ExportFilterParityAndNoSilentWidening (AC-17): two correlation ids seeded; correlation_id=corr-a yields exactly those rows in JSON and CSV; actr_type=user (misspelled) yields 400 request.unknown_parameter naming actr_type with no Content-Disposition; the same misspelling on the list returns 200.
  • TestAPI_AuditEvents_ExportParamGuardMatchesContract (AC-17): reads the export operation from api/openapi.yaml and requires the guard's set to equal the declared parameters, so they cannot drift. Mutation check: dropping correlation_id from the guard turns both tests red.

Guide. The audit section documents the export beside the list with its seven filters, the cap, the truncation header and the refusal rule. Merge after #870 (OW-065); this paragraph supersedes its "today the export drops correlation_id" sentence, and I will refresh on conflict.

Also in this PR: one format-only commit (8e65349b) for three frontend files that drifted on main earlier (24057cb3, 1507b799). The pre-commit prettier hook checks the whole frontend directory, so any PR that regenerates schema.d.ts is blocked by that drift; no CI job runs the check. No logic changes in those files.

Checks

go test ./internal/server/ -run TestAPI_AuditEvents green (dedicated test DB); make spec-check 121/121, 100%; make check-generated in sync; doc style clean; pre-commit and pre-push hooks passed.

Candidate impact

v0.8.0-rc.5 is immutable and carries the old behavior; nothing here changes it.

Format-only. The pre-commit prettier hook checks the whole frontend
directory, so any commit that touches a frontend file is blocked by drift
that landed earlier on main (24057cb, 1507b79). No CI job runs this
check. No logic changes.
…not declare

The export accepted six of the list's seven filters; correlation_id was
missing from the contract and the handler. Because the generated router
drops undeclared query parameters, an export narrowed by correlation_id
(or any misspelled filter) returned the caller's whole trail up to the
10,000-row cap with no signal, and an incident package built from it
would be wrong without anyone noticing (CP bugs/OW-064).

Contract first: api-audit-events-query 1.5.0 amends C-08 (the export
accepts the same filters as the list, correlation_id included, and
rejects an undeclared query parameter with 400 request.unknown_parameter
naming it; the strictness is confined to the export route by founder
decision) and adds AC-17. The export operation in api/openapi.yaml
declares correlation_id and the 400 response; generated code follows.

The handler copies correlation_id into the list query and checks the raw
query string against the set of declared parameters before running
anything, in the request's own order, so the first unknown key is named.
The list endpoint is unchanged and stays lenient.

Tests: AC-17 seeds events under two correlation ids and asserts the
narrowed export in both formats, the 400 envelope for a misspelled
filter with no Content-Disposition, and the list's 200 for the same
misspelling. A second test reads the export operation from
api/openapi.yaml and requires the guard's set to equal the declared
parameters, so the two cannot drift; removing correlation_id from the
guard turns both tests red. The API guide's audit section documents the
export beside the list. The detect-secrets baseline is the hook's own
line-number refresh.

CP: bugs/doing/OW-064
@github-actions github-actions Bot added documentation Improvements or additions to documentation frontend size/L labels Sep 21, 2026
remyluslosius added a commit that referenced this pull request Sep 22, 2026
The error section takes main's paragraph: every process-generated
error now carries the envelope (#871 merged), so this branch's
sentence saying three were plain text is dropped. The audit-export
limitation sentence stays until #872 lands.
A blank line between the two rows split the table, so the export row
would have rendered as loose text.
The audit section keeps one export table row (both sides carried the
same joined row) and takes this branch's export paragraph, which
describes the implemented behavior, over #870's temporary limitation
paragraph.
Merging main kept main's baseline; this branch's regenerated
server.gen.go shifts two findings by one line (4595 to 4596, 4733 to
4734). Rescanned with the pinned detect-secrets 1.5.0: 83 fingerprints,
none added or removed, two locations corrected.
@remyluslosius
remyluslosius merged commit 7e0e2fc into main Sep 22, 2026
14 checks passed
@remyluslosius
remyluslosius deleted the fix/audit-export-filter-parity branch September 22, 2026 02:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation frontend size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant