Commit Graph
9 Commits
Author SHA1 Message Date
jaredandClaude Opus 4.8 2b8d593ab0 Fix issues found in multi-agent code review
Lint / PHP (phpcs PSR-12) (push) Successful in 28s
Lint / JS (eslint) (push) Successful in 19s
Security / PHP Security (semgrep) (push) Failing after 42s
Lint / Deploy (push) Successful in 3s
Lint / Notify on failure (push) Has been skipped
Verified, high-confidence fixes from a project-wide review:

- markdown.js: escape " and ' in the HTML-escape step. User-controlled
  image/link URLs and alt text were interpolated into "..." attributes
  without quote escaping, allowing attribute breakout and injected event
  handlers (stored XSS, only mitigated by CSP). Flagged independently by
  two reviewers.
- cron/create_recurring_tickets.php & cron/cleanup_ratelimit.php: a
  mangled crontab example inside the docblock contained */ which closed
  the comment early, causing a fatal parse error — both cron jobs never
  ran. Rewrote the docblocks without a literal */.
- update_ticket.php: validate visibility BEFORE the core DB write so an
  invalid payload can't leave the ticket updated while the request reports
  failure (which also skipped the audit delta and stats cache invalidation).
- watch_ticket.php: GET watcher_count was capped at 6 (count of a LIMIT 6
  list); use an unbounded COUNT(*) so it matches the POST path.
- notifications.php: "assigned to me" LIKE pattern lacked a trailing
  delimiter, so user 12 also matched 120/123/etc.; anchor with }.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:14:38 -04:00
jared c90bdc8ac8 style: auto-fix 1340 phpcs PSR-12 violations via phpcbf; exclude MissingNamespace and SideEffects
Lint / PHP (phpcs PSR-12) (push) Failing after 29s
Lint / JS (eslint) (push) Successful in 12s
2026-04-13 20:56:10 -04:00
jaredandClaude Sonnet 4.6 60f23051a9 Fix notifications not detecting comment events
AuditLogModel::logCommentCreate logs comments with action_type='comment'
not 'create'. The notification query was filtering on action_type='create'
only, so comment events on watched/owned tickets were never surfaced.

Widen the filter to IN ('comment', 'create') to match the actual logged
values while staying compatible with any legacy entries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 13:45:04 -04:00
jaredandClaude Sonnet 4.6 d295d64f85 Fix leading-zero ticket ID handling across API and UI
- dashboard.js: use String(cb.value) instead of parseInt() in
  getSelectedTicketIds() so zero-padded IDs like 000123456 are
  preserved when sent to bulk_operation.php
- DashboardView.php: remove (int) cast on data-ticket-id attribute
  for quick-status button; was stripping leading zeros
- TicketView.php: remove (int) cast on export URL ticket_id param
- update_ticket.php: preserve ticket_id as string via trim((string)...)
- add_comment.php: preserve ticket_id as string; validate with
  ctype_digit instead of (int) cast so comments are stored with the
  canonical zero-padded ID matching the tickets table
- export_tickets.php: validate singleId as string to avoid stripping
  leading zeros in the export endpoint
- notifications.php: preserve ticket_id strings in URLs and ticket
  ownership checks; index myTicketIds by both int and string forms
  for robust lookup regardless of how audit_log stored the ID
- TicketController.php: fix inline dependency insert — column was
  wrong (depends_on_ticket_id → depends_on_id) and bind types were
  wrong ("iii" → "ssi"); feature was silently broken

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 12:43:18 -04:00
jaredandClaude Sonnet 4.6 bc88ba3612 Fix notifications 500 (audit_id column), smart resolution time units
- notifications.php: audit_log PK is audit_id not log_id; alias all
  three queries with audit_id AS log_id to fix 500 error
- DashboardView: avg resolution time now picks best unit automatically
  (min < 1h, hr < 48h, days < 14d, wks otherwise) with full hours
  shown in title tooltip; adds lt-stat-unit CSS for the suffix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 11:32:02 -04:00
jaredandClaude Sonnet 4.6 5e04478586 Fix parse error in notifications.php: escape inner quotes in LIKE string
The $statusSql double-quoted string contained '%"status":%' which caused
PHP to terminate the string at the inner double quotes, resulting in a
parse error (unexpected identifier 'status') on the beta server.

Also cleared stale stats cache that stored by_assignee in old name=>count
map format instead of the current array-of-objects format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 11:25:26 -04:00
jaredandClaude Sonnet 4.6 ac05b212b2 Fix performAdvancedSearch ReferenceError, settings save, sort reset, notifications 500, CSP
DashboardView.php: wrap performAdvancedSearch in a closure so it is
resolved at event-fire time rather than listener-registration time
(advanced-search.js loads later via pageScripts so the bare identifier
reference caused ReferenceError).

DashboardView.php: reset sort URL to page=1 so sorting all pages
instead of staying on the current page.

dashboard.js: add missing save-settings and close-settings cases to
the click delegation handler (were removed in a prior session under
the assumption they were in dashboard.js, but they were not).

notifications.php: replace JSON_EXTRACT-based comment join (not
universally supported) with a two-step PHP filter: fetch owner/watcher
ticket IDs first, then filter raw comment rows in PHP. Also fix the
status change LIKE pattern to match the actual logTicketUpdate format
{"status": {"from": ..., "to": ...}}.

SecurityHeadersMiddleware.php: add https://cdn.jsdelivr.net to
connect-src so Chart.js source maps load without CSP violations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 10:53:06 -04:00
jaredandClaude Sonnet 4.6 df6c4de196 Fix notification comment query, status title, and is-hidden visibility
notifications.php: comment notifications never fired because the query
used action_type='comment'/entity_type='ticket' but logCommentCreate
logs action_type='create'/entity_type='comment'. Fix query to match
actual log format and extract ticket_id from details JSON.

notifications.php: status change notification titles always showed
"? → ?" because code read details.old_value/new_value but logTicketUpdate
stores the delta as {"status": {"from": ..., "to": ...}}.

base.css: move .is-hidden to base.css (global) — it was only defined in
ticket.css, so on the dashboard the ticket-preview popup had no hide
rule applied and was visible in the DOM at all times.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 10:47:39 -04:00
jaredandClaude Sonnet 4.6 3c29c6ee6f feat: SLA live timer, notification bell, lt-toggle MD, right drawer, kanban drag-drop
- TicketView: SLA banner now shows live HH:MM:SS elapsed + countdown via JS setInterval
  (previously showed static hours from PHP)
- TicketView: Markdown toggles in comment form replaced with lt-toggle switches
- layout_header: In-app notification bell (🔔) with dropdown panel for all users
- layout_footer: Notification JS — polls /api/notifications.php every 60s, badge count,
  mark-all-read, panel open/close with Escape/outside-click
- api/notifications.php (new): Returns assign/comment/status-change events from audit_log
  for current user's tickets and watched tickets; mark-read via user_preferences
- DashboardView: Ticket preview right drawer — Ctrl+click title or ⊙ peek button
  opens lt-drawer-right with ticket summary extracted from table row DOM
- DashboardView: lt.sortable wired on all 4 kanban columns (group='kanban')
  Cross-column drag = status change via POST /api/update_ticket.php with optimistic UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 17:21:21 -04:00