PHPackages                             bbs-lab/nova-action-event-columns - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. bbs-lab/nova-action-event-columns

ActiveLibrary[Security](/categories/security)

bbs-lab/nova-action-event-columns
=================================

Add extra columns to Nova's action\_events table and fill them automatically on every action — client IP out of the box, plus your own columns via a resolver registry.

v1.0.0(today)00MITPHP ^8.2

Since Jul 22Compare

[ Source](https://github.com/BBS-Lab/bbs-lab-nova-action-event-columns)[ Packagist](https://packagist.org/packages/bbs-lab/nova-action-event-columns)[ Docs](https://github.com/BBS-Lab/nova-action-event-columns)[ RSS](/packages/bbs-lab-nova-action-event-columns/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (14)Versions (2)Used By (0)

Nova Action Event Columns
=========================

[](#nova-action-event-columns)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5cfa3dc1cef4f8007e2b75f7c7e5a214c504a1df02bdda383a83382bf869e50a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6262732d6c61622f6e6f76612d616374696f6e2d6576656e742d636f6c756d6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bbs-lab/nova-action-event-columns)[![Tests](https://camo.githubusercontent.com/0e7c9485f3630cbe8e102b4bd8115526a721a2c16d9e8b27f5b5e0623e99db1f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4242532d4c61622f6e6f76612d616374696f6e2d6576656e742d636f6c756d6e732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/BBS-Lab/nova-action-event-columns/actions)[![Total Downloads](https://camo.githubusercontent.com/3369e415814abf6f574b39fc7b8bf4bafa0b78775380830b3faf9d8dc7ecfe2b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6262732d6c61622f6e6f76612d616374696f6e2d6576656e742d636f6c756d6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bbs-lab/nova-action-event-columns)

Add **extra columns to [Laravel Nova](https://nova.laravel.com)'s `action_events` table** and fill them automatically on every action. The **client IP address** (`ip_address`) ships as a built-in column; your app can register **additional columns** — `tenant_id`, `user_agent`, anything — without forking, through a small resolver registry.

Nova writes `action_events` through two internal paths (event-firing `->save()` and event-bypassing mass `::insert()`), and only fires Eloquent events on one of them. This package hooks **both**, so your columns are populated no matter how the event is created: create, update, attach, delete, force-delete, restore, and every custom Nova action. **Works on Nova 4 and Nova 5.**

Screenshots
-----------

[](#screenshots)

> Split diagonally: **light theme** (top-left) / **dark theme** (bottom-right).

The auto-registered "Action Events" resource, with the built-in `ip_address` column filled on every event:

[![Action Events resource with the IP column](art/action-events.png)](art/action-events.png)

An event's detail page shows every column as a field — including the built-in `IP`:

[![Action event detail with the IP field](art/action-event-detail.png)](art/action-event-detail.png)

Features
--------

[](#features)

- 🌐 Built-in **`ip_address`** column captured from `request()->ip()`, toggleable via config
- 🧩 **Column registry** — register your own columns with a value resolver and an optional Nova field
- 🔁 **Every write path covered** — a `creating` hook for `->save()` paths and an `insert()` override for the mass-insert paths
- 🖥️ Custom **`ActionResource`** that surfaces your columns in Nova (your field, or a read-only default)
- 🧹 **`action-events:prune`** command for retention (`--days` / `--hours` / `--all`)
- 📦 Publishable migration, custom-column migration **stub**, and config
- 🧪 100% line coverage, PHPStan level 8, no `final` classes, strict types everywhere

Requirements
------------

[](#requirements)

- PHP `^8.2`
- Laravel Nova `^4.0 || ^5.0`
- Laravel `^11.0 || ^12.0 || ^13.0`

Both Nova majors are exercised in CI. Note that **Nova 4** (through its `inertiajs/inertia-laravel`dependency) tops out at **PHP 8.4** and **Laravel 11**; on PHP 8.5 or Laravel 12+, use Nova 5. Composer resolves the right combination for you.

Installation
------------

[](#installation)

Because Nova is a paid, private package, make sure your application is already authenticated against `nova.laravel.com`, then:

```
composer require bbs-lab/nova-action-event-columns
```

The service provider auto-registers via Laravel package discovery. The `ip_address` migration runs automatically. Publish the config, migration or custom-column stub if you want to tweak them:

```
# Config
php artisan vendor:publish --tag=nova-action-event-columns-config

# The shipped ip_address migration
php artisan vendor:publish --tag=nova-action-event-columns-migrations

# A stub for adding your own action_events column — edit it before migrating
php artisan vendor:publish --tag=nova-action-event-columns-stub

# Translations (en, fr) — to customise the resource / field labels
php artisan vendor:publish --tag=nova-action-event-columns-translations

php artisan migrate
```

Activation
----------

[](#activation)

Nova only records into a custom `action_events` model when you point its action resource at this package. In `config/nova.php`:

```
'actions' => [
    'resource' => \BBSLab\NovaActionEventColumns\Nova\ActionResource::class,
],
```

Then run `php artisan migrate`. Until this is set, Nova uses its own action resource and your extra columns stay `null`.

Usage
-----

[](#usage)

### The built-in IP column

[](#the-built-in-ip-column)

Once activated and migrated, every action event stores the request IP in `ip_address` — nothing else to do. Toggle it in `config/nova-action-event-columns.php` (env `NOVA_ACTION_EVENT_COLUMNS_IP_ENABLED`).

### Registering custom columns

[](#registering-custom-columns)

Register columns from a service provider's `boot()` — **in code, never in config**, because closures cannot be serialized by `config:cache`. Each column gets a **resolver** (the value to store) and an optional **field factory** (how it shows in Nova):

```
use BBSLab\NovaActionEventColumns\Facades\NovaActionEventColumns;
use Laravel\Nova\Fields\Number;

public function boot(): void
{
    NovaActionEventColumns::register(
        'tenant_id',
        fn ($request) => $request?->user()?->tenant_id,       // value resolver
        fn () => Number::make('Tenant', 'tenant_id')->exceptOnForms(), // optional Nova field
    );
}
```

- The resolver receives the current `Illuminate\Http\Request` (or `null` outside an HTTP context — return `null` and leave the column nullable).
- When you omit the field factory, the column is shown read-only via `Text::make(Str::headline($column), $column)`.
- Existing values are never overwritten — resolvers only fill columns that are still `null`.

You must provision the database column yourself; publish the stub (`--tag=nova-action-event-columns-stub`), rename it, set the column name/type, and migrate.

### Viewing the events in Nova

[](#viewing-the-events-in-nova)

The package's `Nova\ActionResource` extends Nova's own and adds a field for each registered column — your registered field if you supplied one, otherwise the read-only default. The built-in `ip_address`ships as an "IP" field.

It is **auto-registered as a navigable resource**, so an "Action Events" entry appears in the Nova sidebar and you can browse every event with its columns — no `Nova::resources()` wiring required. Events also appear on a record's detail page (Nova's built-in action-event feed). To opt out of the navigation entry — to register your own resource, or to keep Nova's default where events show only on detail pages — set `register_resource` to `false` (env `NOVA_ACTION_EVENT_COLUMNS_REGISTER_RESOURCE`).

### The `action-events:prune` command

[](#the-action-eventsprune-command)

Retention for the `action_events` table:

```
# Delete events older than 365 days (chunked)
php artisan action-events:prune --days=365

# Or by hours
php artisan action-events:prune --hours=48

# Wipe everything (TRUNCATE, resets the auto-increment)
php artisan action-events:prune --all

# Skip the production confirmation prompt
php artisan action-events:prune --days=365 --force
```

A window (`--days` / `--hours`) or `--all` is required — with neither, the command refuses. It is **never auto-scheduled**; wire it up yourself if you want it periodic:

```
// routes/console.php
Schedule::command('action-events:prune --days=365 --force')->daily();
```

### TrustProxies caveat

[](#trustproxies-caveat)

`request()->ip()` reflects the real client only if your app trusts its proxies. Behind a load balancer, configure trusted proxies so the forwarded header is honoured:

```
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(headers: Request::HEADER_X_FORWARDED_FOR);
})
```

If you trust proxies as `*`, the forwarded IP is client-spoofable — treat `ip_address` as a best-effort audit signal, not hard proof.

Testing
-------

[](#testing)

```
composer test            # Pest suite
composer test-coverage   # 100% line coverage on src/
composer analyse         # PHPStan level 8
composer format          # Pint (laravel preset + strict types)
```

A full embedded Nova app (via [Orchestra Workbench](https://github.com/orchestral/workbench)) lets you exercise the flow in a real Nova instance:

```
composer serve   # boots Nova at http://localhost:8000/nova
```

Security
--------

[](#security)

The built-in `ip_address` is captured on a best-effort basis and is only trustworthy when proxies are configured correctly (see the TrustProxies caveat). If you discover a security issue, please email `paris@big-boss-studio.com` instead of using the issue tracker.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Credits
-------

[](#credits)

- [Big Boss Studio](https://github.com/BBS-Lab)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5689944?v=4)[Mikaël Popowicz](/maintainers/mikaelpopowicz)[@mikaelpopowicz](https://github.com/mikaelpopowicz)

![](https://www.gravatar.com/avatar/c1edc17683ed39a2cc6dbe453c2c5aaa63468fc5b54f13941f260ebe260da211?d=identicon)[Kezho](/maintainers/Kezho)

---

Tags

laravelsecurityAuditnovaactivity-loglaravel-novabbsaction-events

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/bbs-lab-nova-action-event-columns/health.svg)

```
[![Health](https://phpackages.com/badges/bbs-lab-nova-action-event-columns/health.svg)](https://phpackages.com/packages/bbs-lab-nova-action-event-columns)
```

###  Alternatives

[laravel-chronicle/core

Tamper-evident audit ledger for Laravel applications.

1213.7k6](/packages/laravel-chronicle-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
