# S34-012 Assumptions — Tenant Activity Log (P-044)

## What was implemented

`ActivityLog.php` — a tenant-scoped read query class that reads from the existing `activity_log` table (extended with `tenant_id`, `severity`, `action`, `module`, etc. in prior sprints). Provides:

- `paginate()` — filterable by causer_id, action, module, severity, from/until date, and description search
- `find()` — single entry drill-down, scoped to tenant
- `distinctActions()` / `distinctModules()` — dropdown population helpers

Three controllers wired to routes:
- `GET /settings/activity-log` — paginated list with filter params
- `GET /settings/activity-log/filters` — distinct filter values
- `GET /settings/activity-log/{activityId}` — drill-down single entry

All routes are TA-only (403 for `tenant_user`).

## AC items NOT implemented (out of scope for this task)

The AC for ONB-TA-12 describes a full feature spanning multiple future tasks. The following items are explicitly deferred:

1. **CSV/Excel export** — not in `files_touched` for this task. Requires a separate export action + job. Deferred.
2. **PDPA PII redaction** — `PDPA-SYS-01` redaction belongs to Sprint 17 (PDPA Basic). The activity log query class returns raw `attribute_changes` JSON. PII redaction will be applied as a transform layer in that sprint.
3. **7-year / indefinite retention enforcement** — retention policy is already tracked via `retention_class` column on `activity_log`. Enforcement (purge jobs) is covered by Sprint 18 (Production Logging).
4. **Full-text search on `attribute_changes` / `properties` JSON** — current search filters on `description` and `subject_type`. JSON full-text would require a GIN index and separate migration. Not in `files_touched`; deferred.
5. **Large-value transaction events** — the task title says "all settings changes". Transaction events being surfaced in the tenant log is a separate cross-domain concern.

## Architectural notes

- `ActivityLog.php` placed in `app/Domain/Onboarding/` (not `Models/`) — it's a query class, not an Eloquent model, consistent with the Action-class pattern.
- Uses `Illuminate\Pagination\LengthAwarePaginator` (concrete class) in the return type rather than the contract, to satisfy PHPStan generic type checking.
- Filter array uses `isset()` (not `!== null`) to distinguish "not provided" from "provided as null" — consistent with `$request->only()` which omits absent keys.
- Spatie's `Activity` model has no factory — tests use `Activity::create()` directly.
