Files
tinker_tickets/Claude.md
2026-01-01 19:45:49 -05:00

24 KiB

Tinker Tickets - Project Documentation for AI Assistants

Project Status (January 2026)

Current Phase: All 5 core features implemented and deployed. Ready for ANSI Art redesign.

Recent Completion:

  • Activity Timeline (Feature 1)
  • Ticket Assignment (Feature 2)
  • Status Transitions with Workflows (Feature 3)
  • Ticket Templates (Feature 4)
  • Bulk Actions - Admin Only (Feature 5)

Next Priority: 🎨 ANSI Art Redesign (major visual overhaul)

Project Overview

Tinker Tickets is a feature-rich, self-hosted ticket management system built for managing data center infrastructure issues. It features SSO integration with Authelia/LLDAP, workflow management, Discord notifications, and a comprehensive web interface.

Tech Stack:

  • Backend: PHP 7.4+ with MySQLi
  • Frontend: Vanilla JavaScript, CSS3
  • Database: MariaDB on separate LXC (10.10.10.50)
  • Web Server: Apache on production (10.10.10.45)
  • Authentication: Authelia SSO with LLDAP backend
  • External Libraries: marked.js (Markdown rendering)

Production Environment:

  • Primary URL: http://t.lotusguild.org
  • Web Server: Apache at 10.10.10.45 (/root/code/tinker_tickets)
  • Database: MariaDB at 10.10.10.50 (ticketing_system database)
  • Authentication: Authelia provides SSO via headers

Architecture

MVC Pattern

Controllers → Models → Database
     ↓
   Views

Project Structure (Updated)

/tinker_tickets/
├── api/                                  # API endpoints
│   ├── add_comment.php                   # POST: Add comment
│   ├── assign_ticket.php                 # POST: Assign ticket to user (NEW)
│   ├── bulk_operation.php                # POST: Bulk operations - admin only (NEW)
│   ├── get_template.php                  # GET: Fetch ticket template (NEW)
│   ├── get_users.php                     # GET: Get user list (NEW)
│   └── update_ticket.php                 # POST: Update ticket (workflow validation)
├── assets/
│   ├── css/
│   │   ├── dashboard.css                 # Shared + dashboard + bulk actions
│   │   └── ticket.css                    # Ticket + timeline + dark mode fixes
│   ├── js/
│   │   ├── dashboard.js                  # Dashboard + hamburger + bulk actions + templates
│   │   └── ticket.js                     # Ticket + comments + status updates + assignment
│   └── images/
│       └── favicon.png
├── config/
│   └── config.php                        # Config + .env loading
├── controllers/                           # MVC Controllers
│   ├── DashboardController.php           # Dashboard with assigned_to column
│   └── TicketController.php              # Ticket CRUD + timeline + templates
├── models/                                # Data models
│   ├── AuditLogModel.php                 # Audit logging + timeline
│   ├── BulkOperationsModel.php           # Bulk operations tracking (NEW)
│   ├── CommentModel.php                  # Comment data access
│   ├── TemplateModel.php                 # Ticket templates (NEW)
│   ├── TicketModel.php                   # Ticket CRUD + assignment
│   ├── UserModel.php                     # User management (NEW)
│   └── WorkflowModel.php                 # Status transition workflows (NEW)
├── views/                                 # PHP templates
│   ├── CreateTicketView.php              # Ticket creation with templates
│   ├── DashboardView.php                 # Dashboard with bulk actions + assigned column
│   └── TicketView.php                    # Ticket view with timeline + assignment
├── migrations/                            # Database migrations
│   ├── 001_initial_schema.sql
│   ├── 007_add_ticket_assignment.sql     # Ticket assignment
│   ├── 008_add_status_workflows.sql      # Workflow rules
│   ├── 009_add_ticket_templates.sql      # Ticket templates
│   ├── 010_add_bulk_operations.sql       # Bulk operations
│   └── 011_remove_view_tracking.sql      # Remove view audit logs
├── .env                                   # Environment variables (GITIGNORED)
├── Claude.md                              # This file
├── README.md                              # User documentation
├── index.php                              # Dashboard entry point
└── ticket.php                             # Ticket view/create router

Database Schema (Updated)

Database: ticketing_system at 10.10.10.50 User: tinkertickets Connection: All APIs create their own connections via config.php

Core Tables

tickets Table (Updated)

CREATE TABLE tickets (
  ticket_id INT AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  status VARCHAR(50) DEFAULT 'Open',
  priority INT DEFAULT 4,
  category VARCHAR(50) DEFAULT 'General',
  type VARCHAR(50) DEFAULT 'Issue',
  created_by INT,                               -- User who created
  updated_by INT,                               -- User who last updated
  assigned_to INT,                              -- User assigned to (NEW)
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (created_by) REFERENCES users(user_id),
  FOREIGN KEY (updated_by) REFERENCES users(user_id),
  FOREIGN KEY (assigned_to) REFERENCES users(user_id) ON DELETE SET NULL,
  INDEX idx_status (status),
  INDEX idx_assigned_to (assigned_to)
) ENGINE=InnoDB;

users Table (SSO Integration)

CREATE TABLE users (
  user_id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(100) UNIQUE NOT NULL,
  display_name VARCHAR(255),
  email VARCHAR(255),
  is_admin BOOLEAN DEFAULT FALSE,
  last_login TIMESTAMP NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

comments Table

CREATE TABLE comments (
  comment_id INT AUTO_INCREMENT PRIMARY KEY,
  ticket_id INT NOT NULL,
  user_id INT,
  comment_text TEXT NOT NULL,
  markdown_enabled BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (ticket_id) REFERENCES tickets(ticket_id) ON DELETE CASCADE,
  FOREIGN KEY (user_id) REFERENCES users(user_id),
  INDEX idx_ticket_id (ticket_id)
) ENGINE=InnoDB;

audit_log Table (Activity Timeline)

CREATE TABLE audit_log (
  log_id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT,
  action_type VARCHAR(50) NOT NULL,             -- 'create', 'update', 'comment', 'assign', etc.
  entity_type VARCHAR(50) NOT NULL,             -- 'ticket', 'comment'
  entity_id INT NOT NULL,                       -- ticket_id or comment_id
  details JSON,                                  -- JSON details of what changed
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(user_id),
  INDEX idx_entity (entity_type, entity_id),
  INDEX idx_user (user_id),
  INDEX idx_action (action_type)
) ENGINE=InnoDB;

status_transitions Table (Workflow Rules)

CREATE TABLE status_transitions (
  transition_id INT AUTO_INCREMENT PRIMARY KEY,
  from_status VARCHAR(50) NOT NULL,
  to_status VARCHAR(50) NOT NULL,
  requires_comment BOOLEAN DEFAULT FALSE,        -- Transition requires comment
  requires_admin BOOLEAN DEFAULT FALSE,          -- Transition requires admin
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY unique_transition (from_status, to_status),
  INDEX idx_from_status (from_status)
) ENGINE=InnoDB;

Default transitions:

-- Open → In Progress, Closed, Resolved
-- In Progress → Open, Closed, Resolved
-- Resolved → Closed, In Progress
-- Closed → Open, In Progress (requires comment)

ticket_templates Table

CREATE TABLE ticket_templates (
  template_id INT AUTO_INCREMENT PRIMARY KEY,
  template_name VARCHAR(100) NOT NULL,
  title_template VARCHAR(255) NOT NULL,
  description_template TEXT NOT NULL,
  category VARCHAR(50),
  type VARCHAR(50),
  default_priority INT DEFAULT 4,
  created_by INT,
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (created_by) REFERENCES users(user_id),
  INDEX idx_template_name (template_name)
) ENGINE=InnoDB;

Default templates: Hardware Failure, Software Installation, Network Issue, Maintenance Request

bulk_operations Table

CREATE TABLE bulk_operations (
  operation_id INT AUTO_INCREMENT PRIMARY KEY,
  operation_type VARCHAR(50) NOT NULL,          -- 'bulk_close', 'bulk_assign', 'bulk_priority'
  ticket_ids TEXT NOT NULL,                     -- Comma-separated ticket IDs
  performed_by INT NOT NULL,
  parameters JSON,                               -- Operation parameters
  status VARCHAR(20) DEFAULT 'pending',
  total_tickets INT,
  processed_tickets INT DEFAULT 0,
  failed_tickets INT DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  completed_at TIMESTAMP NULL,
  FOREIGN KEY (performed_by) REFERENCES users(user_id),
  INDEX idx_performed_by (performed_by),
  INDEX idx_created_at (created_at)
) ENGINE=InnoDB;

API Endpoints (Updated)

Authentication

All API endpoints check: $_SESSION['user']['user_id'] for authentication. Admin-only endpoints check: $_SESSION['user']['is_admin'].

POST /api/update_ticket.php

Updates ticket with workflow validation.

Request:

{
  "ticket_id": 123,
  "status": "In Progress",    // Validated against workflow rules
  "priority": 2,
  "title": "Updated title",
  "description": "...",
  "category": "Software",
  "type": "Task"
}

Response:

{
  "success": true,
  "status": "In Progress",
  "priority": 2,
  "message": "Ticket updated successfully"
}

Features:

  • Workflow validation via WorkflowModel
  • Partial updates (only send changed fields)
  • User tracking (updated_by)
  • Discord webhook notifications
  • Audit logging

POST /api/assign_ticket.php (NEW)

Assigns ticket to a user.

Request:

{
  "ticket_id": 123,
  "assigned_to": 5   // user_id, or null to unassign
}

Response:

{
  "success": true
}

GET /api/get_users.php (NEW)

Returns list of all users for assignment dropdowns.

Response:

{
  "success": true,
  "users": [
    {
      "user_id": 1,
      "username": "jared",
      "display_name": "Jared Vititoe",
      "is_admin": true
    }
  ]
}

GET /api/get_template.php?template_id=1 (NEW)

Fetches a ticket template.

Response:

{
  "success": true,
  "template": {
    "template_id": 1,
    "template_name": "Hardware Failure",
    "title_template": "Hardware Failure: [Device Name]",
    "description_template": "Device: \nIssue: \n...",
    "category": "Hardware",
    "type": "Problem",
    "default_priority": 2
  }
}

POST /api/bulk_operation.php (NEW - ADMIN ONLY)

Performs bulk operations on tickets.

Request:

{
  "operation_type": "bulk_close",  // or 'bulk_assign', 'bulk_priority'
  "ticket_ids": [123, 456, 789],
  "parameters": {                   // For bulk_assign or bulk_priority
    "assigned_to": 5,               // For bulk_assign
    "priority": 2                   // For bulk_priority
  }
}

Response:

{
  "success": true,
  "operation_id": 42,
  "processed": 3,
  "failed": 0,
  "message": "Bulk operation completed: 3 succeeded, 0 failed"
}

POST /api/add_comment.php

Adds comment to ticket.

Request:

{
  "ticket_id": 123,
  "comment_text": "Comment content",
  "markdown_enabled": true
}

Response:

{
  "success": true,
  "user_name": "Jared Vititoe",
  "created_at": "Jan 01, 2026 12:00"
}

Key Features Implementation

Feature 1: Activity Timeline

Location: Ticket view → Activity tab

Implementation:

  • AuditLogModel->getTicketTimeline() - Fetches all events for a ticket
  • Shows: creates, updates, comments, assignments, status changes
  • Displays: user, action, timestamp, details
  • CSS: timeline-content boxes with icons
  • Dark mode: Fully supported

Code: views/TicketView.php:258-282, models/AuditLogModel.php:getTicketTimeline()

Feature 2: Ticket Assignment

Location: Ticket view → "Assigned to" dropdown, Dashboard → "Assigned To" column

Implementation:

  • Database: tickets.assigned_to column
  • Models: TicketModel->assignTicket(), TicketModel->unassignTicket()
  • API: api/assign_ticket.php
  • Dashboard: Shows assigned user in table
  • Auto-saves on change
  • Audit logged

Code: views/TicketView.php:170-181, assets/js/ticket.js:handleAssignmentChange()

Feature 3: Status Transitions with Workflows

Location: Ticket view → Status dropdown (header)

Implementation:

  • Database: status_transitions table defines allowed transitions
  • Models: WorkflowModel->isTransitionAllowed(), WorkflowModel->getAllowedTransitions()
  • Dropdown shows only valid transitions for current status
  • Server-side validation prevents invalid changes
  • Can require comments or admin privileges
  • Removed from hamburger menu (was duplicate)

Code: models/WorkflowModel.php, api/update_ticket.php:130-144, views/TicketView.php:185-198

Feature 4: Ticket Templates

Location: Create ticket page → Template selector

Implementation:

  • Database: ticket_templates table
  • Models: TemplateModel->getAllTemplates(), TemplateModel->getTemplateById()
  • API: api/get_template.php
  • JavaScript: loadTemplate() in dashboard.js
  • Auto-fills: title, description, category, type, priority
  • 4 default templates included

Code: views/CreateTicketView.php:27-39, assets/js/dashboard.js:loadTemplate()

Feature 5: Bulk Actions (Admin Only)

Location: Dashboard → Checkboxes + Toolbar (admins only)

Implementation:

  • Database: bulk_operations table tracks operations
  • Models: BulkOperationsModel->processBulkOperation()
  • API: api/bulk_operation.php
  • UI: Toolbar appears when tickets selected
  • Operations: Bulk close, bulk assign, bulk priority
  • All operations audit logged
  • Server-side admin validation

Code: views/DashboardView.php:176-188, assets/js/dashboard.js:bulkClose(), models/BulkOperationsModel.php

Authentication & SSO Integration

Authelia Integration

User information passed via HTTP headers:

  • Remote-User: Username
  • Remote-Name: Display name
  • Remote-Email: Email
  • Remote-Groups: Comma-separated groups

Session Management

$_SESSION['user'] = [
    'user_id' => 123,
    'username' => 'jared',
    'display_name' => 'Jared Vititoe',
    'email' => 'jared@lotusguild.org',
    'is_admin' => true  // true if 'admins' in Remote-Groups
];

Admin Privileges

  • Bulk operations (close, assign, priority)
  • Future: Admin-only transitions

Frontend Components (Updated)

Dashboard (DashboardView.php + dashboard.js)

Features:

  • Sortable columns including new "Assigned To" column
  • Search (title, description, ticket_id, category, type)
  • Status filtering (default: Open + In Progress)
  • Pagination (configurable)
  • Dark mode toggle
  • Bulk Actions Toolbar (admin only):
    • Checkboxes on each ticket
    • "Select All" checkbox
    • Bulk close, assign, priority buttons
    • Shows count of selected tickets

Hamburger Menu:

  • Category/Type filtering
  • Apply/Clear filters
  • No status field (removed)

Ticket View (TicketView.php + ticket.js)

Features:

  • Tabbed Interface: Description, Comments, Activity
  • Activity Timeline: Complete audit trail with icons
  • Assignment Dropdown: Assign to users
  • Status Dropdown: Workflow-validated status changes (header)
  • Hamburger Menu: Priority, Category, Type editing
  • Edit Button: Title and description editing
  • Markdown Comments: With live preview
  • Dark Mode: Comprehensive support

Visual Indicators:

  • Priority colors (P1=Red, P2=Orange, P3=Blue, P4=Green, P5=Gray)
  • Status badges (Open=Green, In Progress=Yellow, Closed=Red, Resolved=Green)
  • Priority border colors on ticket container

Create Ticket (CreateTicketView.php)

Features:

  • Template Selector: Quick-fill from templates
  • Standard fields: title, description, status, priority, category, type
  • Form validation
  • Discord webhook on creation

Dark Mode (Fixed)

Comprehensive Dark Mode CSS

Files: assets/css/ticket.css, assets/css/dashboard.css

Colors:

body.dark-mode {
  --bg-primary: #1a202c;      /* Main background */
  --bg-secondary: #2d3748;    /* Cards, inputs */
  --bg-tertiary: #4a5568;     /* Hover states */
  --text-primary: #e2e8f0;    /* Main text */
  --text-secondary: #cbd5e0;  /* Secondary text */
  --text-muted: #a0aec0;      /* Muted text */
  --border-color: #4a5568;    /* Borders */
}

Fixed Elements:

  • Timeline boxes (background + text)
  • Bulk actions toolbar
  • Tables and table rows
  • Input fields and textareas
  • Dropdowns and selects
  • Comment boxes
  • Modal dialogs
  • All text elements

Important: Used !important flags to override any conflicting styles.

Configuration

Environment Variables (.env)

DB_HOST=10.10.10.50
DB_USER=tinkertickets
DB_PASS=password
DB_NAME=ticketing_system
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...

CRITICAL: .env is gitignored! Never commit this file.

Apache Configuration

Virtual Host: Apache serving from /root/code/tinker_tickets

<VirtualHost *:80>
    ServerName t.lotusguild.org
    DocumentRoot /root/code/tinker_tickets

    <Directory /root/code/tinker_tickets>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

        RewriteEngine On
        RewriteBase /
        RewriteRule ^ticket/([0-9]+)$ ticket.php?id=$1 [L,QSA]
        RewriteRule ^ticket/create$ ticket.php?action=create [L,QSA]
    </Directory>
</VirtualHost>

Deployment

Git Auto-Deploy

Repository: https://code.lotusguild.org/LotusGuild/tinker_tickets

Flow:

  1. Push to main branch
  2. Auto-deploys to /root/code/tinker_tickets on 10.10.10.45
  3. .env is preserved
  4. Migrations must be run manually

Running Migrations

cd /root/code/tinker_tickets/migrations
mysql -h 10.10.10.50 -u tinkertickets -p'pass' ticketing_system < 007_add_ticket_assignment.sql
mysql -h 10.10.10.50 -u tinkertickets -p'pass' ticketing_system < 008_add_status_workflows.sql
mysql -h 10.10.10.50 -u tinkertickets -p'pass' ticketing_system < 009_add_ticket_templates.sql
mysql -h 10.10.10.50 -u tinkertickets -p'pass' ticketing_system < 010_add_bulk_operations.sql
mysql -h 10.10.10.50 -u tinkertickets -p'pass' ticketing_system < 011_remove_view_tracking.sql

Development Guidelines

Code Style

  • PHP: Tabs for indentation, prepared statements, htmlspecialchars() for output
  • JavaScript: Vanilla JS, fetch() for AJAX, clear function names
  • CSS: CSS variables for theming, mobile-responsive
  • Security: No SQL injection, XSS prevention, session validation

Error Handling

  • APIs return JSON with {success: bool, error: string}
  • Debug logging to /tmp/api_debug.log (update_ticket.php)
  • User-friendly error messages

Adding New Features

  1. Database: Create migration in migrations/
  2. Model: Add methods to relevant Model class
  3. API: Create API endpoint in api/ (with auth check)
  4. Controller: Update controller to load data
  5. View: Add UI elements
  6. JavaScript: Add interactivity
  7. CSS: Style for light + dark mode
  8. Test: Test thoroughly before pushing

ANSI Art Redesign (Next Priority)

Goal

Transform Tinker Tickets into a retro terminal aesthetic using ANSI art and ASCII characters.

Design Concept

  • Terminal-style borders: Use box-drawing characters (┌─┐│└─┘)
  • Monospace fonts: Courier New, Consolas, Monaco
  • ASCII art headers: Stylized "TINKER TICKETS" banner
  • Retro color palette: Green terminal, amber terminal, or custom
  • Template objects: Reusable border/box components

Implementation Approach

  1. CSS Variables: Define ANSI color palette
  2. Border Components: Create CSS classes for boxes with ASCII borders
  3. Typography: Monospace fonts throughout
  4. Icons: Replace emoji with ASCII art
  5. Dashboard: Terminal-style table with borders
  6. Tickets: Box-drawing characters for sections
  7. Forms: Terminal-style input boxes

Reference Colors (Classic Terminal)

:root {
  --ansi-black: #000000;
  --ansi-green: #00ff00;
  --ansi-amber: #ffb000;
  --ansi-blue: #0000ff;
  --ansi-cyan: #00ffff;
  --ansi-white: #ffffff;
  --ansi-bg: #000000;
}

Example Box Template

┌─────────────────────────────┐
│ TICKET #123                 │
├─────────────────────────────┤
│ Title: Hardware Failure     │
│ Status: [OPEN]              │
│ Priority: P1 (CRITICAL)     │
└─────────────────────────────┘

Debugging

Common Issues

# API debug logs
tail -f /tmp/api_debug.log

# Database connection
mysql -h 10.10.10.50 -u tinkertickets -p ticketing_system

# JavaScript console
# Open browser DevTools (F12) → Console tab

# Check dark mode
# localStorage.getItem('theme')

Known Behaviors

  • Ticket viewing no longer tracked (011 migration removes view logs)
  • Status can only be changed via header dropdown (removed from hamburger)
  • Bulk actions only visible to admins
  • Templates are optional when creating tickets
  • Workflow validation prevents invalid status transitions

Important Notes for AI Assistants

  1. All 5 features are complete and deployed
  2. Dark mode is fixed with comprehensive CSS
  3. Next priority is ANSI Art redesign (major visual overhaul)
  4. Database at 10.10.10.50, can't access directly from dev machine
  5. Auto-deploy is active, test carefully before pushing
  6. Session format: $_SESSION['user']['user_id'] (not $_SESSION['user_id'])
  7. API auth: Check $_SESSION['user']['user_id'] exists
  8. Admin check: $_SESSION['user']['is_admin'] ?? false
  9. Config path: config/config.php (not config/db.php)
  10. Migrations: Must be run manually on database server

File Reference Quick Guide

File Purpose Key Functions
index.php Dashboard router Database connection, routing
ticket.php Ticket router View/create ticket routing
api/update_ticket.php Update API Workflow validation, partial updates
api/assign_ticket.php Assignment API Assign/unassign tickets
api/bulk_operation.php Bulk ops API Admin bulk operations
api/get_template.php Template API Fetch ticket templates
api/get_users.php Users API Get user list
models/TicketModel.php Ticket data CRUD, assignment, filtering
models/WorkflowModel.php Workflow rules Status transition validation
models/AuditLogModel.php Audit logging Timeline, activity tracking
models/TemplateModel.php Templates Template CRUD
models/BulkOperationsModel.php Bulk ops Process bulk operations
controllers/DashboardController.php Dashboard logic Pagination, filters, assigned column
controllers/TicketController.php Ticket logic CRUD, timeline, templates
assets/js/dashboard.js Dashboard UI Filters, bulk actions, templates
assets/js/ticket.js Ticket UI Status updates, assignment, comments
assets/css/dashboard.css Dashboard styles Layout, table, bulk toolbar, dark mode
assets/css/ticket.css Ticket styles Timeline, ticket view, dark mode

Repository & Contact