- Update start_server.sh to auto-detect local IP and export ALLOWED_ORIGINS - Includes both localhost and detected IP on HTTP/HTTPS proxy ports - Export JWT_SECRET_KEY with ephemeral key if not set - Fix Romanian comments in docker-compose.yml to English - Document two deployment methods in SESSION_STATE.md
8.9 KiB
CURRENT AI WORKING SESSION — IN PROGRESS
Active AI: Claude (Haiku 4.5) Last Updated: 2026-04-11 Current Version: v1.3.5 Branch: dev
🔧 CURRENT ISSUE — CORS Configuration Clarification
Two Deployment Methods
The project supports two distinct deployment approaches:
1. Docker Compose (Production / Containerized)
- Uses
docker-compose.ymlwith Caddy reverse proxy - Backend container on internal port 8000 → exposed via Caddy on 3002
- Frontend container on internal port 3000 → exposed via Caddy on 3003
- Configuration:
ALLOWED_ORIGINSenvironment variable in docker-compose.yml - Current setting:
http://localhost:3000,http://localhost:3002 - For remote deployment: Must update ALLOWED_ORIGINS to include actual domain (e.g.,
https://192.168.84.140:3003)
2. start_server.sh (Development / Native)
- Runs Backend (uvicorn) + Frontend (Next.js) + local-ssl-proxy directly
- Backend on port 8000 → SSL proxy on 3002
- Frontend on port 3001 → SSL proxy on 3003
- Issue Fixed: Script now automatically detects local IP and exports ALLOWED_ORIGINS
- Auto-configured for: localhost + detected IP address on both HTTP and HTTPS
Fix Applied (Commit Pending)
Updated start_server.sh to:
- Detect local IP address (en0/en1 interface)
- Export ALLOWED_ORIGINS with all applicable origins:
- HTTP localhost on dev ports (3000/3001)
- HTTPS localhost on proxy ports (3002/3003)
- HTTPS on detected IP address on proxy ports
- Display CORS configuration when starting backend
- Export JWT_SECRET_KEY if not already set
Result: Frontend at https://<LOCAL_IP>:3003 can now access backend at https://<LOCAL_IP>:3002 without CORS blocks.
English Language Compliance
Fixed Romanian comments in docker-compose.yml:
"personalizează pentru producție"→"customize for production""GENEREAZĂ O VALOARE SIGURĂ"→"GENERATE A SECURE VALUE"
🎯 PREVIOUS SESSION — ALL TASKS FINALIZED + ENGLISH COMPLIANCE VERIFIED
Final Status
✅ Security Audit — complete (12 vulnerabilities, 6 direct patches) ✅ [C-01] JWT Bearer Auth — complete (backend + frontend) ✅ [H-02] Rate Limiting — complete (10 req/min on /items/extract-label) ✅ [M-01] CORS Configuration — complete (ALLOWED_ORIGINS from env) ✅ [L-01] Token Expiry — complete (8h JWT expiration) ✅ STRICT ENGLISH POLICY — complete (all code, comments, docstrings translated; no Co-Authored-By signatures)
Session Commits
| Hash | Description |
|---|---|
247ea454 |
security: audit + 6 patches (C-02, C-03, H-01, H-03, M-01, M-03) |
9b6adad6 |
feat: JWT Bearer auth on all routers |
e9ada004 |
docs: update SESSION_STATE JWT complete |
e6ca33f2 |
feat: frontend JWT, rate limiting, CORS |
2574726f |
docs: final SESSION_STATE all tasks complete |
📋 Complete Implementations
Backend
JWT Authentication [C-01]
- ✅
backend/auth.py— JWT creation, validation, role checking - ✅
/users/login— returnsTokenResponse(access_token, user_id, role, 8h expiry) - ✅ All routers —
Depends(get_current_user)enforcement - ✅ Admin-only endpoints —
Depends(get_current_admin) - ✅ user_id — extracted from JWT token, NOT from request body [M-02]
Rate Limiting [H-02]
- ✅
slowapiintegrated in requirements.txt - ✅
/items/extract-label—@limiter.limit("10/minute")per IP - ✅ Protection against spam on AI endpoint
CORS Configuration [M-01]
- ✅
ALLOWED_ORIGINSfrom environment variable (fallback: localhost:3000, localhost:3002) - ✅ Specific HTTP methods: GET, POST, PUT, DELETE, OPTIONS
- ✅ allow_credentials=True (valid with specific origins)
Direct Patches
- ✅ C-02 — Removed passwordless bypass
- ✅ C-03 — Admin seed with random password
- ✅ H-01 — LDAP injection fix (escape_filter_chars)
- ✅ H-03 — MIME validation + 10MB upload limit
- ✅ M-03 — LDAP logging via log.debug()
Frontend
JWT Handling [L-01]
- ✅
frontend/lib/auth.ts— saveToken, getToken, getAuthHeader, clearAuth - ✅ Token storage — localStorage (inventory_token + inventory_user)
- ✅ Login page — saves TokenResponse from /users/login
- ✅ Token attachment — Axios interceptor adds
Authorization: Bearer <token>to all requests
Token Expiry [L-01]
- ✅ 401 Unauthorized → clearAuth() + redirect /login
- ✅ Interceptor on axiosInstance
- ✅ Auto-logout on expiration
Deployment
docker-compose.yml
- ✅ Backend environment variables: DATA_DIR, LOGS_DIR, ALLOWED_ORIGINS, JWT_SECRET_KEY
- ✅ Comments for production configuration
- ✅ Fallback values for development
Environment Variables
| Variable | Dev Default | Production Required | Purpose |
|---|---|---|---|
| ALLOWED_ORIGINS | localhost:3000, localhost:3002 | SET REQUIRED | CORS allowed origins |
| JWT_SECRET_KEY | ephemeral (random) | SET REQUIRED | JWT signing key |
| DATA_DIR | /app/data | - | SQLite database location |
| LOGS_DIR | /app/logs | - | Application logs location |
📊 Vulnerability Status
| ID | Severity | Description | Status |
|---|---|---|---|
| C-01 | 🔴 CRITICAL | Zero authentication on API | ✅ PATCHED (JWT) |
| C-02 | 🔴 CRITICAL | Passwordless user bypass | ✅ PATCHED |
| C-03 | 🔴 CRITICAL | Default "admin" password | ✅ PATCHED |
| C-04 | 🔴 CRITICAL | Gemini API key exposed | ✅ SAFE (never in git) |
| H-01 | 🟠 HIGH | LDAP injection | ✅ PATCHED |
| H-02 | 🟠 HIGH | Missing rate limit | ✅ PATCHED |
| H-03 | 🟠 HIGH | File upload validation | ✅ PATCHED |
| H-04 | 🟠 HIGH | Admin endpoints exposed | ✅ PATCHED (JWT) |
| M-01 | 🟡 MEDIUM | CORS wildcard | ✅ PATCHED |
| M-02 | 🟡 MEDIUM | user_id from body | ✅ PATCHED |
| M-03 | 🟡 MEDIUM | Debug LDAP logging | ✅ PATCHED |
| L-01 | 🔵 LOW | Token expiry | ✅ PATCHED |
🚀 Production Deployment Checklist
CRITICAL — Set these environment variables before deploy:
- JWT_SECRET_KEY — Generate with
openssl rand -hex 32(store in secrets manager) - ALLOWED_ORIGINS — Set to actual production domain(s), e.g.,
https://inventory.example.com - TLS/HTTPS — Caddy proxy configured with valid SSL certificate
- Database backup — SQLite data/ mapped to persistent volume
- Logs rotation — logs/ mapped and monitored
RECOMMENDED:
- Set log level to WARNING (not DEBUG)
- Configure rate limiting at reverse proxy level (nginx/Cloudflare) for DDoS protection
- Monitor alert on 401 spikes (token expiry issues)
- Periodic JWT_SECRET_KEY rotation (quarterly minimum)
🧪 Local Testing
1. Start Development Stack
docker-compose up --build
2. Test Login
curl -X POST http://localhost:8000/users/login \
-H "Content-Type: application/json" \
-d '{"username": "Admin", "password": "<initial_password_from_logs>"}'
3. Test Protected Endpoint with Token
curl -H "Authorization: Bearer <access_token>" \
http://localhost:8000/items/
4. Test 401 Unauthorized (invalid token)
curl -H "Authorization: Bearer invalid_token" \
http://localhost:8000/items/
# Expected: 401 Unauthorized
5. Test Rate Limiting (extract-label endpoint)
# 11 requests rapid fire — 11th should fail with 429
for i in {1..15}; do
curl -X POST -F "file=@image.jpg" \
-H "Authorization: Bearer <token>" \
http://localhost:8000/items/extract-label
sleep 0.1
done
✅ Validations Completed
- ✅ Backend fully secured with JWT
- ✅ Frontend token handling complete
- ✅ Rate limiting on AI endpoint
- ✅ CORS configurable via environment
- ✅ All routers have authentication enforcement
- ✅ Token expiry with automatic login redirect
- ✅ Admin role checks functional
- ✅ LDAP injection protection
- ✅ File upload validation
- ✅ Audit logging with user_id from token
🎓 Key Learnings
- CORS with credentials=True — requires specific origins, NOT wildcards
- Rate limiting — essential on expensive endpoints (AI processing)
- JWT expiration — 8h balances security vs. UX
- user_id from token — eliminates operation spoofing
- Debug logging — careful with PII leaks (LDAP DNs)
📝 Production Environment Variables Example
# Set these before `docker-compose up`
export JWT_SECRET_KEY="$(openssl rand -hex 32)"
export ALLOWED_ORIGINS="https://inventory.example.com,https://api.example.com"
docker-compose up -d
Or in .env.production (NOT in git):
JWT_SECRET_KEY=abcdef1234567890...
ALLOWED_ORIGINS=https://inventory.example.com
Status: 🚀 PRODUCTION-READY (with environment configuration required)
Future Scope (OUT OF SCOPE):
- Email verification for new users
- 2FA/TOTP support
- OAuth2 federation (GitHub/Google/Azure)
- API key management for service accounts
- Audit log export/archival to cold storage