Files
resolutionflow/CLAUDE.md
2026-02-11 21:52:13 -05:00

12 KiB

CLAUDE.md - Patherly / ResolutionFlow Project Context

Last Updated: February 11, 2026


Project Overview

Patherly (user-facing brand: ResolutionFlow) is a SaaS product for MSP professionals. It provides troubleshooting decision trees that guide engineers through proven troubleshooting paths, capture decisions and notes, and generate professional ticket documentation.

Target Market: MSP companies — IT service providers managing infrastructure and support for multiple clients.

SaaS Context: Multi-tenant design — teams represent MSP companies, trees shared within teams, tiered access (super_admin, team_admin, engineer, viewer).

Branding

Context Name Used
Repository / directory / database / Docker patherly / patherly_postgres
Backend, frontend UI, production URLs ResolutionFlow
  • Design: Monochrome dark-only — black backgrounds, white text with opacity, Inter font
  • CSS utilities: glass-card, glass-card-hover, glass-card-glow, glass-stat (in index.css)
  • Logo: Inline SVG in BrandLogo.tsx
  • Design system guide: docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md

When adding new pages/components: use "ResolutionFlow" branding, monochrome design, glass-card containers, text-white hierarchy, white primary buttons, functional color only for status.


Current State

  • Phase: Phase 2.5 - Step Library Foundation (In Progress)
  • Backend: Complete (25+ API endpoints, 100+ integration tests)
  • Frontend: Core features complete, Tree Editor functional
  • Database: PostgreSQL with Docker, 29+ migrations
  • Detailed status: CURRENT-STATE.md

What's In Progress

  • Custom step continuation flow refinements (Phase 2.5)
  • Tree forking from sessions with custom steps

Tech Stack

Backend

  • Framework: Python FastAPI
  • Database: PostgreSQL 16 (async via SQLAlchemy 2.0 + asyncpg)
  • Migrations: Alembic
  • Auth: JWT (python-jose) + bcrypt, refresh token rotation (JTI-based)
  • Validation: Pydantic v2

Frontend

  • Framework: React 19 + Vite + TypeScript
  • Styling: Tailwind CSS v3 — monochrome glass-morphism (dark-only)
  • State: Zustand (with immer + zundo for undo/redo)
  • Routing: React Router v7
  • API Client: Axios with token refresh interceptor
  • Icons: Lucide React

Key Project Structure

patherly/
├── backend/
│   ├── app/
│   │   ├── main.py                 # FastAPI entry point
│   │   ├── api/endpoints/          # Route handlers (auth, trees, sessions, admin, steps, etc.)
│   │   ├── api/deps.py             # Auth dependencies
│   │   ├── api/router.py           # Route registration
│   │   ├── core/                   # config, database, permissions, security, audit, rate_limit
│   │   ├── models/                 # SQLAlchemy models
│   │   └── schemas/                # Pydantic schemas
│   ├── alembic/                    # Database migrations (001-029+)
│   ├── scripts/                    # seed_data.py, seed_trees.py
│   └── tests/                      # pytest integration tests
├── frontend/
│   ├── src/
│   │   ├── api/                    # Axios client + endpoint modules
│   │   ├── components/             # common, layout, tree-editor, session, library, step-library, ui
│   │   ├── hooks/                  # usePermissions, useSessionTimer, useKeyboardShortcuts
│   │   ├── pages/                  # All page components
│   │   ├── store/                  # Zustand stores (auth, treeEditor, userPreferences)
│   │   └── types/                  # TypeScript interfaces
│   └── tailwind.config.js
├── CLAUDE.md                       # This file
├── CURRENT-STATE.md                # Detailed feature status
├── LESSONS-LEARNED.md              # Bugs and fixes (READ THIS!)
└── docs/plans/                     # Design docs & implementation plans

Environment Variables

Backend (backend/.env)

APP_NAME=ResolutionFlow
DEBUG=true
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/patherly
DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/patherly
SECRET_KEY=<openssl rand -hex 32>
ACCESS_TOKEN_EXPIRE_MINUTES=5
REFRESH_TOKEN_EXPIRE_DAYS=7
REQUIRE_INVITE_CODE=true

Frontend (frontend/.env.local - optional)

VITE_API_URL=http://localhost:8000

Development Commands

# Start PostgreSQL
docker start patherly_postgres

# Backend (from backend/)
.\venv\Scripts\Activate
uvicorn app.main:app --reload

# Frontend (from frontend/)
npm run dev

# Run tests (from backend/)
pytest --override-ini="addopts="

# First time only: create test database
docker exec -it patherly_postgres psql -U postgres -c "CREATE DATABASE patherly_test;"

# Frontend build
cd frontend && npm run build

# Database migrations
cd backend && alembic upgrade head
alembic revision --autogenerate -m "Description"

# Access PostgreSQL
docker exec -it patherly_postgres psql -U postgres -d patherly

# Seed data
cd backend && pip install httpx && python -m scripts.seed_trees

URLs


Critical Lessons Learned

Full reference: LESSONS-LEARNED.md — read before making changes!

Top Gotchas (most commonly hit)

1. DateTime Handling — Always timezone-aware:

# CORRECT
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
# NEVER use datetime.utcnow()

2. SQLAlchemy Async — No lazy loading on new objects:

# WRONG — MissingGreenlet error
new_tree = Tree(...); db.add(new_tree); await db.flush()
new_tree.tags.append(tag)  # Lazy load fails!

# CORRECT — Use direct SQL for junction tables
await db.execute(tree_tag_assignments.insert().values(tree_id=new_tree.id, tag_id=tag.id))

3. React State — Don't store object snapshots:

// WRONG — snapshot won't update
const [editingNode, setEditingNode] = useState(node)
// CORRECT — store ID, derive object
const [editingNodeId, setEditingNodeId] = useState(node.id)
const editingNode = editingNodeId ? findNode(editingNodeId, tree?.tree_structure) : null

4. Modal Draft State — Exclude store-managed fields:

const { children, ...draftWithoutChildren } = draft
updateNode(node.id, draftWithoutChildren)  // Don't overwrite children

5. Multiple FKs to same table — Specify foreign_keys on BOTH sides:

author = relationship("User", foreign_keys=[author_id], back_populates="trees")

6. PostgreSQL NULL in UUID columns:

SELECT 'tag', 'slug', NULL::uuid as team_id  -- Must cast NULL to uuid

7. API Path Gotcha: Frontend apiClient baseURL is http://localhost:8000/api/v1 — use relative paths WITHOUT /api/v1/ prefix (e.g., /admin/users not /api/v1/admin/users). Invite codes endpoint is /invites (NOT /invite-codes).

8. CORS errors can mask 500s: Check backend logs first. Also run alembic upgrade head after pulling changes.

9. Public endpoints with optional auth: Use manual _get_optional_user(request, db) helper, NOT Optional[User] param (FastAPI treats it as Pydantic field).

10. React Router — Clear dirty state before navigation:

markSaved()  // Clear isDirty BEFORE navigate()
navigate(`/trees/${newTree.id}/edit`)

RBAC & Permissions

  • Role hierarchy: super_admin > team_admin > engineer > viewer
  • Team Admin: role='engineer' + is_team_admin=True + valid team_id
  • Backend deps: get_current_active_user(user, db) (any active + auto-downgrades expired trials), require_engineer_or_admin (blocks viewers), require_admin (super admin only)
  • Never use role == "admin" — use is_super_admin instead
  • Frontend: usePermissions() hook for all permission checks
  • Centralized: backend/app/core/permissions.py, frontend/src/hooks/usePermissions.ts

Monochrome Design System

  • Backgrounds: bg-black, subtle radial gradients
  • Cards: glass-card rounded-2xl (NOT bg-card border-border)
  • Buttons: Primary: bg-white text-black hover:bg-white/90. Secondary: border border-white/10 text-white/60 hover:bg-white/10
  • Inputs: border-white/10 bg-black/50 text-white + focus: border-white/30 ring-white/20
  • Text: text-whitetext-white/70text-white/40text-white/30
  • Borders: border-white/[0.06] or border-white/10
  • Functional color only: emerald-400 (success), red-400 (error), yellow-400 (warning), blue-400 (info)

Frontend Patterns

  • Component guidelines: Use cn() from @/lib/utils, Lucide icons (wrap in <span> for title), modals with fixed header/footer
  • Type organization: Create in types/, export from types/index.ts, import with import type { T } from '@/types'
  • Scratchpad overlay: position: fixed, onOpenChange callback for parent padding adjustment, right-2 positioning
  • Custom step flow: CustomStepModalPostStepActionModalContinuationModal → custom step view. Key state: pendingStep, pendingContinuationNodeId, customBranchMode, branchOriginNodeId. Use findCustomStep() not findNode() for custom step UUIDs.

Common Tasks

  • New endpoint: Create in endpoints/ → add to router.py → schema in schemas/ → tests → frontend API client
  • New page: Create in pages/ → add route in router.tsx → nav link in AppLayout.tsx
  • Schema change: Update model → alembic revision --autogenerate -m "desc" → review → alembic upgrade head
  • New frontend API module: Types in types/ → export from types/index.ts → client in api/ → export from api/index.ts

Coding Standards

Python

  • Type hints everywhere, async/await for DB, Pydantic for validation, DateTime(timezone=True) always

TypeScript

  • Interfaces for all data, const over let, functional components + hooks, reusable logic in custom hooks

Git

  • Format: type: description (feat, fix, refactor, docs, test, chore)
  • Always include Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
  • Always create feature branch BEFORE committing: git checkout -b feat/feature-name
  • Large features: commit per phase with npm run build validation

Deployment (Railway)

  • Production: resolutionflow.com (frontend), api.resolutionflow.com (backend)
  • Auto-deploys on push to main
  • PR environments auto-created (need manual domain generation in Railway dashboard)
  • PR envs need VITE_API_URL set with https:// prefix on frontend service
  • ALLOW_RAILWAY_ORIGINS=true enables CORS for *.up.railway.app
  • Super admin utility: backend/make_superadmin_simple.py list|<email>

Future Roadmap

  • Phase 3: File attachments, offline mode, client context, analytics
  • Phase 4: PSA integrations (ConnectWise, Kaseya), PowerShell automation, enterprise SSO

Quick Reference

What Where
API Docs http://localhost:8000/api/docs
Detailed Status CURRENT-STATE.md
Bugs & Fixes LESSONS-LEARNED.md
Feature Specs 04-FEATURE-SPECIFICATIONS.md
Design System docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md