# SCHEMA_CORE.md

**Source:** MSP-MODE-SPEC.md
**Section:** Core MSP Tracking Tables
**Date:** 2026-01-15

## Overview

Core tables for MSP Mode tracking system: machines, clients, projects, sessions, and tasks. These tables form the foundation of the MSP tracking database and are referenced by most other tables in the system.

---

## Core MSP Tracking Tables (6 tables)

### `machines`

Technician's machines (laptops, desktops) used for MSP work.

```sql
CREATE TABLE machines (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Machine identification (auto-detected)
    hostname VARCHAR(255) NOT NULL UNIQUE, -- from `hostname` command
    machine_fingerprint VARCHAR(500) UNIQUE, -- hostname + username + platform hash

    -- Environment details
    friendly_name VARCHAR(255), -- "Main Laptop", "Home Desktop", "Travel Laptop"
    machine_type VARCHAR(50) CHECK(machine_type IN ('laptop', 'desktop', 'workstation', 'vm')),
    platform VARCHAR(50), -- "win32", "darwin", "linux"
    os_version VARCHAR(100),
    username VARCHAR(255), -- from `whoami`
    home_directory VARCHAR(500), -- user home path

    -- Capabilities
    has_vpn_access BOOLEAN DEFAULT false, -- can connect to client networks
    vpn_profiles TEXT, -- JSON array: ["dataforth", "grabb", "internal"]
    has_docker BOOLEAN DEFAULT false,
    has_powershell BOOLEAN DEFAULT false,
    powershell_version VARCHAR(20),
    has_ssh BOOLEAN DEFAULT true,
    has_git BOOLEAN DEFAULT true,

    -- Network context
    typical_network_location VARCHAR(100), -- "home", "office", "mobile"
    static_ip VARCHAR(45), -- if has static IP

    -- Claude Code context
    claude_working_directory VARCHAR(500), -- primary working dir
    additional_working_dirs TEXT, -- JSON array

    -- Tool versions
    installed_tools TEXT, -- JSON: {"git": "2.40", "docker": "24.0", "python": "3.11"}

    -- MCP Servers & Skills (NEW)
    available_mcps TEXT, -- JSON array: ["claude-in-chrome", "filesystem", "custom-mcp"]
    mcp_capabilities TEXT, -- JSON: {"chrome": {"version": "1.0", "features": ["screenshots"]}}
    available_skills TEXT, -- JSON array: ["pdf", "commit", "review-pr", "custom-skill"]
    skill_paths TEXT, -- JSON: {"/pdf": "/path/to/pdf-skill", ...}

    -- OS-Specific Commands
    preferred_shell VARCHAR(50), -- "powershell", "bash", "zsh", "cmd"
    package_manager_commands TEXT, -- JSON: {"install": "choco install", "update": "choco upgrade"}

    -- Status
    is_primary BOOLEAN DEFAULT false, -- primary machine
    is_active BOOLEAN DEFAULT true,
    last_seen TIMESTAMP,
    last_session_id UUID, -- last session from this machine

    -- Notes
    notes TEXT, -- "Travel laptop - limited tools, no VPN"

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_machines_hostname (hostname),
    INDEX idx_machines_fingerprint (machine_fingerprint),
    INDEX idx_machines_is_active (is_active),
    INDEX idx_machines_platform (platform)
);
```

**Machine Fingerprint Generation:**
```javascript
fingerprint = SHA256(hostname + "|" + username + "|" + platform + "|" + home_directory)
// Example: SHA256("ACG-M-L5090|MikeSwanson|win32|C:\Users\MikeSwanson")
```

**Auto-Detection on Session Start:**
```javascript
hostname = exec("hostname")          // "ACG-M-L5090"
username = exec("whoami")            // "MikeSwanson" or "AzureAD+MikeSwanson"
platform = process.platform          // "win32", "darwin", "linux"
home_dir = process.env.HOME || process.env.USERPROFILE

fingerprint = SHA256(`${hostname}|${username}|${platform}|${home_dir}`)

// Query database: SELECT * FROM machines WHERE machine_fingerprint = ?
// If not found: Create new machine record
// If found: Update last_seen, return machine_id
```

**Examples:**

**ACG-M-L5090 (Main Laptop):**
```json
{
  "hostname": "ACG-M-L5090",
  "friendly_name": "Main Laptop",
  "platform": "win32",
  "os_version": "Windows 11 Pro",
  "has_vpn_access": true,
  "vpn_profiles": ["dataforth", "grabb", "internal"],
  "has_docker": true,
  "powershell_version": "7.4",
  "preferred_shell": "powershell",
  "available_mcps": ["claude-in-chrome", "filesystem"],
  "available_skills": ["pdf", "commit", "review-pr", "frontend-design"],
  "package_manager_commands": {
    "install": "choco install {package}",
    "update": "choco upgrade {package}",
    "list": "choco list --local-only"
  }
}
```

**Mike-MacBook (Development Machine):**
```json
{
  "hostname": "Mikes-MacBook-Pro",
  "friendly_name": "MacBook Pro",
  "platform": "darwin",
  "os_version": "macOS 14.2",
  "has_vpn_access": false,
  "has_docker": true,
  "powershell_version": null,
  "preferred_shell": "zsh",
  "available_mcps": ["filesystem"],
  "available_skills": ["commit", "review-pr"],
  "package_manager_commands": {
    "install": "brew install {package}",
    "update": "brew upgrade {package}",
    "list": "brew list"
  }
}
```

**Travel-Laptop (Limited):**
```json
{
  "hostname": "TRAVEL-WIN",
  "friendly_name": "Travel Laptop",
  "platform": "win32",
  "os_version": "Windows 10 Home",
  "has_vpn_access": false,
  "vpn_profiles": [],
  "has_docker": false,
  "powershell_version": "5.1",
  "preferred_shell": "powershell",
  "available_mcps": [],
  "available_skills": [],
  "notes": "Minimal toolset, no Docker, no VPN - use for light work only"
}
```

---

### `clients`

Master table for all client organizations.

```sql
CREATE TABLE clients (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL UNIQUE,
    type VARCHAR(50) NOT NULL CHECK(type IN ('msp_client', 'internal', 'project')),
    network_subnet VARCHAR(100), -- e.g., "192.168.0.0/24"
    domain_name VARCHAR(255), -- AD domain or primary domain
    m365_tenant_id UUID, -- Microsoft 365 tenant ID
    primary_contact VARCHAR(255),
    notes TEXT,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_clients_type (type),
    INDEX idx_clients_name (name)
);
```

**Examples:** Dataforth, Grabb & Durando, Valley Wide Plastering, AZ Computer Guru (internal)

---

### `projects`

Individual projects/engagements for clients.

```sql
CREATE TABLE projects (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID NOT NULL REFERENCES clients(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    slug VARCHAR(255) UNIQUE, -- directory name: "dataforth-dos"
    category VARCHAR(50) CHECK(category IN (
        'client_project', 'internal_product', 'infrastructure',
        'website', 'development_tool', 'documentation'
    )),
    status VARCHAR(50) DEFAULT 'working' CHECK(status IN (
        'complete', 'working', 'blocked', 'pending', 'critical', 'deferred'
    )),
    priority VARCHAR(20) CHECK(priority IN ('critical', 'high', 'medium', 'low')),
    description TEXT,
    started_date DATE,
    target_completion_date DATE,
    completed_date DATE,
    estimated_hours DECIMAL(10,2),
    actual_hours DECIMAL(10,2),
    gitea_repo_url VARCHAR(500),
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_projects_client (client_id),
    INDEX idx_projects_status (status),
    INDEX idx_projects_slug (slug)
);
```

**Examples:** dataforth-dos, gururmm, grabb-website-move

---

### `sessions`

Work sessions with time tracking (enhanced with machine tracking).

```sql
CREATE TABLE sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID REFERENCES clients(id) ON DELETE SET NULL,
    project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
    machine_id UUID REFERENCES machines(id) ON DELETE SET NULL, -- NEW: which machine
    session_date DATE NOT NULL,
    start_time TIMESTAMP,
    end_time TIMESTAMP,
    duration_minutes INTEGER, -- auto-calculated or manual
    status VARCHAR(50) DEFAULT 'completed' CHECK(status IN (
        'completed', 'in_progress', 'blocked', 'pending'
    )),
    session_title VARCHAR(500) NOT NULL,
    summary TEXT, -- markdown summary
    is_billable BOOLEAN DEFAULT false,
    billable_hours DECIMAL(10,2),
    technician VARCHAR(255), -- "Mike Swanson", etc.
    session_log_file VARCHAR(500), -- path to .md file
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_sessions_client (client_id),
    INDEX idx_sessions_project (project_id),
    INDEX idx_sessions_date (session_date),
    INDEX idx_sessions_billable (is_billable),
    INDEX idx_sessions_machine (machine_id)
);
```

---

### `pending_tasks`

Open items across all clients/projects.

```sql
CREATE TABLE pending_tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID REFERENCES clients(id) ON DELETE CASCADE,
    project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
    work_item_id UUID REFERENCES work_items(id) ON DELETE SET NULL,
    title VARCHAR(500) NOT NULL,
    description TEXT,
    priority VARCHAR(20) CHECK(priority IN ('critical', 'high', 'medium', 'low')),
    blocked_by TEXT, -- what's blocking this
    assigned_to VARCHAR(255),
    due_date DATE,
    status VARCHAR(50) DEFAULT 'pending' CHECK(status IN (
        'pending', 'in_progress', 'blocked', 'completed', 'cancelled'
    )),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_at TIMESTAMP,

    INDEX idx_pending_tasks_client (client_id),
    INDEX idx_pending_tasks_status (status),
    INDEX idx_pending_tasks_priority (priority)
);
```

---

### `tasks`

Task/checklist management for tracking implementation steps, analysis work, and other agent activities.

```sql
CREATE TABLE tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Task hierarchy
    parent_task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    task_order INTEGER NOT NULL,

    -- Task details
    title VARCHAR(500) NOT NULL,
    description TEXT,
    task_type VARCHAR(100) CHECK(task_type IN (
        'implementation', 'research', 'review', 'deployment',
        'testing', 'documentation', 'bugfix', 'analysis'
    )),

    -- Status tracking
    status VARCHAR(50) NOT NULL CHECK(status IN (
        'pending', 'in_progress', 'blocked', 'completed', 'cancelled'
    )),
    blocking_reason TEXT, -- Why blocked (if status='blocked')

    -- Context
    session_id UUID REFERENCES sessions(id) ON DELETE CASCADE,
    client_id UUID REFERENCES clients(id) ON DELETE SET NULL,
    project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
    assigned_agent VARCHAR(100), -- Which agent is handling this

    -- Timing
    estimated_complexity VARCHAR(20) CHECK(estimated_complexity IN (
        'trivial', 'simple', 'moderate', 'complex', 'very_complex'
    )),
    started_at TIMESTAMP,
    completed_at TIMESTAMP,

    -- Context data (JSON)
    task_context TEXT, -- Detailed context for this task
    dependencies TEXT, -- JSON array of dependency task_ids

    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_tasks_session (session_id),
    INDEX idx_tasks_status (status),
    INDEX idx_tasks_parent (parent_task_id),
    INDEX idx_tasks_client (client_id),
    INDEX idx_tasks_project (project_id)
);
```

---

## Tagging System Tables (3 tables)

### `tags`

Flexible tagging system for work items and sessions.

```sql
CREATE TABLE tags (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(100) UNIQUE NOT NULL,
    category VARCHAR(50) CHECK(category IN (
        'technology', 'client', 'infrastructure',
        'problem_type', 'action', 'service'
    )),
    description TEXT,
    usage_count INTEGER DEFAULT 0, -- auto-increment on use
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_tags_category (category),
    INDEX idx_tags_name (name)
);
```

**Pre-populated tags:** 157+ tags identified from analysis
- 58 technology tags (docker, postgresql, apache, etc.)
- 24 infrastructure tags (jupiter, saturn, pfsense, etc.)
- 20+ client tags
- 30 problem type tags (connection-timeout, ssl-error, etc.)
- 25 action tags (migration, upgrade, cleanup, etc.)

---

### `work_item_tags` (Junction Table)

Many-to-many relationship: work items ↔ tags.

```sql
CREATE TABLE work_item_tags (
    work_item_id UUID NOT NULL REFERENCES work_items(id) ON DELETE CASCADE,
    tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
    PRIMARY KEY (work_item_id, tag_id),

    INDEX idx_wit_work_item (work_item_id),
    INDEX idx_wit_tag (tag_id)
);
```

---

### `session_tags` (Junction Table)

Many-to-many relationship: sessions ↔ tags.

```sql
CREATE TABLE session_tags (
    session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
    tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
    PRIMARY KEY (session_id, tag_id),

    INDEX idx_st_session (session_id),
    INDEX idx_st_tag (tag_id)
);
```

---

## Relationships

- `machines` → `sessions` (one-to-many): Track which machine was used for each session
- `clients` → `projects` (one-to-many): Each client can have multiple projects
- `clients` → `sessions` (one-to-many): Track all work sessions for a client
- `projects` → `sessions` (one-to-many): Sessions belong to specific projects
- `sessions` → `work_items` (one-to-many): Each session contains multiple work items
- `sessions` → `pending_tasks` (one-to-many): Tasks can be created from sessions
- `sessions` → `tasks` (one-to-many): Task checklists linked to sessions
- `tags` ↔ `sessions` (many-to-many via session_tags)
- `tags` ↔ `work_items` (many-to-many via work_item_tags)

---

## Cross-References

- **Work Items & Time Tracking:** See [SCHEMA_MSP.md](SCHEMA_MSP.md)
- **Infrastructure Details:** See [SCHEMA_INFRASTRUCTURE.md](SCHEMA_INFRASTRUCTURE.md)
- **Credentials & Security:** See [SCHEMA_CREDENTIALS.md](SCHEMA_CREDENTIALS.md)
- **Environmental Learning:** See [SCHEMA_CONTEXT.md](SCHEMA_CONTEXT.md)
- **External Integrations:** See [SCHEMA_INTEGRATIONS.md](SCHEMA_INTEGRATIONS.md)
- **API Endpoints:** See [API_SPEC.md](API_SPEC.md)
- **Architecture Overview:** See [ARCHITECTURE_OVERVIEW.md](ARCHITECTURE_OVERVIEW.md)
