docs: update PROJECT_STATE.md after deployment stabilization
This commit is contained in:
+112
-47
@@ -10,67 +10,132 @@ Runs as a Docker Compose stack managed via Portainer, exposed externally via Clo
|
|||||||
|
|
||||||
## Build Progress
|
## Build Progress
|
||||||
|
|
||||||
### ✅ Step 1 — Project scaffold
|
### ✅ Steps 1-7 — Complete
|
||||||
### ✅ Step 2 — Database schema
|
All backend, frontend, and deployment steps are complete. App is live and accessible.
|
||||||
### ✅ Step 3 — Auth + user management
|
|
||||||
### ✅ Step 4 — Collection import
|
|
||||||
### ✅ Step 5 — Claude AI integration
|
|
||||||
### ✅ Step 6 — React frontend
|
|
||||||
### ✅ Step 7 — First deployment
|
|
||||||
|
|
||||||
App is live at http://commander.bussenet.ca
|
---
|
||||||
|
|
||||||
|
## Live Deployment
|
||||||
|
|
||||||
|
- **URL:** https://commander.bussenet.ca
|
||||||
|
- **Admin login:** busse.daniel@gmail.com / Admin1234
|
||||||
|
- **Portainer stack:** commander-forge (ID: 54)
|
||||||
|
- **Stack type:** Pre-built images only — no build directives
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deployment Architecture
|
## Deployment Architecture
|
||||||
|
|
||||||
- Cloudflare Tunnel → Traefik (port 80) → nginx container
|
### Networking
|
||||||
- Portainer stack ID: 52 (commander-forge)
|
- Cloudflare Tunnel → `http://localhost:80` → Traefik → nginx (`traefik-public` network)
|
||||||
- Backend container manually created outside Portainer — needs reconciliation
|
- Traefik routes by hostname label using `traefik.docker.network=traefik-public`
|
||||||
- Admin login: busse.daniel@gmail.com / Admin1234
|
- All other services (backend, db, cache, frontend) on `commander-forge_internal` network
|
||||||
|
- Cloudflared runs on host network — must use `localhost` not container hostnames
|
||||||
|
|
||||||
## Known fixes applied
|
### Image Management
|
||||||
- passlib replaced with bcrypt==4.1.3
|
All three custom images are built manually on the server and Portainer uses pre-built images:
|
||||||
- npm ci replaced with npm install in frontend Dockerfile
|
```bash
|
||||||
- package-lock.json added to repo
|
sudo docker build -t commander-forge-nginx:latest --no-cache --pull http://192.168.0.62:3001/Dan/Commander-Deck-App.git#master:nginx
|
||||||
- nginx baked into image via nginx/Dockerfile
|
sudo docker build -t commander-forge-frontend:latest --no-cache http://192.168.0.62:3001/Dan/Commander-Deck-App.git#master:frontend
|
||||||
- docker-compose.yml uses Traefik labels, no port 80 binding
|
sudo docker build -t commander-forge-backend:latest --no-cache --pull http://192.168.0.62:3001/Dan/Commander-Deck-App.git#master:backend
|
||||||
- DATABASE_URL and REDIS_URL passed explicitly as env vars
|
```
|
||||||
- UserRole enum uses values_callable for lowercase storage
|
|
||||||
- Portainer git source caches aggressively — use --no-cache --pull for rebuilds
|
After rebuilding, redeploy the stack in Portainer to pick up the new images.
|
||||||
|
|
||||||
|
### Why pre-built images?
|
||||||
|
Portainer's repository-based builds aggressively cache the git source. Even with `--no-cache --pull`, Portainer's internal git clone cache serves stale code. Pre-built images bypass this entirely.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Fixes Applied
|
||||||
|
|
||||||
|
- `passlib` replaced with `bcrypt==4.1.3` in requirements.txt and security.py
|
||||||
|
- `npm ci` replaced with `npm install` in frontend Dockerfile (Windows-generated lockfile missing Linux binaries)
|
||||||
|
- `package-lock.json` added to repo
|
||||||
|
- nginx baked into its own image via `nginx/Dockerfile` (Portainer pre-creates volume mount paths as directories)
|
||||||
|
- `docker-compose.yml` uses Traefik labels + `traefik.docker.network=traefik-public`
|
||||||
|
- `DATABASE_URL` and `REDIS_URL` passed explicitly as env vars
|
||||||
|
- `UserRole` enum members renamed to lowercase (`pending/approved/admin`) to match database values
|
||||||
|
- `admin_bootstrap.py` and `deps.py` updated to use lowercase `UserRole.admin`, `UserRole.pending`, etc.
|
||||||
|
- Portainer git source caches aggressively — always use `--no-cache --pull` and pre-built images
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Infrastructure
|
## Infrastructure
|
||||||
- Gitea: http://192.168.0.62:3001 / https://gitea.bussenet.ca
|
|
||||||
- GitHub mirror: https://github.com/danbusse/Commander-Deck-App (private)
|
| Service | URL | Notes |
|
||||||
- Portainer MCP: fixed, using custom mcp-portainer:latest image with -- entrypoint fix
|
|---------|-----|-------|
|
||||||
- Cloudflare tunnel: degraded (region2 unreachable, ISP routing issue), region1 stable
|
| Commander Forge | https://commander.bussenet.ca | Main app |
|
||||||
|
| Portainer | https://portainer.bussenet.ca | Stack management |
|
||||||
|
| Gitea | https://gitea.bussenet.ca | Primary git (SSH port 2222) |
|
||||||
|
| GitHub mirror | https://github.com/danbusse/Commander-Deck-App | Private, Claude's file access path |
|
||||||
|
| Vault | https://vault.bussenet.ca | Secrets store |
|
||||||
|
| Portainer MCP | https://mcp-portainer.bussenet.ca/sse | Custom image with entrypoint fix |
|
||||||
|
|
||||||
|
### Portainer MCP
|
||||||
|
Custom `mcp-portainer:latest` image built from `ghcr.io/serraniel/portainer-mcp-docker:http` with a fixed entrypoint that passes `--` before the portainer-mcp command. Tools written to `/tmp/tools.yaml`. PORTAINER_SERVER must be set without protocol prefix (e.g. `192.168.0.62:9443`) since the MCP binary always prepends `https://`.
|
||||||
|
|
||||||
|
### Cloudflare Tunnel
|
||||||
|
- Tunnel ID: `3a032a2b-aa42-46a2-b749-e3fa9166ac59`
|
||||||
|
- Only region1 (`198.41.192.x`) is reachable — region2 (`198.41.200.x`) times out (ISP routing issue, outside our control)
|
||||||
|
- Tunnel maintains 1 of 4 connections; services are accessible but logs show constant reconnect attempts
|
||||||
|
- Cloudflared runs on host network — all tunnel ingress entries use `localhost` not container IPs
|
||||||
|
|
||||||
|
### GitHub API Access
|
||||||
|
Claude can read/write files to the GitHub mirror using token stored in Vault at `secret/github.claude-api-token`. This is the primary mechanism for Claude to update project files between sessions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Environment Variables (Portainer stack env)
|
## Environment Variables (Portainer stack env)
|
||||||
- SECRET_KEY: changeme (needs replacing)
|
|
||||||
- POSTGRES_PASSWORD: changeme (needs replacing)
|
| Variable | Value | Notes |
|
||||||
- DATABASE_URL: postgresql+asyncpg://mtg:changeme@db:5432/mtgdb
|
|----------|-------|-------|
|
||||||
- REDIS_URL: redis://cache:6379
|
| SECRET_KEY | changeme | ⚠️ Needs replacing |
|
||||||
- ANTHROPIC_API_KEY: in Vault at secret/anthropic
|
| POSTGRES_PASSWORD | changeme | ⚠️ Needs replacing |
|
||||||
- ADMIN_EMAIL: busse.daniel@gmail.com
|
| POSTGRES_DB | mtgdb | |
|
||||||
- ADMIN_PASSWORD: Admin1234
|
| POSTGRES_USER | mtg | |
|
||||||
|
| DATABASE_URL | postgresql+asyncpg://mtg:changeme@db:5432/mtgdb | ⚠️ Update with new password |
|
||||||
|
| REDIS_URL | redis://cache:6379 | |
|
||||||
|
| ANTHROPIC_API_KEY | (in Vault at secret/anthropic) | |
|
||||||
|
| ADMIN_EMAIL | busse.daniel@gmail.com | |
|
||||||
|
| ADMIN_PASSWORD | Admin1234 | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git Workflow
|
||||||
|
|
||||||
|
Two remotes are configured:
|
||||||
|
- `origin` → Gitea (`ssh://git@192.168.0.62:2222/Dan/Commander-Deck-App.git`)
|
||||||
|
- `github` → GitHub (`https://github.com/danbusse/Commander-Deck-App.git`)
|
||||||
|
|
||||||
|
Always push to both:
|
||||||
|
```bash
|
||||||
|
git push origin master
|
||||||
|
git push github master
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Next Session — Start Here
|
## Next Session — Start Here
|
||||||
|
|
||||||
**Priority 1 — Portainer housekeeping:**
|
**Priority 1 — Harden credentials:**
|
||||||
Backend container was manually created outside Portainer stack. Needs clean redeploy.
|
- Generate new SECRET_KEY: `openssl rand -hex 32`
|
||||||
|
- Set strong POSTGRES_PASSWORD
|
||||||
|
- Update DATABASE_URL to match
|
||||||
|
- Update these in Portainer stack env vars
|
||||||
|
|
||||||
**Priority 2 — Harden credentials:**
|
**Priority 2 — Test end to end:**
|
||||||
- SECRET_KEY → openssl rand -hex 32
|
|
||||||
- POSTGRES_PASSWORD → strong password
|
|
||||||
- DATABASE_URL → update to match
|
|
||||||
|
|
||||||
**Priority 3 — Test end to end:**
|
|
||||||
- Try building a deck via Generate mode
|
- Try building a deck via Generate mode
|
||||||
- Test collection import with Archidekt export
|
- Test collection import with an Archidekt export
|
||||||
- Verify admin approval flow
|
- Verify admin approval flow for a new registered user
|
||||||
|
|
||||||
**Priority 4 — GitHub mirror sync:**
|
**Priority 3 — Commit docker-compose.yml changes to repo:**
|
||||||
When committing from Windows: push to both Gitea and GitHub
|
The docker-compose.yml in the repo still has `build:` directives. Update it to use `image:` directives to match the actual deployment approach:
|
||||||
git push origin master
|
```yaml
|
||||||
git push github master
|
backend:
|
||||||
Or set up automatic mirror push from Gitea.
|
image: commander-forge-backend:latest
|
||||||
|
frontend:
|
||||||
|
image: commander-forge-frontend:latest
|
||||||
|
nginx:
|
||||||
|
image: commander-forge-nginx:latest
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user