Found while verifying #21 against the live schema: the model writes
'completed_with_errors' (21 chars) when a bulk operation finishes with
per-ticket failures, but bulk_operations.status was varchar(20), so the
write failed with "Data too long for column 'status'".
This was latent — bulk status changes previously forced every transition
through, so failed was always 0. Now that they honour the Workflow
Designer, a partially-skipped batch is a normal outcome and hits it.
- migrations/001 widens the column to varchar(32) (idempotent).
- The baseline is updated to match, for fresh installs.
- The bookkeeping UPDATE is wrapped in a try/catch: it runs after the
ticket changes are committed, so an instance deployed ahead of its
migrations must not turn a completed operation into an error response.
Verified against the live database with a disposable-ticket harness:
comment-required rejection changes nothing, undefined transitions are
refused per ticket with a reason, allowed transitions still work, mixed
batches apply the valid half, and an already-Closed ticket is a no-op.
Foundation for extending the Bearer API beyond create-only:
- api_keys gains a scope column (read | read_write); baseline schema updated
and the column applied to the live DB. Existing keys default to
read_write so the hwmon create key keeps working.
- ApiKeyModel: createKey() takes a validated scope; validateKey() always
surfaces scope (defaults read_write); getAllKeys() is paginated
({keys,total,page,perPage}, key_hash stripped).
- ApiKeyAuth: expose getKeyContext() (scope/key_name/created_by/api_key_id)
and requireScope() (403 on insufficient scope); existing return values
unchanged.
- create_ticket_api.php: require read_write scope (a read key can't create).
- Admin /admin/api-keys: scope selector on the create form, a scope column,
and pagination (revoked keys were stacking up).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- migrations/000_baseline.sql: full schema baseline captured from prod
(validated on a throwaway DB: 17 tables/17 FKs), so the schema is
reproducible for fresh installs / disaster recovery
- create_recurring_tickets cron: send the Matrix ticket-created
notification and invalidate the stats cache like the other create paths
- create_ticket_api.php + TicketController::create: invalidate the stats
cache on create/escalate/reopen so dashboard counts aren't stale
- scripts/cleanup_orphan_uploads.php: restored, made safe (24h mtime
grace, 9-digit-dir only, skips avatars/symlinks, matches the unique
filename column, --dry-run)
- cron/cleanup_audit_log.php: enforce the configured audit-log retention
(deleteOldLogs was implemented but never called)
- README: correct CSRF-rotation, hwmon dedup (no 24h window), SLA (no P3),
stats-cache callers, and the project structure/endpoint listing
- .env.example: document TRUSTED_PROXIES fail-open risk and .env quoting
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All SQL migration files have been applied and recorded in the migrations
tracking table. Folder intentionally empty — migrate.php kept as runner
for future one-time schema changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CreateTicketView: "Link as duplicate" button on each duplicate result;
stores chosen ticket ID in hidden field, auto-creates duplicates dependency
after ticket is saved (TicketController)
- migrations/004: ticket_watchers table (ticket_id, user_id primary key)
- migrations/005: FULLTEXT index on tickets(title, description) for fast
relevance search replacing LIKE scan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add comment threading/reply functionality with nested display
- Database migration for parent_comment_id and thread_depth columns
- Recursive comment rendering with depth-based indentation
- Reply form with inline UI and smooth animations
- Thread collapse/expand capability
- Max thread depth of 3 levels
- Fix 401 authentication errors on API calls
- Add credentials: 'same-origin' to all fetch calls
- Affects settings.js, ticket.js, dashboard.js, advanced-search.js
- Ensures session cookies are sent with requests
- Enhanced comment styling
- Thread connector lines for visual hierarchy
- Reply button on comments (up to depth 3)
- Quote block styling for replies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Consolidate all 20 API files to use centralized Database helper
- Add optimistic locking to ticket updates to prevent concurrent conflicts
- Add caching to StatsModel (60s TTL) for dashboard performance
- Add health check endpoint (api/health.php) for monitoring
- Improve rate limit cleanup with cron script and efficient DirectoryIterator
- Enable rate limit response headers (X-RateLimit-*)
- Add audit logging for workflow transitions
- Log Discord webhook failures instead of silencing
- Fix visibility check on export_tickets.php
- Add database migration system with performance indexes
- Fix cron recurring tickets to use assignTicket method
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix collapsible sidebar toggle button positioning (moved outside sidebar)
- Toggle button now stays visible when sidebar is collapsed
- Update cache busting version
- Update Claude.md with new features documentation
- Update README.md with new features documentation
- Remove migrations folder (no longer needed)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add admin dropdown menu in dashboard header with links to all admin pages
- Fix template modal: larger size (800px), responsive grid, type/priority dropdowns
- Fix recurring tickets modal: add Type and Assign To fields, larger size
- Make dashboard stat cards clickable for quick filtering
- Fix user-activity query (remove is_active requirement)
- Add table existence check in ticket_dependencies API
- Fix table overflow on dashboard
- Update Claude.md and README.md with current project status
- Remove migrations directory (all migrations completed)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Completely rewrote README with all new features and admin routes
- Cleaned up remaining migration files
- Added detailed PHP error/exception handlers to dependencies API
to help debug the 500 error
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add detailed error handling in DependencyModel (throw exceptions on failure)
- Add try-catch in ticket_dependencies.php to catch query errors
- Remove all old migrations (001-014) that have already been run
- Keep only new feature migrations (015-018) for reference
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create CsrfMiddleware.php with token generation and validation
- Add database indexes for ticket_comments and audit_log
- Includes rollback script for safe deployment
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed all reported issues:
1. **Dark Mode Improvements:**
- Fixed bulk-actions-info white on white text (now yellow on dark background)
- Fixed timeline-content boxes with explicit dark mode colors
- All text now properly visible in dark mode
2. **Dashboard Enhancement:**
- Added "Assigned To" column showing ticket assignments
- Updated TicketModel query to include assigned user information
- Shows "Unassigned" when no user assigned
3. **Removed Ticket View Tracking:**
- Removed logTicketView call from TicketController
- Created migration 011 to delete all view records from audit_log
- Viewing tickets no longer clutters activity timeline
4. **Removed Duplicate Status Dropdown:**
- Removed status field from hamburger menu
- Status can now only be changed via the workflow-validated dropdown in ticket header
- Prevents confusion and ensures all status changes follow workflow rules
All changes improve usability and reduce clutter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>