fix: high-severity security hardening (Phase B permissions audit)
Phase B addresses 7 high-severity gaps from the permissions audit: - B1: Enforce tree access check on session start via can_access_tree - B2: Replace all inline permission helpers with centralized permissions.py - B3: Fix require_engineer_or_admin to check is_team_admin before role - B4: Add is_active field on User with enforcement in get_current_active_user - B5: Add admin user management endpoints (list, get, role, team-admin, deactivate, activate) - B6: Add rate limiting on auth/invite endpoints via slowapi (disabled in DEBUG) - B7: Implement refresh token rotation with JTI-based revocation and meaningful logout Also reduces access token TTL from 15 to 5 minutes and updates CLAUDE.md with SaaS/MSP context for future planning sessions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
36
CLAUDE.md
36
CLAUDE.md
@@ -1,20 +1,24 @@
|
||||
# CLAUDE.md - Patherly / ResolutionFlow Project Context
|
||||
|
||||
> **Purpose:** This file provides Claude Code with essential context for working on the Patherly project.
|
||||
> **Last Updated:** February 4, 2026
|
||||
> **Last Updated:** February 5, 2026
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Patherly** (user-facing brand: **ResolutionFlow**) is a troubleshooting decision tree application designed for MSP engineers. It guides engineers through proven troubleshooting paths, captures decisions and notes automatically, and generates professional ticket documentation.
|
||||
**Patherly** (user-facing brand: **ResolutionFlow**) is a **SaaS product for Managed Service Provider (MSP) professionals and companies**. It provides troubleshooting decision trees that guide engineers through proven troubleshooting paths, capture decisions and notes automatically, and generate professional ticket documentation.
|
||||
|
||||
**Tagline:** "Take the path MOST traveled."
|
||||
|
||||
**Target Market:** MSP (Managed Service Provider) companies — IT service providers that manage infrastructure, endpoints, and support for multiple client organizations.
|
||||
|
||||
**Primary User:** Michael Chihlas - Senior Systems Engineer at an MSP
|
||||
|
||||
**Goal:** Michael uses this tool for 50% of his tickets within 3 months.
|
||||
|
||||
**SaaS Context:** All features should be designed with multi-tenant MSP use in mind — teams represent MSP companies, trees are shared within teams, and the permission model supports tiered access (super_admin for platform, team_admin for MSP company, engineer for technicians, viewer for read-only access).
|
||||
|
||||
### Branding
|
||||
|
||||
The project was rebranded from "Patherly" to "ResolutionFlow" in the frontend (PR #26, commit `cfbd815`). The naming is split:
|
||||
@@ -44,7 +48,7 @@ When adding new frontend pages or components, use "ResolutionFlow" for any user-
|
||||
## Current State
|
||||
|
||||
- **Phase:** Phase 2.5 - Step Library Foundation (In Progress)
|
||||
- **Backend:** Complete (20+ API endpoints, 40+ integration tests, all passing)
|
||||
- **Backend:** Complete (25+ API endpoints, 50+ integration tests, all passing)
|
||||
- **Frontend:** Core features complete, Tree Editor functional, Settings page added
|
||||
- **Database:** PostgreSQL with Docker (container name: `patherly_postgres`)
|
||||
|
||||
@@ -111,6 +115,16 @@ When adding new frontend pages or components, use "ResolutionFlow" for any user-
|
||||
- Secret key validator — rejects default key when `DEBUG=False`
|
||||
- Role CHECK constraint on `users` table (migration 011)
|
||||
- `test_admin` fixture fixed to properly grant `is_super_admin=True`
|
||||
- **Security Hardening (Phase B):**
|
||||
- B1: Tree access check on `start_session` via `can_access_tree` from permissions.py
|
||||
- B2: All inline permission helpers replaced with centralized imports from `permissions.py`
|
||||
- B3: `require_engineer_or_admin` checks `is_team_admin` before role check
|
||||
- B4: `is_active` field on User model (migration 012), enforced in `get_current_active_user`
|
||||
- B5: Admin user management endpoints at `/api/v1/admin/users/*` (6 endpoints)
|
||||
- B6: Rate limiting on auth endpoints via slowapi (disabled when `DEBUG=True`)
|
||||
- B7: Refresh token rotation — JTI-based revocation, meaningful logout (migration 013)
|
||||
- Access token TTL reduced from 15 to 5 minutes
|
||||
- All endpoints now use `get_current_active_user` (not `get_current_user`)
|
||||
- **Session Scratchpad (Floating Overlay):**
|
||||
- Fixed-position overlay panel (420px wide, 55vh tall) on right edge
|
||||
- Floating button when collapsed, slide-in panel when expanded
|
||||
@@ -165,6 +179,7 @@ patherly/
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── endpoints/
|
||||
│ │ │ │ ├── auth.py # Auth: register, login, refresh, logout
|
||||
│ │ │ │ ├── admin.py # Admin user management (6 endpoints)
|
||||
│ │ │ │ ├── trees.py # Trees CRUD + search
|
||||
│ │ │ │ ├── sessions.py # Sessions + export
|
||||
│ │ │ │ └── invite.py # Invite code management
|
||||
@@ -174,7 +189,8 @@ patherly/
|
||||
│ │ │ ├── config.py # Settings (pydantic-settings)
|
||||
│ │ │ ├── database.py # Async SQLAlchemy
|
||||
│ │ │ ├── permissions.py # Centralized RBAC (role checks, content guards)
|
||||
│ │ │ ├── security.py # JWT + password hashing
|
||||
│ │ │ ├── rate_limit.py # Shared slowapi limiter (disabled in DEBUG)
|
||||
│ │ │ ├── security.py # JWT + password hashing + token rotation
|
||||
│ │ │ ├── logging_config.py # Structured logging
|
||||
│ │ │ └── middleware.py # Request logging
|
||||
│ │ ├── models/ # SQLAlchemy models
|
||||
@@ -187,8 +203,9 @@ patherly/
|
||||
│ │ │ ├── category.py # TreeCategory model
|
||||
│ │ │ ├── tag.py # TreeTag model
|
||||
│ │ │ ├── folder.py # UserFolder model
|
||||
│ │ │ ├── step_category.py # StepCategory model (NEW)
|
||||
│ │ │ └── step_library.py # StepLibrary, StepRating, StepUsageLog (NEW)
|
||||
│ │ │ ├── step_category.py # StepCategory model
|
||||
│ │ │ ├── step_library.py # StepLibrary, StepRating, StepUsageLog
|
||||
│ │ │ └── refresh_token.py # RefreshToken model (JTI-based revocation)
|
||||
│ │ └── schemas/ # Pydantic schemas
|
||||
│ ├── alembic/ # Database migrations
|
||||
│ ├── scripts/
|
||||
@@ -275,8 +292,8 @@ DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/patherly
|
||||
|
||||
# JWT Settings - CHANGE THESE IN PRODUCTION
|
||||
SECRET_KEY=<generate with: openssl rand -hex 32>
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||
REFRESH_TOKEN_EXPIRE_MINUTES=10080
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=5 # Reduced from 15; refresh tokens handle session continuity
|
||||
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||
|
||||
# Auth
|
||||
REQUIRE_INVITE_CODE=true # Set false to allow open registration
|
||||
@@ -514,7 +531,7 @@ When using `allow_origin_regex` for wildcard patterns, also include `allow_origi
|
||||
|
||||
### RBAC Permission Checks
|
||||
|
||||
- Backend auth deps: `get_current_user` (any logged-in), `require_engineer_or_admin` (blocks viewers), `require_admin` (super admin only)
|
||||
- Backend auth deps: `get_current_active_user` (any logged-in + active), `require_engineer_or_admin` (blocks viewers), `require_admin` (super admin only)
|
||||
- Backend: `is_super_admin` replaces all `role == "admin"` checks. Never use `role == "admin"`.
|
||||
- Frontend: use `usePermissions()` hook for all role/permission checks
|
||||
- `TreeListItem` includes `team_id` for frontend permission checks (`author_id` and `team_id` are nullable)
|
||||
@@ -595,6 +612,7 @@ After cloning or pulling new changes, always run `alembic upgrade head` before s
|
||||
- **Categories:** `/api/v1/categories/*` - tree categories (global + team-specific)
|
||||
- **Step Categories:** `/api/v1/step-categories/*` - step categories for library
|
||||
- **Step Library:** `/api/v1/steps/*` - reusable steps, ratings, reviews, full-text search
|
||||
- **Admin:** `/api/v1/admin/users/*` - user management (list, get, change role, toggle team admin, deactivate, activate)
|
||||
- **Invite Codes:** `/api/v1/invite-codes/*` - admin management
|
||||
|
||||
**Key constraints:**
|
||||
|
||||
Reference in New Issue
Block a user