You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Deleting a template writes an audit row (fixed in #73). Creating agents in bulk does not.
None of these four write endpoints call audit_service:
Endpoint
What it does
POST /dashboard/api/agents/import
creates or overwrites arbitrary agent configs, memory blocks and triggers
POST /dashboard/api/templates/import
creates a project plus its whole agent tree
POST /dashboard/api/templates/create-from-agents
writes a new template file to disk
POST /dashboard/api/templates/sync
mutates existing agents to match a template
ACTION_TEMPLATE_IMPORT = "template.import" has existed in shared/utils/audit_service.py:46 since the constant list was written, and nothing references it — the intent was there, the call never was.
The result is an asymmetric trail: the audit log shows agents and templates being deleted, but not created or bulk-modified. For a log whose module docstring says "Audit logging service for EU AI Act compliance", that is the wrong half to be missing — agents/import with overwrite=true can rewrite every agent in an installation and leave no record of who did it.
ACTION_TEMPLATE_IMPORT and RESOURCE_TEMPLATE constants are already defined.
Every one of the four endpoints already has username and request in scope, so no plumbing is needed.
Scope
Audit all four endpoints, passing request so the actor's IP is recorded.
Add the missing action constants (agents.import, template.create, template.sync); reuse ACTION_TEMPLATE_IMPORT for the template import.
Put the blast radius in details — agent count, project id, and for agents/import whether overwrite was set, since that is the difference between adding and destroying.
A test per endpoint asserting the row appears.
Acceptance criteria
Each of the four endpoints writes an audit row on success
overwrite=true on agents/import is visible in the row's details
ACTION_TEMPLATE_IMPORT is no longer dead
Failed operations are not audited as if they succeeded
Explicitly out of scope
A general "audit every mutating dashboard route" sweep. This issue covers the import/sync family, where the gap is both concrete and highest-impact.
Problem
Deleting a template writes an audit row (fixed in #73). Creating agents in bulk does not.
None of these four write endpoints call
audit_service:POST /dashboard/api/agents/importPOST /dashboard/api/templates/importPOST /dashboard/api/templates/create-from-agentsPOST /dashboard/api/templates/syncACTION_TEMPLATE_IMPORT = "template.import"has existed inshared/utils/audit_service.py:46since the constant list was written, and nothing references it — the intent was there, the call never was.The result is an asymmetric trail: the audit log shows agents and templates being deleted, but not created or bulk-modified. For a log whose module docstring says "Audit logging service for EU AI Act compliance", that is the wrong half to be missing —
agents/importwithoverwrite=truecan rewrite every agent in an installation and leave no record of who did it.What already exists
audit_service.log(actor, action, resource_type, resource_id=None, details=None, request=None)— the correct API, used at ~11 call sites including the template deletion added in fix: template deletion audit entry calls a function that does not exist #73.ACTION_TEMPLATE_IMPORTandRESOURCE_TEMPLATEconstants are already defined.usernameandrequestin scope, so no plumbing is needed.Scope
requestso the actor's IP is recorded.agents.import,template.create,template.sync); reuseACTION_TEMPLATE_IMPORTfor the template import.details— agent count, project id, and foragents/importwhetheroverwritewas set, since that is the difference between adding and destroying.Acceptance criteria
overwrite=trueonagents/importis visible in the row's detailsACTION_TEMPLATE_IMPORTis no longer deadExplicitly out of scope
A general "audit every mutating dashboard route" sweep. This issue covers the import/sync family, where the gap is both concrete and highest-impact.