fix(audit): attribute admin actions to caller + log old->new diffs (#21 follow-up)#3245
Merged
Merged
Conversation
… follow-up) Audit rows for budget mutations now carry the caller's user_id as attribution and an old->new diff per field, so a single forensics row is self-describing instead of requiring a multi-row correlation walk. - update_user_budget: detail now '... hourly: 1->5 daily: 10->10 ...' with old=None rendered as 'none' (first-time configuration) - delete_user_budget: detail now '... hourly: 5->none ...' (records what was actually cleared, not just 'cleared') - update_agent_budget: previously emitted no audit row at all; now emits ConfigChange with old->new diff and caller attribution - update_budget (global): previously emitted no audit row at all; now emits ConfigChange with old->new diff and caller attribution Diff helpers fmt_user_budget_diff / fmt_agent_resources_diff / fmt_global_budget_diff colocated at the top of routes/budget.rs. Hash-chain integrity preserved (we only changed the detail string; the chain re-hashes the entire entry). Test test_user_budget_put_audit_records_old_new_diff_and_caller pins the new format end-to-end via /api/audit/query.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
Summary
Audit follow-up for review item #21 (cross-cutting audit-attribution bugs). Two problems fixed across budget mutation endpoints:
update_budget,update_agent_budgetemitted no audit at all) or, where the row was emitted, lose the diff context.update_user_budgetpreviously logged only the forward state (hourly=X daily=Y monthly=Z alert=A). Forensics had to correlate multiple rows to see what was rotated.Both are now self-describing in a single row.
Call sites changed
crates/librefang-api/src/routes/budget.rs:331update_budget(global PUT/api/budget)crates/librefang-api/src/routes/budget.rs:505update_agent_budget(PUT/api/budget/agents/{id})crates/librefang-api/src/routes/budget.rs:849update_user_budget(PUT/api/budget/users/{user})crates/librefang-api/src/routes/budget.rs:1011delete_user_budget(DELETE/api/budget/users/{user})The
require_admin/require_admin_for_user_budgetpaths inroutes/audit.rs,routes/authz.rs, androutes/budget.rsalready passSome(u.user_id)for the user_id field —agent_id="system"there is correct because the action wasn't an agent invocation, it was a request denial. Left those alone per task notes.Audit detail samples
Before (
update_user_budget):Reader cannot tell what changed without correlating with the previous row.
After (
update_user_budget, second PUT bumping hourly 1.0 → 5.0):After (
update_user_budget, first-time configuration):After (
delete_user_budget):After (
update_budgetglobal):After (
update_agent_budget):Implementation notes
fmt_user_budget_diff,fmt_agent_resources_diff,fmt_global_budget_diff) live at the top ofcrates/librefang-api/src/routes/budget.rs.Nonerenders as the literalnoneso a missing cap is distinguishable from0.0(which means "explicitly unlimited").Displayis used (no rounding);1.0_f64.to_string() == "1".detailstring changed; the chain re-hashes the entire entry.agent_idfield inupdate_agent_budget's audit row is the target agent (the one whose cap is being mutated), not the actor. The actor is inuser_id. This matches the existing convention used by other agent-scoped writes.Test plan
test_user_budget_put_audit_records_old_new_diff_and_caller(new): two sequential PUTs to/api/budget/users/Alice, then queries/api/audit/query?action=ConfigChangeand asserts:hourly: none→1andalert: none→0.8hourly: 1→5user_idfield is the calling admin's UUID (Alice)agent_idfield is"system"(config mutations are not agent-scoped)"user_budget updated for "for grep-friendly forensicscargo build --workspace --lib,cargo test --workspace,cargo clippy --workspace --all-targets -- -D warnings(skipped locally per repo policy)Linked review item
Follow-up to review item #21 from the audit-attribution review.