# 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** 💙🔥❄️
