fix: Custom step navigation bugs - go-back, descendants, redundant checkbox

- Show previously-created custom steps as clickable options on decision
  nodes so they remain accessible after going back
- Fix breadcrumb to show custom step titles instead of raw UUIDs
- Fix ContinuationModal to show grandchildren (two levels deep) instead
  of immediate children that duplicate option labels
- Remove redundant "Save to Library" checkbox from StepForm since
  PostStepActionModal now handles that decision

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-02-03 21:17:54 -05:00
parent 6bd21d7efc
commit 27624fbe55
5 changed files with 234 additions and 34 deletions

View File

@@ -2,7 +2,7 @@
> **Purpose:** This file documents bugs, fixes, and gotchas encountered during development.
> **For Claude Code:** Read this file at the start of each session to avoid repeating past mistakes.
> **Last Updated:** January 30, 2026
> **Last Updated:** February 1, 2026
---
@@ -570,6 +570,160 @@ pip install httpx
---
## Railway Deployment
### DATABASE_URL_SYNC Must Derive from DATABASE_URL ⚠️ CRITICAL
**Problem:** Alembic migrations run but connect to localhost instead of Railway's Postgres. Database tables never get created.
**Cause:** `DATABASE_URL_SYNC` was a separate pydantic field with a default value pointing to `localhost:5432`. Railway only provides `DATABASE_URL`, so the sync version wasn't being set correctly.
**Solution:** Make `DATABASE_URL_SYNC` a property that derives from `DATABASE_URL`:
```python
# BAD: Separate field with default
DATABASE_URL_SYNC: str = "postgresql://postgres:postgres@localhost:5432/patherly"
# GOOD: Property that derives from DATABASE_URL
@property
def DATABASE_URL_SYNC(self) -> str:
"""Get sync URL by removing asyncpg prefix from DATABASE_URL."""
return self.DATABASE_URL.replace("postgresql+asyncpg://", "postgresql://", 1)
```
**Files affected:** `backend/app/core/config.py`
---
### Railway releaseCommand May Not Execute
**Problem:** Migrations in `railway.toml` `releaseCommand` don't run. Deploy logs show the app starting but no migration output.
**Cause:** Railway's `releaseCommand` feature may not work reliably with all configurations, especially with Dockerfile builds.
**Solution:** Run migrations in the Docker CMD instead:
```dockerfile
# Instead of relying on railway.toml releaseCommand:
CMD alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-8000}
```
**Files affected:** `backend/Dockerfile`, `backend/railway.toml` (keep releaseCommand as backup)
---
### Alembic env.py Must Import All Models
**Problem:** Migration runs but table isn't created. Or migration fails with model-related errors.
**Cause:** Alembic's `env.py` only discovers models that are imported. If you add a new model (like `InviteCode`), you must add it to the imports.
**Solution:** Add new models to the import statement in `alembic/env.py`:
```python
# BEFORE: Missing InviteCode
from app.models import User, Team, Tree, Session, Attachment
# AFTER: All models imported
from app.models import User, Team, Tree, Session, Attachment, InviteCode
```
**Files affected:** `backend/alembic/env.py`
---
### New Users Default to "engineer" Role, Not Admin
**Problem:** After registering, user cannot access admin-only endpoints (like creating invite codes). Returns 403 Forbidden.
**Cause:** The User model defaults to `role="engineer"`. The first user isn't automatically made admin.
**Solution:** Manually promote user to admin via Railway's Postgres Query tab:
```sql
UPDATE users SET role = 'admin' WHERE email = 'your@email.com';
```
**Then log out and back in** to get a new JWT with the updated role.
**Files affected:** Database (manual update required for first admin)
---
### Frontend VITE_API_URL Must Use HTTPS, No Port
**Problem:** Frontend gets "Network Error" when trying to call API on Railway.
**Cause:** Common mistakes:
- Using `http://` instead of `https://`
- Including port number (`:8080`) when Railway handles routing
- Typos in variable names (e.g., `FRONTED_URL` vs `FRONTEND_URL`)
**Solution:** Ensure correct format:
```
# WRONG
VITE_API_URL=http://api.patherly.com:8080
VITE_API_URL=http://api.patherly.com
# CORRECT
VITE_API_URL=https://api.patherly.com
```
**Note:** This is a **build-time** variable. After changing it, you must trigger a new frontend build/deploy.
---
### Swagger OAuth2 Password Flow Returns 401
**Problem:** Clicking "Authorize" in Swagger UI with username/password returns 401, even with correct credentials.
**Workaround:** Use the login endpoint directly instead:
1. Call `POST /api/v1/auth/login` with your credentials
2. Copy the `access_token` from the response
3. Click "Authorize" button
4. Paste just the token (no "Bearer" prefix) in the authorization field
**Files affected:** This is a Swagger UI / FastAPI OAuth2 configuration quirk
---
### Seed Script: Use --email/--password Instead of Creating User
**Problem:** Seed script fails when `REQUIRE_INVITE_CODE=true` because it tries to register a new seed user without an invite code.
**Solution:** Modified seed script to accept admin credentials via CLI arguments:
```bash
python -m scripts.seed_trees \
--api-url https://api.patherly.com/api/v1 \
--email admin@patherly.com \
--password "your-password"
```
**Files affected:** `backend/scripts/seed_trees.py`
---
### Seed Script: Use venv Python, Not System Python
**Problem:** Running `python -m scripts.seed_trees` fails with `ModuleNotFoundError: No module named 'httpx'` even after installing httpx.
**Cause:** Installing with system Python (`pip install httpx`) but running with venv Python, or vice versa.
**Solution:** Always use the venv's Python explicitly:
```powershell
# Use venv Python directly
./venv/Scripts/python -m scripts.seed_trees --api-url ... --email ... --password ...
# Or ensure venv is activated first
.\venv\Scripts\Activate
python -m scripts.seed_trees ...
```
**Files affected:** Any script in `backend/scripts/`
---
### Railway Environment Variable Naming
**Problem:** Environment variable isn't being read by the application.
**Checklist:**
- Case-sensitive: `FRONTEND_URL``frontend_url``Frontend_Url`
- No typos: `FRONTEND_URL``FRONTED_URL`
- Empty string vs not set: Setting a variable to empty string is different from not setting it
- Delete stale variables: If you changed a variable from a field to a property (like `DATABASE_URL_SYNC`), delete the Railway variable
**Files affected:** Railway dashboard → Service → Variables tab
---
## Adding New Lessons
When you encounter and fix a bug, add it here with: