Bulk-operation audit_log entries use a different shape than every other status-change path, breaking the timeline and in-app notifications #74

Open
opened 2026-09-01 00:07:11 -04:00 by jared · 0 comments
Owner

Severity: Medium

Single-edit (api/update_ticket.php) and Bearer API (api/ticket_status_api.php) paths log status changes via AuditLogModel::logTicketUpdate() with a {'status': {'from': X, 'to': Y}} shape. models/BulkOperationsModel.php instead logs ['status' => 'Closed', 'bulk_operation_id' => ...] — a bare string.

Impact — two downstream consumers silently degrade for bulk-originated rows:

  1. views/TicketView.php (~lines 67-74, case 'update':) — the field-name extractor requires is_array($v) && isset($v['from'],$v['to']); a bare string fails this, so the ticket timeline shows generic "updated this ticket" for a bulk status change instead of "updated status" (which single-edit/API paths correctly get).
  2. api/notifications.php (~lines 229-231) — $details['status']['from'] on a string triggers a PHP array-offset-on-string warning and falls through to ?? '?' for both from/to, producing a broken in-app notification title: "{actor} changed status on #NNN: ? → ?" for any notification derived from a bulk status change.

Fix: Change BulkOperationsModel's audit log call to use the same {'status': {'from': ..., 'to': ...}} shape as AuditLogModel::logTicketUpdate(), keeping bulk_operation_id as an additional metadata field alongside it.

**Severity:** Medium Single-edit (`api/update_ticket.php`) and Bearer API (`api/ticket_status_api.php`) paths log status changes via `AuditLogModel::logTicketUpdate()` with a `{'status': {'from': X, 'to': Y}}` shape. `models/BulkOperationsModel.php` instead logs `['status' => 'Closed', 'bulk_operation_id' => ...]` — a bare string. **Impact — two downstream consumers silently degrade for bulk-originated rows:** 1. `views/TicketView.php` (~lines 67-74, `case 'update':`) — the field-name extractor requires `is_array($v) && isset($v['from'],$v['to'])`; a bare string fails this, so the ticket timeline shows generic "updated this ticket" for a bulk status change instead of "updated status" (which single-edit/API paths correctly get). 2. `api/notifications.php` (~lines 229-231) — `$details['status']['from']` on a string triggers a PHP array-offset-on-string warning and falls through to `?? '?'` for both `from`/`to`, producing a broken in-app notification title: `"{actor} changed status on #NNN: ? → ?"` for any notification derived from a bulk status change. **Fix:** Change `BulkOperationsModel`'s audit log call to use the same `{'status': {'from': ..., 'to': ...}}` shape as `AuditLogModel::logTicketUpdate()`, keeping `bulk_operation_id` as an additional metadata field alongside it.
jared added the data-integritynotificationspriority/medium labels 2026-09-08 10:15:47 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/tinker_tickets#74