- Remove outdated documentation files - Add ARCHITECTURE.md and BACKLOG.md - Add docs/ folder - Update CURRENT-STATE.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
12 KiB
Patherly - Architecture & Overview
Purpose: Core technical reference combining project vision and technical implementation. Last Updated: February 2, 2026
Table of Contents
- Project Vision
- Problem Statement
- Solution Overview
- Tech Stack
- System Architecture
- Database Schema
- API Endpoints
- Data Structures
- Security
- 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
- Automatic documentation generation - No separate note-taking step
- On-the-fly customization - Add custom branches when encountering edge cases
- Learning system - Tracks common paths, suggests optimizations
- Automation integration - Execute PowerShell/scripts directly from decision nodes
- 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
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
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
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
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
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)
{
"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)
{
"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
# 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
# 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 For development setup, see QUICK-START.md For known issues, see LESSONS-LEARNED.md