User action audit
In admin-gui-backend, user action audit is sent through the ensi/action-audit-event-producer package to the central action-audit service over Kafka.
When to add audit
Add audit for any request that changes data state:
- create, update, delete, replace;
- status changes and other significant flags;
- attaching and removing files or relations;
- bulk operations;
- authentication actions that matter for traceability, such as login and logout;
- settings changes.
Do not add audit for read-only endpoints:
- search, list, get, and
metaendpoints; - enum value lookups;
- helper endpoints that do not change state.
In this service, audit calls live in HTTP controllers, not in domain actions.
How the package works
AuditEvent::log()adds an event to an in-memory queue.- The queue is automatically flushed in Laravel
terminating. - Sending happens after the response has already been returned to the client.
- If
AUDIT_EVENTS_ENABLED=false,AuditEvent::log()is a no-op.
Do not call flush() manually in service code.
What is already configured
The package is already wired into the service:
AppServiceProviderbindsAuditResolversInterfacetoApp\Domain\Audit\AuditResolver;config/audit-event-producer.phpreads:AUDIT_EVENTS_ENABLEDAUDIT_EVENTS_SYSTEM_CODEAUDIT_EVENTS_KAFKA_TOPICAUDIT_EVENTS_CACHE_STORE
- in
config/kafka.php, theaudit-eventskey is mapped to theaction-auditKafka topic.
If you add a new environment or deployment profile, make sure these settings are present there as well.
How to call audit
Use the facade:
use Ensi\ActionAuditEventProducer\AuditEvent;
use Ensi\ActionAuditEventProducer\DTOs\PerformerDto;
AuditEvent::log(
actionType: AuditActions::ORDERS_PATCH->value,
entityType: AuditEntityType::ORDER->value,
entityId: (string) $id,
entityTitle: fn () => $order->order->getNumber(),
context: fn () => $request->validated(),
);
Parameter rules:
actionTypeis required and must come fromApp\Domain\Audit\Enums\AuditActions;entityTypeis optional and should come fromApp\Domain\Audit\Enums\AuditEntityType;entityIdshould be a string;entityTitleis optional and should return a short human-readable label;contextis optional and should return a small array with the important change details;performeris optional and should be used only when the default authenticated user is not the real performer.
entityTitle and context are Closures. They are evaluated only at flush time, so keep them side-effect free and lightweight.
When to pass performer explicitly
For normal authenticated requests, do not pass performer. By default, the package resolves the performer through App\Domain\Audit\AuditResolver.
Use an explicit PerformerDto only when the action is performed by someone other than the current request user. The current example in the service is login:
AuditEvent::log(
AuditActions::AUTH_LOGIN->value,
context: fn () => [
'ip' => $request->ip(),
'user-agent' => $request->userAgent(),
],
performer: new PerformerDto($request->getLogin()),
);
Adding new actions and entities
If you add a new auditable action or a new entity type:
- Add a new case to
App\Domain\Audit\Enums\AuditActionsorAuditEntityType. - Add translations in:
resources/lang/en/audit-actions.phpresources/lang/ru/audit-actions.phpresources/lang/en/audit-entities.phpresources/lang/ru/audit-entities.php
- Use the new enum value in the controller.
AuditResolver reads those translation files and sends localized names to the audit service.
Where to place the call
Place AuditEvent::log() next to the state-changing action in the controller. The common sequence is:
- execute the domain action;
- log audit using request data or the action result;
- return the response.
Typical examples in this service:
- customer create, update, and delete flows;
- order patch and order item or file operations;
- CMS and catalog mutations;
- user and role management changes;
- audit settings updates.
What to put in payload
Keep the payload focused and useful:
- include only what helps explain what changed;
- prefer IDs, codes, numbers, and short labels;
- do not send passwords, tokens, secrets, or oversized structures.