From cf6d8bd57b66c0a7fae14774fe746ad25e7bea4c Mon Sep 17 00:00:00 2001 From: chihlasm Date: Fri, 6 Feb 2026 00:40:34 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20audit=20and=20improve=20CLAUDE.md=20?= =?UTF-8?q?=E2=80=94=20add=20Phase=20C/D,=20trim=20verbose=20sections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 186 +++++++++++++++--------------------------------------- 1 file changed, 50 insertions(+), 136 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2182af48..0ae5ac94 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,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 (25+ API endpoints, 50+ integration tests, all passing) +- **Backend:** Complete (25+ API endpoints, 60+ integration tests, all passing) - **Frontend:** Core features complete, Tree Editor functional, Settings page added - **Database:** PostgreSQL with Docker (container name: `patherly_postgres`) @@ -125,6 +125,19 @@ When adding new frontend pages or components, use "ResolutionFlow" for any user- - 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`) +- **Permissions UX (Phase C):** + - Super admin bypass in tree list filter (`build_tree_access_filter` returns `sa_true()`) + - Audit log table (`audit_logs`) with JSONB details, integrated at admin + tree delete endpoints + - Soft delete for trees (`deleted_at` + `deleted_by` columns, migration 015) + - ProtectedRoute supports optional `requiredRole` prop for role-based route guards + - TreeEditorPage checks `canEditTree()` after fetch, before loading into editor + - Reusable `ConfirmDialog` component + tree delete UI on library page + - CustomStepModal hides "Type My Own" tab for users without `canCreateSteps` +- **Permissions Cleanup (Phase D):** + - Password complexity validation: requires uppercase, lowercase, and digit (min 10 chars) + - Soft delete cascade: cleans up folder/tag junction entries on tree delete + - Debug endpoint `/debug/cors` gated behind `if settings.DEBUG:` + - Tag search escapes SQL wildcards (`%`, `_`) before LIKE query - **Session Scratchpad (Floating Overlay):** - Fixed-position overlay panel (420px wide, 55vh tall) on right edge - Floating button when collapsed, slide-in panel when expanded @@ -182,12 +195,18 @@ patherly/ │ │ │ │ ├── admin.py # Admin user management (6 endpoints) │ │ │ │ ├── trees.py # Trees CRUD + search │ │ │ │ ├── sessions.py # Sessions + export -│ │ │ │ └── invite.py # Invite code management +│ │ │ │ ├── invite.py # Invite code management +│ │ │ │ ├── categories.py # Tree categories (global + team) +│ │ │ │ ├── tags.py # Tree tags + autocomplete +│ │ │ │ ├── folders.py # User folders (hierarchy) +│ │ │ │ ├── steps.py # Step library CRUD + search +│ │ │ │ └── step_categories.py # Step categories │ │ │ ├── deps.py # Auth dependencies │ │ │ └── router.py │ │ ├── core/ │ │ │ ├── config.py # Settings (pydantic-settings) │ │ │ ├── database.py # Async SQLAlchemy +│ │ │ ├── audit.py # Centralized audit log helper (log_audit) │ │ │ ├── permissions.py # Centralized RBAC (role checks, content guards) │ │ │ ├── rate_limit.py # Shared slowapi limiter (disabled in DEBUG) │ │ │ ├── security.py # JWT + password hashing + token rotation @@ -205,7 +224,8 @@ patherly/ │ │ │ ├── folder.py # UserFolder model │ │ │ ├── step_category.py # StepCategory model │ │ │ ├── step_library.py # StepLibrary, StepRating, StepUsageLog -│ │ │ └── refresh_token.py # RefreshToken model (JTI-based revocation) +│ │ │ ├── refresh_token.py # RefreshToken model (JTI-based revocation) +│ │ │ └── audit_log.py # AuditLog model (JSONB details, indexed) │ │ └── schemas/ # Pydantic schemas │ ├── alembic/ # Database migrations │ ├── scripts/ @@ -238,11 +258,12 @@ patherly/ │ │ │ ├── treeEditorStore.ts # Tree editor state (immer + zundo) │ │ │ └── userPreferencesStore.ts # User preferences (NEW) │ │ ├── components/ -│ │ │ ├── common/ # Modal, ErrorBoundary, ThemeToggle +│ │ │ ├── common/ # Modal, ErrorBoundary, ThemeToggle, ConfirmDialog │ │ │ ├── layout/ # AppLayout, ProtectedRoute │ │ │ ├── tree-editor/ # Tree editor components │ │ │ ├── tree-preview/ # Visual tree preview │ │ │ ├── step-library/ # Step library browser, forms, modals +│ │ │ ├── library/ # Tree library UI components │ │ │ ├── session/ # Session modals, scratchpad floating overlay │ │ │ └── ui/ # MarkdownContent │ │ ├── pages/ @@ -492,6 +513,16 @@ await db.execute( ``` Accessing relationships on newly created objects triggers lazy loading, which fails in async SQLAlchemy. Use direct SQL inserts for junction tables instead. +### SQLAlchemy: Multiple FKs to Same Table Require `foreign_keys` + +When a model has two FKs to the same table (e.g., Tree has `author_id` and `deleted_by` both pointing to `users`), specify `foreign_keys` on BOTH sides: +```python +# On Tree model +author = relationship("User", foreign_keys=[author_id], back_populates="trees") +# On User model +trees = relationship("Tree", foreign_keys="[Tree.author_id]", back_populates="author") +``` + ### React Router: Clear Dirty State Before Navigation ```tsx @@ -626,49 +657,10 @@ For detailed parameters, request/response schemas, and examples, visit the API d ## Data Models -### Tree Structure (JSONB) +Key JSONB structures stored in PostgreSQL. See `frontend/src/types/` for full TypeScript interfaces. -```typescript -interface TreeStructure { - id: string - type: 'decision' | 'action' | 'solution' - - // Decision nodes - question?: string - help_text?: string - options?: Array<{ - id: string - label: string - next_node_id?: string - }> - - // Action nodes - title?: string - description?: string - commands?: string[] - next_node_id?: string - - // Solution nodes - title?: string - description?: string - steps?: string[] - - // All nodes can have children - children?: TreeStructure[] -} -``` - -### Session Decisions (JSONB) - -```typescript -interface Decision { - node_id: string - question?: string - answer: string - notes?: string - timestamp: string // ISO string, not datetime object -} -``` +- **Tree Structure:** Recursive node tree (`decision`/`action`/`solution` types with `children[]`). See `types/tree.ts`. +- **Session Decisions:** Array of `{node_id, question, answer, notes, timestamp}`. Timestamps are ISO strings, not datetime objects. --- @@ -728,34 +720,10 @@ Position overlay at `right-2` (not `right-0`) so it sits inside the page scrollb ## Common Tasks -### Adding a New API Endpoint - -1. Create route in `backend/app/api/endpoints/` -2. Add to router in `backend/app/api/router.py` -3. Create/update Pydantic schemas in `backend/app/schemas/` -4. Add tests in `backend/tests/` -5. Update API client in `frontend/src/api/` - -### Adding a New API Client Module (Frontend) - -1. Create types in `frontend/src/types/modulename.ts` -2. Export types from `frontend/src/types/index.ts` -3. Create API client in `frontend/src/api/modulename.ts` following existing pattern -4. Export from `frontend/src/api/index.ts` -5. Import in components: `import { moduleApi } from '@/api'` - -### Adding a New Page - -1. Create page component in `frontend/src/pages/` -2. Add route in `frontend/src/router.tsx` -3. Add navigation link in `AppLayout.tsx` if needed - -### Modifying Database Schema - -1. Update model in `backend/app/models/` -2. Create migration: `alembic revision --autogenerate -m "description"` -3. Review generated migration file -4. Apply: `alembic upgrade head` +- **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` --- @@ -798,28 +766,11 @@ Position overlay at `right-2` (not `right-0`) so it sits inside the page scrollb ### Phase 2.5 (In Progress) -- ✅ Step Categories database and API -- ✅ Step Library database schema (step_library, step_ratings, step_usage_log) -- ✅ Step Library CRUD API with search and ratings -- ✅ User Preferences (Settings page, export format default) -- 🔲 Step Library browser component (frontend) -- 🔲 Add Custom Step button in tree navigation -- 🔲 Custom step creation modal -- 🔲 Personal tree branching (add custom steps during sessions) -- 🔲 Tree forking and sharing +- Custom step continuation flow refinements +- Tree forking from sessions with custom steps -### Phase 3 (Planned) - -- File attachments (screenshots, logs) -- Offline mode (Service Workers + IndexedDB) -- Client context system -- Analytics dashboard - -### Phase 4 (Planned) - -- API & integrations (ConnectWise, Kaseya) -- PowerShell automation execution -- Enterprise features (SSO, white-labeling) +### Phase 3 — File attachments, offline mode, client context, analytics +### Phase 4 — PSA integrations (ConnectWise, Kaseya), PowerShell automation, enterprise SSO --- @@ -933,57 +884,20 @@ Railway creates isolated preview environments for each pull request. - Migrations run automatically via `releaseCommand` - Domains must be generated manually for each PR service -**Debug Endpoints (available in PR environments):** -- `/debug/cors` - Check CORS configuration (allow_railway_origins, cors_mode) +**Debug Endpoints (only when `DEBUG=True`):** +- `/debug/cors` - Check CORS configuration (requires `DEBUG=True` in environment) ### Railway CLI (Local) -The Railway CLI can be installed locally for managing deployments, viewing logs, and checking service status. - -**Setup on a new machine:** +Railway CLI installed via npm in project root (gitignored). Services: `patherly` (backend), `hopeful-liberation` (frontend), `Postgres` (DB). ```powershell -# 1. Install Railway CLI via npm (in project root) -cd C:\Dev\Projects\patherly -npm init -y -npm install @railway/cli - -# 2. Login to Railway -./node_modules/.bin/railway login - -# 3. Link to the project -./node_modules/.bin/railway link -# Select: selfless-grace → production -``` - -**Common Commands:** - -```powershell -# Check service status -./node_modules/.bin/railway service status --service patherly +# Common commands (run from project root) ./node_modules/.bin/railway service status --all - -# View logs ./node_modules/.bin/railway service logs --service patherly - -# Check environment variables ./node_modules/.bin/railway variables --service patherly - -# Deploy new code (from backend directory) -cd backend && ../node_modules/.bin/railway up --service patherly - -# Redeploy existing build -./node_modules/.bin/railway service redeploy --service patherly --yes ``` -**Services:** - -- `patherly` - Backend API -- `hopeful-liberation` - Frontend -- `Postgres` - Database - -**Note:** The `node_modules/`, `package.json`, and `package-lock.json` files for the Railway CLI are gitignored (local tooling only). - --- ## Contact