diff --git a/CLAUDE.md b/CLAUDE.md index 8550359b..47424eb0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -204,7 +204,7 @@ author = relationship("User", foreign_keys=[author_id], back_populates="trees") 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`). +**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. @@ -222,7 +222,7 @@ navigate(`/trees/${newTree.id}/edit`) - **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` (any active), `require_engineer_or_admin` (blocks viewers), `require_admin` (super admin only) +- **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`