ipsocode/hypervel-auditing
Audit trail package for Hypervel apps that logs model creates, updates, and deletes with old/new values and user attribution. Track changes, debug issues, and support compliance with a simple, configurable activity history.
Install the package alongside the matching framework component line. As of v0.2.0 you must be on hypervel/components 0.4.x-dev; that constraint is what pins your PHP version, so bump it first and let Composer resolve PHP before touching anything else.
composer require ipsocode/hypervel-auditing:^0.2.0
Then publish and run the migration if you have not already:
php artisan vendor:publish --tag=auditing-config
php artisan migrate
Look first at config/auditing.php — it decides which models are audited, which events are recorded, and how the causer is resolved. After that, read Ipsocode\Auditing\Contracts\Auditor; it is the surface you will interact with daily (and the thing that changed in this release).
The first real use case is the one this release unlocks: attribute an audit to someone other than the authenticated user. Anywhere you perform a privileged or impersonated action — an admin editing on behalf of a customer, a queued job acting for a user, a console command — wrap it:
use Ipsocode\Auditing\Facades\Auditor;
Auditor::actingAs($customer, function () use ($request) {
$order->update($request->validated());
});
Every audit written inside that closure records $customer as its causer, then the previous causer is restored.
Scoped causer attribution. actingAs() is a stack-friendly scoped override, not a global setter. Use it in jobs, artisan commands, and impersonation flows where Auth::user() is null or wrong:
class ReconcileOrders implements ShouldQueue
{
public function handle(): void
{
Auditor::actingAs($this->initiator, function () {
// all audits here blame $this->initiator
});
}
}
Nest calls when you need to hand attribution down and back up; the causer active before the callback is restored when it returns.
Testing with Auditor::fake(). This is the pattern most teams will adopt first — assert that an action produced exactly the audits you expect without hitting the audit table:
use Ipsocode\Auditing\Facades\Auditor;
it('audits an order status change', function () {
Auditor::fake();
$this->put("/orders/{$order->id}", ['status' => 'shipped']);
Auditor::assertAudited($order); // see the fake's assertion API for the exact names
Auditor::assertNothingAudited($otherOrder);
});
Swap the real repository in config/auditing.php/the service container for the fake so feature tests stay fast, and keep a small number of integration tests hitting the real driver so the config itself stays covered.
Custom auditors. If you have your own class implementing Ipsocode\Auditing\Contracts\Auditor (rather than using the shipped Auditor), add the two new methods:
public function actingAs($user, callable $callback): mixed
{
$previous = $this->currentCauser();
$this->causer = $user;
try {
return $callback();
} finally {
$this->causer = $previous;
}
}
public function currentCauser(): mixed
{
return $this->causer;
}
Delegate to the parent or to the package's Auditor if you are only decorating it.
Integration tips. Wrap your own service-layer entry points — not controllers — in actingAs(), so the scope matches the transaction boundary. If you already have an Auditable trait or observer-based pipeline, put actingAs() at the outermost layer and let inner code stay ignorant of it. Pair fake() with existing HTTP tests rather than rewriting them: add the fake in setUp and assert afterwards.
Auditor need no change. Only classes that implement Ipsocode\Auditing\Contracts\Auditor themselves must add actingAs() and currentCauser(). Grep your codebase for implements Auditor before upgrading; a missing method is a fatal error, not a soft deprecation.0.4.x-dev is a dev constraint. You are tracking a development branch of hypervel/components. Pin with a commit hash or a dev- alias in composer.json if you need reproducible builds, and expect PHP version shifts to arrive with framework bumps rather than with this package. Check CI runs the same PHP minor as production.actingAs() does not bypass auth checks. It only names the causer for audit records; authorization, guards, and Auth::user() are untouched inside the callback. Do not use it as an impersonation mechanism.finally. If you write your own, do the same, or a thrown exception leaks attribution into every subsequent audit in the same request/coroutine.actingAs() over manually setting a causer, and avoid stashing causer state on long-lived singletons outside the callback.Auditor::fake() is per-test-container; if you resolve Auditor statically in a service provider's register(), the binding captured at boot may not be the fake. Resolve it inside the method under test, or reset the fake in setUp.config/auditing.php and actingAs() interact — the explicit causer wins inside the callback, but verify your resolver does not overwrite it on the model's saved event.fake() "swallowed" your records; a fake left installed from a previous test in the same process is the usual culprit.actingAs() as the single mutation entry point so future package additions stay compatible.How can I help you explore Laravel packages today?