Files
tfm_ainventory/dev_docs/SESSION_STATE.md
Daniel Bedeleanu 483a747600 fix: CORS configuration for both docker-compose and start_server.sh deployments
- 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
2026-04-11 14:44:00 +03:00

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.yml with 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_ORIGINS environment 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:

  1. Detect local IP address (en0/en1 interface)
  2. 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
  3. Display CORS configuration when starting backend
  4. 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 — returns TokenResponse (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]

  • slowapi integrated in requirements.txt
  • /items/extract-label@limiter.limit("10/minute") per IP
  • Protection against spam on AI endpoint

CORS Configuration [M-01]

  • ALLOWED_ORIGINS from 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

  1. CORS with credentials=True — requires specific origins, NOT wildcards
  2. Rate limiting — essential on expensive endpoints (AI processing)
  3. JWT expiration — 8h balances security vs. UX
  4. user_id from token — eliminates operation spoofing
  5. 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