Watch/unwatch actions are never logged to audit_log #93

Closed
opened 2026-09-01 00:08:21 -04:00 by jared · 1 comment
Owner

Severity: Low

api/watch_ticket.php performs the INSERT IGNORE/DELETE on ticket_watchers directly with no AuditLogModel call anywhere in the file. Every other ticket-adjacent mutation in the app (comments, attachments, dependencies, status/field changes) is logged, so this is either an intentional omission (watching arguably isn't audit-worthy) or a gap in the "Full lt-timeline audit trail" claim from the README.

Flagging for a decision rather than asserting it's wrong: if watcher add/remove events should show up in a ticket's timeline (e.g. "alice started watching this ticket"), add an AuditLogModel::log() call to both the watch and unwatch paths in api/watch_ticket.php. If intentionally excluded, no action needed.

**Severity:** Low `api/watch_ticket.php` performs the `INSERT IGNORE`/`DELETE` on `ticket_watchers` directly with no `AuditLogModel` call anywhere in the file. Every other ticket-adjacent mutation in the app (comments, attachments, dependencies, status/field changes) is logged, so this is either an intentional omission (watching arguably isn't audit-worthy) or a gap in the "Full lt-timeline audit trail" claim from the README. Flagging for a decision rather than asserting it's wrong: if watcher add/remove events should show up in a ticket's timeline (e.g. "alice started watching this ticket"), add an `AuditLogModel::log()` call to both the watch and unwatch paths in `api/watch_ticket.php`. If intentionally excluded, no action needed.
jared added the needs-decisionpriority/low labels 2026-09-08 10:15:49 -04:00
Author
Owner

Decision: log it. Fixed in commit e91f454 (merged to main in d0a7630).

Added AuditLogModel::log() calls to both the watch and unwatch paths in api/watch_ticket.php, gated on affected_rows so a no-op (already watching/not watching) doesn't produce a duplicate timeline entry. Timeline now renders 'started watching this ticket' / 'stopped watching this ticket'.

Verified against real MariaDB: watch -> unwatch -> watch again produces exactly 2 timeline entries, not 4 — the no-op repeats correctly logged nothing.

Decision: log it. Fixed in commit e91f454 (merged to main in d0a7630). Added AuditLogModel::log() calls to both the watch and unwatch paths in api/watch_ticket.php, gated on affected_rows so a no-op (already watching/not watching) doesn't produce a duplicate timeline entry. Timeline now renders 'started watching this ticket' / 'stopped watching this ticket'. Verified against real MariaDB: watch -> unwatch -> watch again produces exactly 2 timeline entries, not 4 — the no-op repeats correctly logged nothing.
jared closed this issue 2026-09-12 01:21:14 -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#93