# Patherly - Architecture & Overview

> **Purpose:** Core technical reference combining project vision and technical implementation.
> **Last Updated:** February 2, 2026

---

## Table of Contents

1. [Project Vision](#project-vision)
2. [Problem Statement](#problem-statement)
3. [Solution Overview](#solution-overview)
4. [Tech Stack](#tech-stack)
5. [System Architecture](#system-architecture)
6. [Database Schema](#database-schema)
7. [API Endpoints](#api-endpoints)
8. [Data Structures](#data-structures)
9. [Security](#security)
10. [Deployment](#deployment)

---

## Project Vision

A decision tree troubleshooting application designed for MSP engineers to transform diagnostic processes into clean, professional documentation automatically.

**Tagline:** "Take the path MOST traveled"

### Success Criteria

**3-Month Goal:** Michael uses this tool for 50% of his tickets

**Key Metrics:**
- Time saved per ticket
- Documentation quality improvement
- Reduction in "what did I do?" moments
- Team adoption rate

### Target Users

**Primary:** Senior Systems Engineers at MSPs managing Windows Server, Active Directory, Citrix, networking equipment

**Secondary:**
- Junior engineers needing guided troubleshooting
- Onsite technicians following remote engineer instructions
- MSP teams wanting standardized procedures

### Key Differentiators

1. **Automatic documentation generation** - No separate note-taking step
2. **On-the-fly customization** - Add custom branches when encountering edge cases
3. **Learning system** - Tracks common paths, suggests optimizations
4. **Automation integration** - Execute PowerShell/scripts directly from decision nodes
5. **Knowledge hub** - Links to documentation, KB articles, tutorials at each step

---

## Problem Statement

MSP engineers face constant context switching between diverse technical issues (file shares, server outages, VPN failures, Active Directory problems). Each context switch:

- Takes 15-25 minutes to regain full focus
- Creates cognitive overhead and attention residue
- Contributes to burnout (research-backed)
- Makes consistent documentation challenging
- Results in lost tribal knowledge

---

## Solution Overview

An intelligent decision tree system that:

- Guides engineers through proven troubleshooting paths
- Captures decisions and notes automatically
- Generates professional ticket documentation
- Builds institutional knowledge
- Reduces cognitive load during high-stress situations

---

## Tech Stack

### Frontend
| Component | Technology |
|-----------|------------|
| Framework | React 18 + Vite + TypeScript |
| Styling | Tailwind CSS |
| State Management | Zustand (with immer + zundo) |
| Routing | React Router v6 |
| API Client | Axios |
| Offline | Service Workers + IndexedDB (planned) |

### Backend
| Component | Technology |
|-----------|------------|
| Framework | Python FastAPI |
| ORM | SQLAlchemy 2.0 (async) |
| Validation | Pydantic |
| Auth | JWT (python-jose) + bcrypt |
| Migrations | Alembic |

### Database & Storage
| Component | Technology |
|-----------|------------|
| Database | PostgreSQL 16 |
| File Storage | S3-compatible (planned) |
| Development | Docker containers |

### Hosting
| Environment | Platform |
|-------------|----------|
| Development | Local (Vite + Uvicorn + Docker PostgreSQL) |
| Production | Railway Pro |
| Domain | patherly.com (api.patherly.com for backend) |

---

## System Architecture

```
┌─────────────────────────────────────────────────────┐
│                  Frontend (React)                    │
│  - Tree Navigation UI                               │
│  - Tree Editor                                      │
│  - Session Management                               │
│  - Export Functionality                             │
└─────────────────┬───────────────────────────────────┘
                  │ REST API (JSON)
┌─────────────────┴───────────────────────────────────┐
│              Backend (Python FastAPI)                │
│  - Authentication & Authorization                   │
│  - Tree CRUD Operations                             │
│  - Session Tracking                                 │
│  - Export Generation                                │
│  - File Upload/Storage (planned)                    │
└─────────────────┬───────────────────────────────────┘
                  │
┌─────────────────┴───────────────────────────────────┐
│              Database (PostgreSQL)                   │
│  - Trees (JSONB structure)                          │
│  - Sessions (path tracking)                         │
│  - Users & Teams                                    │
│  - Attachments Metadata                             │
└──────────────────────────────────────────────────────┘
```

---

## Database Schema

### Users Table

```sql
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    name VARCHAR(255) NOT NULL,
    role VARCHAR(50) NOT NULL DEFAULT 'engineer', -- admin, engineer, viewer
    team_id UUID REFERENCES teams(id),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    last_login TIMESTAMP WITH TIME ZONE
);
```

### Teams Table

```sql
CREATE TABLE teams (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```

### Trees Table

```sql
CREATE TABLE trees (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    description TEXT,
    category VARCHAR(100),
    tree_structure JSONB NOT NULL,
    author_id UUID REFERENCES users(id),
    team_id UUID REFERENCES teams(id),
    is_active BOOLEAN DEFAULT true,
    version INTEGER DEFAULT 1,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    usage_count INTEGER DEFAULT 0
);

CREATE INDEX idx_trees_category ON trees(category);
CREATE INDEX idx_trees_search ON trees USING gin(to_tsvector('english', name || ' ' || description));
```

### Sessions Table

```sql
CREATE TABLE sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tree_id UUID REFERENCES trees(id),
    user_id UUID REFERENCES users(id),
    tree_snapshot JSONB NOT NULL,
    path_taken JSONB NOT NULL,
    decisions JSONB NOT NULL,
    started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    completed_at TIMESTAMP WITH TIME ZONE,
    ticket_number VARCHAR(100),
    client_name VARCHAR(255),
    exported BOOLEAN DEFAULT false
);
```

### Attachments Table

```sql
CREATE TABLE attachments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id UUID REFERENCES sessions(id),
    node_id VARCHAR(100),
    file_name VARCHAR(255) NOT NULL,
    file_type VARCHAR(50),
    file_size INTEGER,
    storage_path VARCHAR(500),
    uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
```

---

## API Endpoints

### Authentication
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/v1/auth/register` | Register new user |
| POST | `/api/v1/auth/login` | Login (form data) |
| POST | `/api/v1/auth/login/json` | Login (JSON body) |
| POST | `/api/v1/auth/refresh` | Refresh access token |
| GET | `/api/v1/auth/me` | Get current user |
| POST | `/api/v1/auth/logout` | Logout |

### Trees
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/trees` | List trees (paginated) |
| POST | `/api/v1/trees` | Create tree |
| GET | `/api/v1/trees/categories` | Get unique categories |
| GET | `/api/v1/trees/search` | Full-text search |
| GET | `/api/v1/trees/{id}` | Get tree by ID |
| PUT | `/api/v1/trees/{id}` | Update tree |
| DELETE | `/api/v1/trees/{id}` | Soft delete tree |

### Sessions
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/sessions` | List user's sessions |
| POST | `/api/v1/sessions` | Start new session |
| GET | `/api/v1/sessions/{id}` | Get session |
| PUT | `/api/v1/sessions/{id}` | Update session |
| POST | `/api/v1/sessions/{id}/complete` | Mark complete |
| POST | `/api/v1/sessions/{id}/export` | Export (md/txt/html) |

---

## Data Structures

### Tree Structure (JSONB)

```json
{
  "id": "root",
  "type": "decision",
  "question": "Can you ping the server?",
  "help_text": "Run: ping servername",
  "options": [
    { "label": "Yes", "value": "yes", "next_node_id": "node_2" },
    { "label": "No", "value": "no", "next_node_id": "node_network" }
  ],
  "children": [
    {
      "id": "node_2",
      "type": "action",
      "title": "Check service status",
      "description": "Verify the service is running",
      "commands": ["Get-Service -Name 'ServiceName'"],
      "next_node_id": "node_3"
    },
    {
      "id": "node_3",
      "type": "solution",
      "title": "Issue Resolved",
      "description": "Service restarted successfully",
      "resolution_steps": ["Document the fix", "Update ticket"]
    }
  ]
}
```

### Session Decision (JSONB array item)

```json
{
  "node_id": "node_1",
  "question": "Can you ping the VDA?",
  "answer": "yes",
  "notes": "Ping successful, 2ms response time",
  "timestamp": "2026-01-22T14:31:00Z",
  "attachments": []
}
```

---

## Security

### Authentication
- JWT tokens: 15-minute access, 7-day refresh
- Passwords: bcrypt with cost factor 12
- Role-based access: admin, engineer, viewer

### API Security
- CORS configured for frontend origins
- Rate limiting planned
- Input validation via Pydantic
- SQL injection prevention via SQLAlchemy ORM

### Data Protection
- HTTPS in production
- Timezone-aware timestamps (UTC storage)
- Soft deletes for trees (is_active flag)

---

## Deployment

### Development Setup

```powershell
# Terminal 1: Database
docker start patherly_postgres

# Terminal 2: Backend
cd backend
.\venv\Scripts\activate
uvicorn app.main:app --reload

# Terminal 3: Frontend
cd frontend
npm run dev
```

### Production (Railway)

- **Database:** Railway managed PostgreSQL
- **Backend:** api.patherly.com
- **Frontend:** patherly.com
- **Environment:** PR environments for testing

### Key Configuration

```env
# Backend .env
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/patherly
SECRET_KEY=your-secret-key
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=15

# Frontend .env
VITE_API_URL=http://localhost:8000
```

---

## File Structure

```
patherly/
├── backend/
│   ├── app/
│   │   ├── api/v1/endpoints/    # Route handlers
│   │   ├── core/                # Config, security, logging
│   │   ├── models/              # SQLAlchemy models
│   │   └── schemas/             # Pydantic schemas
│   ├── alembic/                 # Migrations
│   ├── tests/                   # pytest tests
│   └── scripts/                 # Seed scripts
├── frontend/
│   ├── src/
│   │   ├── api/                 # API client
│   │   ├── components/          # React components
│   │   ├── pages/               # Page components
│   │   └── store/               # Zustand stores
│   └── public/
└── docs/                        # Documentation
```

---

*For current project status, see [CURRENT-STATE.md](./CURRENT-STATE.md)*
*For development setup, see [QUICK-START.md](./QUICK-START.md)*
*For known issues, see [LESSONS-LEARNED.md](./LESSONS-LEARNED.md)*
