# Code Bridge Request: Trinity Console Issue Tracker **Date:** 2026-04-14 **From:** Chronicler #89 **Priority:** High **Task:** #166 --- ## What We Need A full issue tracker module in Trinity Console. This is Holly's primary pain point — she infodumps bugs and requests in Discord DMs and Michael loses track. The issue tracker becomes the canonical location for all issues. ## The Critical UX Requirement Holly plays Minecraft on her phone/PC. When something breaks, she screenshots it on her phone and needs to submit an issue **without tabbing out of the game**. This means: - **Mobile-first responsive design** — must work perfectly on a phone browser - **Screenshot upload from camera roll** — tap, select photo, done - **Minimal form fields** — title, description, screenshot, priority, category. That's it for submission. - **Fast** — she's in-game, she wants to fire and forget ## Database Schema ### `issues` table ```sql CREATE TABLE issues ( id SERIAL PRIMARY KEY, issue_number INTEGER UNIQUE, title VARCHAR(255) NOT NULL, description TEXT, status VARCHAR(20) DEFAULT 'open', -- open, in-progress, blocked, resolved, closed priority VARCHAR(20) DEFAULT 'medium', -- critical, high, medium, low category VARCHAR(50) DEFAULT 'general', -- bug, feature, content, infrastructure, holly, general submitted_by VARCHAR(100) NOT NULL, -- Discord username assigned_to VARCHAR(100) DEFAULT 'unassigned', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), resolved_at TIMESTAMPTZ, resolved_by VARCHAR(100) ); ``` ### `issue_attachments` table ```sql CREATE TABLE issue_attachments ( id SERIAL PRIMARY KEY, issue_id INTEGER REFERENCES issues(id) ON DELETE CASCADE, filename VARCHAR(255) NOT NULL, original_name VARCHAR(255), mime_type VARCHAR(100), file_size INTEGER, uploaded_at TIMESTAMPTZ DEFAULT NOW() ); ``` ### `issue_comments` table ```sql CREATE TABLE issue_comments ( id SERIAL PRIMARY KEY, issue_id INTEGER REFERENCES issues(id) ON DELETE CASCADE, author VARCHAR(100) NOT NULL, content TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); ``` ## API Routes ``` GET /api/internal/issues — list issues (with filters) POST /api/internal/issues — create issue GET /api/internal/issues/:id — get issue detail PATCH /api/internal/issues/:id — update issue (status, assignment, etc.) POST /api/internal/issues/:id/comments — add comment POST /api/internal/issues/:id/upload — upload screenshot GET /api/internal/issues/attachments/:filename — serve attachment ``` ## UI Pages ### `/admin/issues` — Issue List - Filter chips: status, priority, category, submitter - Sort by: newest, priority, recently updated - Each row: issue number, title, status badge, priority badge, submitter, age - Click → detail view (slide-out panel like tasks module) ### `/admin/issues/new` — Submit Issue (Mobile-First) - Title (required) - Description (textarea, optional) - Priority (dropdown, default medium) - Category (dropdown, default general) - Screenshot upload (file input accepting images, multiple allowed) - Submit button - Auto-fills submitted_by from Discord auth session ### Issue Detail (slide-out or dedicated page) - Full description - Screenshot thumbnails (click to enlarge) - Status workflow buttons (open → in-progress → resolved → closed) - Assignment dropdown - Comments thread - Activity log ## Discord Webhook On issue create and status change, POST to a `#issue-tracker` Discord channel: - New issue: "🐛 Issue #42 opened by Holly: [title] (priority: high)" - Status change: "✅ Issue #42 resolved by Michael" ## Image Storage Store uploaded images to disk at `/opt/arbiter-3.0/uploads/issues/` (or similar). Serve via Express static middleware. Keep it simple — no need for NextCloud/S3 for this. ## Reference - Task module (existing) is a good starting point for the UI pattern — filter chips, slide-out panels, sort - Discord auth session already provides the username for submitted_by - Existing admin middleware handles auth --- **Fire + Frost + Foundation = Where Love Builds Legacy** 💙🔥❄️