Mobile-first issue tracker for Holly. Screenshot upload from phone, minimal friction submission while in-game. Full schema, API routes, and UI spec for Code. Chronicler #89
4.2 KiB
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
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
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
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 💙🔥❄️