docs: consolidate LESSONS-LEARNED.md into CLAUDE.md, single source of truth

Merged 8 unique lessons (#30-#37) from LESSONS-LEARNED.md into CLAUDE.md:
Alembic env.py imports, JSONB datetime serialization, export pipeline order,
Railway deployment gotchas, bcrypt pinning, email validator TLD, first admin
promotion. Deleted LESSONS-LEARNED.md and updated all references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-01 14:51:43 -05:00
parent a1c9675be7
commit 9811c56280
4 changed files with 21 additions and 939 deletions

View File

@@ -114,7 +114,7 @@ patherly/
│ └── tailwind.config.js
├── CLAUDE.md # This file
├── CURRENT-STATE.md # Detailed feature status
├── LESSONS-LEARNED.md # Bugs and fixes (READ THIS!)
├── LESSONS-LEARNED.md # (Deprecated — consolidated into CLAUDE.md)
└── docs/plans/ # Design docs & implementation plans
```
@@ -194,8 +194,6 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
## Critical Lessons Learned
**Full reference:** [LESSONS-LEARNED.md](LESSONS-LEARNED.md) — read before making changes!
### Top Gotchas (most commonly hit)
**1. DateTime Handling — Always timezone-aware:**
@@ -290,6 +288,22 @@ navigate(`/trees/${newTree.id}/edit`)
**29. ESLint `no-unused-vars` has no `argsIgnorePattern`:** Underscore-prefixed callback params (e.g., `_count`) still trigger errors. Use `// eslint-disable-next-line @typescript-eslint/no-unused-vars` or remove the param if the type signature allows it.
**30. Alembic `env.py` must import all models:** New models won't be discovered by `--autogenerate` unless imported in `alembic/env.py`. If a migration runs but the table isn't created, check imports first.
**31. JSONB fields — convert datetime to `.isoformat()` string:** Storing `datetime` objects directly in JSONB columns causes serialization errors. Always convert: `"timestamp": datetime.now(timezone.utc).isoformat()`.
**32. Export pipeline order matters:** Generate export → resolve session variables → apply redaction. Redaction MUST run last or sensitive data injected via variables bypasses it. See `sessions.py` export endpoint.
**33. Railway: `DATABASE_URL_SYNC` is a property, not an env var:** It derives from `DATABASE_URL` by replacing `postgresql+asyncpg://` with `postgresql://`. Delete any stale `DATABASE_URL_SYNC` variable in Railway dashboard.
**34. Railway: run migrations in Docker CMD, not `releaseCommand`:** `releaseCommand` in `railway.toml` is unreliable. Use `CMD alembic upgrade head && uvicorn ...` in the Dockerfile instead.
**35. `bcrypt==4.0.1` pinned for passlib compatibility:** Newer bcrypt versions break password hashing. Keep `bcrypt==4.0.1` and `passlib[bcrypt]==1.7.4` pinned in `requirements.txt`.
**36. Email validator rejects `.local` TLD:** Pydantic's email validation (via `email-validator`) rejects `.local` as a reserved TLD. Use `example.com` for test/seed user emails.
**37. First deployed user needs manual admin promotion:** New users default to `engineer` role. Promote via SQL: `UPDATE users SET role = 'admin' WHERE email = '...';` then re-login for new JWT.
---
## RBAC & Permissions
@@ -392,6 +406,6 @@ When a feature, fix, or significant piece of work is finished and merged/committ
| Detailed Status | [CURRENT-STATE.md](CURRENT-STATE.md) |
| Development Roadmap | [03-DEVELOPMENT-ROADMAP.md](03-DEVELOPMENT-ROADMAP.md) |
| GitHub Issues | `gh issue list --state open` |
| Bugs & Fixes | [LESSONS-LEARNED.md](LESSONS-LEARNED.md) |
| Bugs & Fixes | CLAUDE.md → Critical Lessons Learned section |
| Feature Specs | [04-FEATURE-SPECIFICATIONS.md](04-FEATURE-SPECIFICATIONS.md) |
| Design System | [docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md](docs/plans/Frontend/DESIGN_SYSTEM_GUIDE.md) |