Skip to content

Tenant Audit Logs & Impersonation History — Production Readiness

FieldValue
Date2026-08-17
StatusGo for production after companion CI green + staging smoke
ScopeCentral tenant details: Impersonation history + platform Audit Logs
Branchfeature/tenant-audit-impersonation-history
Backendb27abb1 + remediations
Frontend1d240a39 + remediations

Companion docs: Admin UI · Central API v1 · Authentication · Changelog


Executive summary

Central already wrote impersonation and platform audit events; this ship surfaces them on tenant details:

TabDataPermission
Impersonationimpersonation_sessionsimpersonation.list
Audit LogsSpatie activity_log (platform) for the workspacetenants.read

Does not redesign auth, tenancy, or audit write paths (platform freeze).

Go / No-Go: Go — prior residuals remediated; no hard blockers remain.

GateResult
Authz (impersonation.list / tenants.read)Pass
Tenant isolationPass
List responses omit tokensPass
Audit list properties allowlisted (no before/after blobs)Pass
Pagination / sort allowlistsPass
Central session resume after end (resumeToken + skipSessionExpiry)Pass
Impersonation Expired status (is_expired + UI badge)Pass
FE permission gates + ErrorState on tab fetch failurePass
Pest Impersonation + TenantAuditLogPass
Playwright one-session validation + historyPass (impersonation + tenants.view)
Docs admin-ui / central-v1 / authentication / changelogPass
MySQL migration (activity_log.properties_tenant_id index)Pass — run on deploy

Security summary

ControlStatus
Central API auth + verified + not.suspendedPass
Policy viewAnyimpersonation.listPass
Tenant viewtenants.read for audit listPass
Query scoped to route tenantPass
No tenant_token / PAT id on list resourcePass
Audit list redacts non-allowlisted properties keysPass
Resume central admin after end (even if end API fails)Pass

Residual risk — remediated

IDItemResolution
M1Full audit properties visible to tenants.readRemediatedTenantAuditLogResource allowlists public keys; before / after and other unreviewed keys omitted from list responses.
L1Audit tab not FE-gated like ImpersonationRemediated — both tabs check tenants.read / impersonation.list; restricted empty state when permission missing; ErrorState on failed fetch.
L2isActive() ignores expires_atRemediatedisActive() / isExpired() honour expires_at; list resource exposes is_expired; UI shows Expired badge.
L3JSON properties->tenant_id unindexedRemediated — migration 2026_08_17_040000_add_activity_log_properties_tenant_id_index adds MySQL virtual column + index.

Test evidence

SuiteResultNotes
Pest ImpersonationTest + TenantAuditLogTestPassAuthz, isolation, allowlisted properties, is_expired
Playwright test:e2e:impersonationPassValidation, start/end, history tabs
Playwright tenants.viewPassTabs not placeholder; permission empty states

Staging smoke

  1. Open an active workspace → Impersonation / Audit Logs tabs (no “not available yet”).
  2. Impersonate with empty / short reason → client validation (≥ 5 chars).
  3. Start with a real reason → End impersonation → land on Central dashboard as same admin (verify resumeToken restore).
  4. Impersonation tab shows the reason and Ended status; expired open sessions show Expired.
  5. Audit Logs shows impersonation_started (and ended) with allowlisted properties (reason visible; no before/after blobs in network payload).
  6. Role without impersonation.list → restricted empty state on Impersonation tab (not a silent empty table).
  7. Role without tenants.read → restricted empty state on Audit Logs tab.
  8. Simulate audit-list API failure (or revoke permission mid-session) → ErrorState with retry, not a blank table.

Deploy

  • Run migrations before traffic: php artisan migrate --force (includes 2026_08_17_040000_add_activity_log_properties_tenant_id_index — MySQL/MariaDB virtual column on activity_log.properties->tenant_id). No-op on SQLite test runs.
  • Deploy Backend + Frontend + Docs companions together.
  • Confirm Central roles that should view history have impersonation.list (already in central-permissions; sync via existing Permissions / Role seeders if a custom role lacks it).
  • tenants.read still required for Audit Logs; list responses no longer expose full property blobs.

Sign-off

RoleDecisionDate
EngineeringGo2026-08-17
Ops☐ Staging smoke
ProductGo — M1 accepted remediation2026-08-17

Current decision (2026-08-17): Go — merge after CI green; complete staging smoke before production traffic.

Official documentation for the EloSync SaaS Platform.