Files
bakery-ia/DEMO_IMPLEMENTATION_SUMMARY.md
2025-10-03 14:09:34 +02:00

15 KiB

Demo Architecture Implementation Summary

Implementation Complete

All components of the production demo system have been implemented. This document provides a summary of what was created and how to use it.


📁 Files Created

Demo Session Service (New Microservice)

services/demo_session/
├── app/
│   ├── __init__.py
│   ├── main.py                          # FastAPI application
│   ├── api/
│   │   ├── __init__.py
│   │   ├── routes.py                    # API endpoints
│   │   └── schemas.py                   # Pydantic models
│   ├── core/
│   │   ├── __init__.py
│   │   ├── config.py                    # Settings
│   │   ├── database.py                  # Database manager
│   │   └── redis_client.py              # Redis client
│   ├── models/
│   │   ├── __init__.py
│   │   └── demo_session.py              # Session model
│   └── services/
│       ├── __init__.py
│       ├── session_manager.py           # Session lifecycle
│       ├── data_cloner.py               # Data cloning
│       └── cleanup_service.py           # Cleanup logic
├── migrations/
│   ├── env.py
│   ├── script.py.mako
│   └── versions/
├── requirements.txt
├── Dockerfile
└── alembic.ini

Demo Seeding Scripts

scripts/demo/
├── __init__.py
├── seed_demo_users.py                   # Creates demo users
├── seed_demo_tenants.py                 # Creates demo tenants
├── seed_demo_inventory.py               # Populates Spanish inventory (25 ingredients)
└── clone_demo_tenant.py                 # Clones data from template (runs as K8s Job)

Gateway Middleware

gateway/app/middleware/
└── demo_middleware.py                   # Demo session handling

Kubernetes Resources

infrastructure/kubernetes/base/
├── components/demo-session/
│   ├── deployment.yaml                  # Service deployment (with CLONE_JOB_IMAGE env)
│   ├── service.yaml                     # K8s service
│   ├── database.yaml                    # PostgreSQL DB
│   └── rbac.yaml                        # RBAC for job creation
├── migrations/
│   └── demo-session-migration-job.yaml  # Migration job
├── jobs/
│   ├── demo-seed-users-job.yaml         # User seeding
│   ├── demo-seed-tenants-job.yaml       # Tenant seeding
│   ├── demo-seed-inventory-job.yaml     # Inventory seeding
│   ├── demo-seed-rbac.yaml              # RBAC permissions for seed jobs
│   └── demo-clone-job-template.yaml     # Reference template for clone jobs
└── cronjobs/
    └── demo-cleanup-cronjob.yaml        # Hourly cleanup

Documentation

DEMO_ARCHITECTURE.md                     # Complete architecture guide
DEMO_IMPLEMENTATION_SUMMARY.md           # This file

Updated Files

services/tenant/app/models/tenants.py       # Added demo flags
services/demo_session/app/services/k8s_job_cloner.py  # K8s Job cloning implementation
gateway/app/main.py                         # Added demo middleware
gateway/app/middleware/demo_middleware.py   # Converted to BaseHTTPMiddleware
Tiltfile                                    # Added demo resources + CLONE_JOB_IMAGE patching
shared/config/base.py                       # Added demo-related settings

🎯 Key Features Implemented

1. Session Isolation

  • Each prospect gets isolated virtual tenant
  • No data interference between sessions
  • Automatic resource cleanup

2. Spanish Demo Data

  • Panadería San Pablo (Individual Bakery)

    • Raw ingredients: Harina, Levadura, Mantequilla, etc.
    • Local production focus
    • Full recipe management
  • Panadería La Espiga (Central Baker Satellite)

    • Pre-baked products from central baker
    • Supplier management
    • Order tracking

3. Redis Caching

  • Hot data cached for fast access
  • Automatic TTL (30 minutes)
  • Session metadata storage

4. Gateway Integration

  • Demo session detection
  • Operation restrictions
  • Virtual tenant injection

5. Automatic Cleanup

  • Hourly CronJob cleanup
  • Expired session detection
  • Database and Redis cleanup

6. K8s Job-based Data Cloning

  • Database-level cloning (faster than API calls)
  • Environment-based image configuration
  • Works in dev (Tilt dynamic tags) and production (stable tags)
  • Uses ORM models for safe data copying
  • imagePullPolicy: IfNotPresent for local images

7. AI & Scheduler Restrictions

  • Fake AI models in database (no real files)
  • Forecast API blocked at gateway for demo accounts
  • Procurement scheduler filters out demo tenants
  • Manual operations still allowed for realistic testing

🚀 Quick Start

Local Development with Tilt

# Start all services including demo system
tilt up

# Watch demo initialization
tilt logs demo-seed-users
tilt logs demo-seed-tenants
tilt logs demo-seed-inventory

# Check demo service
tilt logs demo-session-service

Test Demo Session Creation

# Get demo accounts info
curl http://localhost/api/demo/accounts | jq

# Create demo session
curl -X POST http://localhost/api/demo/session/create \
  -H "Content-Type: application/json" \
  -d '{
    "demo_account_type": "individual_bakery",
    "ip_address": "127.0.0.1"
  }' | jq

# Response:
# {
#   "session_id": "demo_abc123...",
#   "virtual_tenant_id": "uuid-here",
#   "expires_at": "2025-10-02T12:30:00Z",
#   "session_token": "eyJ..."
# }

Use Demo Session

# Make request with demo session
curl http://localhost/api/inventory/ingredients \
  -H "X-Demo-Session-Id: demo_abc123..." \
  -H "Content-Type: application/json"

# Try restricted operation (should fail)
curl -X DELETE http://localhost/api/inventory/ingredients/uuid \
  -H "X-Demo-Session-Id: demo_abc123..."

# Response:
# {
#   "error": "demo_restriction",
#   "message": "Esta operación no está permitida en cuentas demo..."
# }

📊 Demo Accounts

Account 1: Individual Bakery

Name: Panadería San Pablo - Demo
Email: demo.individual@panaderiasanpablo.com
Password: DemoSanPablo2024!
Business Model: individual_bakery
Location: Madrid, Spain

Features:
  - Production Management ✓
  - Recipe Management ✓
  - Inventory Tracking ✓
  - Demand Forecasting ✓
  - POS System ✓
  - Sales Analytics ✓

Data:
  - 20+ raw ingredients
  - 5+ finished products
  - Multiple stock lots
  - Production batches
  - Sales history

Account 2: Central Baker Satellite

Name: Panadería La Espiga - Demo
Email: demo.central@panaderialaespiga.com
Password: DemoLaEspiga2024!
Business Model: central_baker_satellite
Location: Barcelona, Spain

Features:
  - Supplier Management ✓
  - Inventory Tracking ✓
  - Order Management ✓
  - POS System ✓
  - Sales Analytics ✓
  - Demand Forecasting ✓

Data:
  - 15+ par-baked products
  - 10+ finished products
  - Supplier relationships
  - Delivery tracking
  - Sales history

🔧 Configuration

Session Settings

Edit services/demo_session/app/core/config.py:

DEMO_SESSION_DURATION_MINUTES = 30        # Session lifetime
DEMO_SESSION_MAX_EXTENSIONS = 3           # Max extensions allowed
REDIS_SESSION_TTL = 1800                  # Redis cache TTL (seconds)

Operation Restrictions

Edit gateway/app/middleware/demo_middleware.py:

DEMO_ALLOWED_OPERATIONS = {
    "GET": ["*"],
    "POST": [
        "/api/pos/sales",           # Allow sales
        "/api/orders",              # Allow orders
        "/api/inventory/adjustments" # Allow adjustments
    ],
    "DELETE": []  # Block all deletes
}

Cleanup Schedule

Edit infrastructure/kubernetes/base/cronjobs/demo-cleanup-cronjob.yaml:

spec:
  schedule: "0 * * * *"  # Every hour
  # Or:
  # schedule: "*/30 * * * *"  # Every 30 minutes
  # schedule: "0 */3 * * *"   # Every 3 hours

📈 Monitoring

Check Active Sessions

# Get statistics
curl http://localhost/api/demo/stats | jq

# Get specific session
curl http://localhost/api/demo/session/{session_id} | jq

View Logs

# Demo session service
kubectl logs -f deployment/demo-session-service -n bakery-ia

# Cleanup job
kubectl logs -l app=demo-cleanup -n bakery-ia --tail=100

# Seed jobs
kubectl logs job/demo-seed-inventory -n bakery-ia

Metrics

# Database queries
kubectl exec -it deployment/demo-session-service -n bakery-ia -- \
  psql $DEMO_SESSION_DATABASE_URL -c \
  "SELECT status, COUNT(*) FROM demo_sessions GROUP BY status;"

# Redis memory
kubectl exec -it deployment/redis -n bakery-ia -- \
  redis-cli INFO memory

🔄 Maintenance

Manual Cleanup

# Trigger cleanup manually
kubectl create job --from=cronjob/demo-session-cleanup \
  manual-cleanup-$(date +%s) -n bakery-ia

# Watch cleanup progress
kubectl logs -f job/manual-cleanup-xxxxx -n bakery-ia

Reseed Demo Data

# Delete and recreate seed jobs
kubectl delete job demo-seed-inventory -n bakery-ia
kubectl apply -f infrastructure/kubernetes/base/jobs/demo-seed-inventory-job.yaml

# Watch progress
kubectl logs -f job/demo-seed-inventory -n bakery-ia

Scale Demo Service

# Scale up for high load
kubectl scale deployment/demo-session-service --replicas=4 -n bakery-ia

# Scale down for maintenance
kubectl scale deployment/demo-session-service --replicas=1 -n bakery-ia

🛠 Troubleshooting

Sessions Not Creating

  1. Check demo-session-service health

    kubectl get pods -l app=demo-session-service -n bakery-ia
    kubectl logs deployment/demo-session-service -n bakery-ia --tail=50
    
  2. Verify base tenants exist

    kubectl exec -it deployment/tenant-service -n bakery-ia -- \
      psql $TENANT_DATABASE_URL -c \
      "SELECT id, name, is_demo_template FROM tenants WHERE is_demo = true;"
    
  3. Check Redis connection

    kubectl exec -it deployment/demo-session-service -n bakery-ia -- \
      python -c "import redis; r=redis.Redis(host='redis-service'); print(r.ping())"
    

Sessions Not Cleaning Up

  1. Check CronJob status

    kubectl get cronjobs -n bakery-ia
    kubectl get jobs -l app=demo-cleanup -n bakery-ia
    
  2. Manually trigger cleanup

    curl -X POST http://localhost/api/demo/cleanup/run
    
  3. Check for stuck sessions

    kubectl exec -it deployment/demo-session-service -n bakery-ia -- \
      psql $DEMO_SESSION_DATABASE_URL -c \
      "SELECT session_id, status, expires_at FROM demo_sessions WHERE status = 'active';"
    

Gateway Not Injecting Virtual Tenant

  1. Check middleware is loaded

    kubectl logs deployment/gateway -n bakery-ia | grep -i demo
    
  2. Verify session ID in request

    curl -v http://localhost/api/inventory/ingredients \
      -H "X-Demo-Session-Id: your-session-id"
    
  3. Check demo middleware logic


🎉 Success Criteria

Demo session creates successfully

  • Session ID returned
  • Virtual tenant ID generated
  • Expiration time set

Data is isolated

  • Multiple sessions don't interfere
  • Each session has unique tenant ID

Spanish demo data loads

  • Ingredients in Spanish
  • Realistic bakery scenarios
  • Both business models represented

Operations restricted

  • Read operations allowed
  • Write operations limited
  • Delete operations blocked

Automatic cleanup works

  • Sessions expire after 30 minutes
  • CronJob removes expired sessions
  • Redis keys cleaned up

Gateway integration works

  • Middleware detects sessions
  • Virtual tenant injected
  • Restrictions enforced

K8s Job cloning works

  • Dynamic image detection in Tilt (dev)
  • Environment variable configuration
  • Automatic data cloning per session
  • No service-specific clone endpoints needed

AI & Scheduler protection works

  • Forecast API blocked for demo accounts
  • Scheduler filters demo tenants
  • Fake models in database only

📚 Next Steps

For Frontend Integration

  1. Create demo login page showing both accounts
  2. Implement session token storage (cookie/localStorage)
  3. Add session timer UI component
  4. Show "DEMO MODE" badge in header
  5. Display session expiration warnings

For Marketing

  1. Publish demo credentials on website
  2. Create demo walkthrough videos
  3. Add "Probar Demo" CTA buttons
  4. Track demo → signup conversion

For Operations

  1. Set up monitoring dashboards
  2. Configure alerts for cleanup failures
  3. Track session metrics (duration, usage)
  4. Optimize Redis cache strategy

📞 Support

For issues or questions:

  • Review DEMO_ARCHITECTURE.md for detailed documentation
  • Check logs: tilt logs demo-session-service
  • Inspect database: psql $DEMO_SESSION_DATABASE_URL

🔧 Technical Architecture Decisions

Data Cloning: Why Kubernetes Jobs?

Problem: Need to clone demo data from base template tenants to virtual tenants for each session.

Options Considered:

  1. Service-based clone endpoints - Would require /internal/demo/clone in every service
  2. PostgreSQL Foreign Data Wrapper - Complex setup, doesn't work across databases
  3. Kubernetes Jobs - Selected approach

Why K8s Jobs Won:

  • Database-level operations (ORM-based, faster than API calls)
  • Scalable (one job per session, isolated execution)
  • No service coupling (don't need clone endpoints in every service)
  • Works in all environments (dev & production)

Image Configuration: Environment Variables

Problem: K8s Jobs need container images, but Tilt uses dynamic tags (e.g., tilt-abc123) while production uses stable tags.

Solution: Environment variable CLONE_JOB_IMAGE

# Demo-session deployment has default
env:
- name: CLONE_JOB_IMAGE
  value: "bakery/inventory-service:latest"

# Tilt patches it dynamically
# Tiltfile line 231-237
inventory_image_ref = kubectl get deployment inventory-service ...
kubectl set env deployment/demo-session-service CLONE_JOB_IMAGE=$inventory_image_ref

Benefits:

  • General solution (not tied to specific service)
  • Works in dev (dynamic Tilt tags)
  • Works in production (stable release tags)
  • Easy to change image via env var

Middleware: BaseHTTPMiddleware Pattern

Problem: Initial function-based middleware using @app.middleware("http") wasn't executing.

Solution: Converted to class-based BaseHTTPMiddleware

class DemoMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        # ... middleware logic

Why: FastAPI's BaseHTTPMiddleware provides better lifecycle hooks and guaranteed execution order.


Implementation Date: 2025-10-02 Last Updated: 2025-10-03 Status: Complete - Ready for Production Next: Frontend integration and end-to-end testing