Audit query: Action filter dropdown is a stale hardcoded list (missing seat-release and friends) #433

Closed
opened 2026-09-05 05:10:27 +00:00 by Cordy · 1 comment
Owner

Found during #428 live verification: the audit query page's Action dropdown offers read/write/rename/delete/manual-purge/auto-purge/share-create, but the action vocabulary has grown past it — seat-release (#428), break-lock, share-revoke, peer-* are all filterable only via free-typed query or "Any action".

Options: keep the list in one place (it drifted exactly the way the audit.go comment did, fixed in the 2026-09-05 docs run to be explicitly non-exhaustive), or derive the dropdown from the actions actually present in the record (one cheap distinct-scan, honest by construction). Small either way.

Found during #428 live verification: the audit query page's Action dropdown offers read/write/rename/delete/manual-purge/auto-purge/share-create, but the action vocabulary has grown past it — `seat-release` (#428), `break-lock`, `share-revoke`, `peer-*` are all filterable only via free-typed query or "Any action". Options: keep the list in one place (it drifted exactly the way the `audit.go` comment did, fixed in the 2026-09-05 docs run to be explicitly non-exhaustive), or derive the dropdown from the actions actually present in the record (one cheap distinct-scan, honest by construction). Small either way.
Cordy closed this issue 2026-09-06 05:05:40 +00:00
Author
Owner

Shipped in v0.6.135 (PR #441, merged; dogfoods live, build_info v0.6.135).

Research record (Nikola's ask: how do comparable products do this, and does our design hold up?):

  • GitLab: per-event YAML definitions (schema + CLI generator, single source of truth) feeding docs and the UI's event-type filter (16.1+). Pitfall: enforcement is a runtime warning only — undefined events can still ship. We enforce at build time instead.
  • Keycloak: EventType enum served via serverinfo's enums map; the console filter builds from it — no drift possible. Pitfall: closed Java enum, custom event types impossible (#15288). A Go slice has no such wall.
  • CloudTrail: thousands of service-derived event names killed the dropdown — exact-match text entry only. Lesson: dropdowns need curated vocabularies; ours is 52, grouped, with room to spare.
  • Nextcloud / Gitea / Forgejo: file-only or minimal audit, no filter UI. Cairn's filterable in-app query was already ahead of the category.

What shipped (the researched design + two pitfall adjustments):

  • audit.Verbs — canonical, append-only registry: 52 verbs in 9 groups (files, trash, locks, shares, spaces, legal holds, encryption, peering, seats & licence). Append-only so retired features' history stays selectable forever.
  • verbs_test.go scanner (witnessed compile-red): every emitted verb — literal Action: fields plus the known dynamic families — must be registered, and any Action built from an unexempted non-literal fails loudly (closing the GitLab gap: nothing can slip past the literal scan). It caught real drift twice during its own build: the peering runtime family (peer-auth/send/deliver…), then auto-purge and key-drain wired in main.go. Notably it disproved this issue's own guess — auto-purge IS emitted (from main.go), the old dropdown just couldn't have told anyone what else existed.
  • Info() carries the registry through the existing /api/v1/admin/audit/info; the query page builds grouped optgroups from it (9 i18n group labels ×4), preserving the current selection across refills, with a lazy fill when the query tab opens before the settings tab. The hardcoded seven-option list is gone.

Growing it from here is exactly one step: write the new Action: "verb" literal at the call site, and CI tells you to add one line to verbs.go. The dropdown, the API and the docs-of-record all follow automatically.

Shipped in **v0.6.135** (PR #441, merged; dogfoods live, `build_info v0.6.135`). **Research record (Nikola's ask: how do comparable products do this, and does our design hold up?):** - **GitLab**: per-event YAML definitions (schema + CLI generator, single source of truth) feeding docs and the UI's event-type filter (16.1+). Pitfall: enforcement is a runtime *warning* only — undefined events can still ship. We enforce at build time instead. - **Keycloak**: `EventType` enum served via `serverinfo`'s enums map; the console filter builds from it — no drift possible. Pitfall: closed Java enum, custom event types impossible (#15288). A Go slice has no such wall. - **CloudTrail**: thousands of service-derived event names killed the dropdown — exact-match text entry only. Lesson: dropdowns need curated vocabularies; ours is 52, grouped, with room to spare. - **Nextcloud / Gitea / Forgejo**: file-only or minimal audit, no filter UI. Cairn's filterable in-app query was already ahead of the category. **What shipped (the researched design + two pitfall adjustments):** - `audit.Verbs` — canonical, **append-only** registry: 52 verbs in 9 groups (files, trash, locks, shares, spaces, legal holds, encryption, peering, seats & licence). Append-only so retired features' history stays selectable forever. - `verbs_test.go` scanner (witnessed compile-red): every emitted verb — literal `Action:` fields plus the known dynamic families — must be registered, and any Action built from an unexempted non-literal fails loudly (closing the GitLab gap: nothing can slip past the literal scan). **It caught real drift twice during its own build**: the peering runtime family (peer-auth/send/deliver…), then `auto-purge` and `key-drain` wired in main.go. Notably it *disproved* this issue's own guess — `auto-purge` IS emitted (from main.go), the old dropdown just couldn't have told anyone what else existed. - `Info()` carries the registry through the existing `/api/v1/admin/audit/info`; the query page builds grouped optgroups from it (9 i18n group labels ×4), preserving the current selection across refills, with a lazy fill when the query tab opens before the settings tab. The hardcoded seven-option list is gone. **Growing it from here** is exactly one step: write the new `Action: "verb"` literal at the call site, and CI tells you to add one line to verbs.go. The dropdown, the API and the docs-of-record all follow automatically.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#433
No description provided.