Improve the frontend and fix TODOs

This commit is contained in:
Urtzi Alfaro
2025-10-24 13:05:04 +02:00
parent 07c33fa578
commit 61376b7a9f
100 changed files with 8284 additions and 3419 deletions

211
Tiltfile
View File

@@ -1,6 +1,41 @@
# Tiltfile for Bakery IA - Local Development
# This replaces Skaffold for faster, smarter local Kubernetes development
# Tiltfile for Bakery IA - Secure Local Development
# Includes TLS encryption, strong passwords, PVCs, and audit logging
# =============================================================================
# SECURITY SETUP
# =============================================================================
print("""
======================================
🔐 Bakery IA Secure Development Mode
======================================
Security Features:
✅ TLS encryption for PostgreSQL and Redis
✅ Strong 32-character passwords
✅ PersistentVolumeClaims (no data loss)
✅ pgcrypto extension for encryption
✅ PostgreSQL audit logging
Applying security configurations...
""")
# Apply security configurations before loading main manifests
local_resource('security-setup',
cmd='''
echo "📦 Applying security secrets and configurations..."
kubectl apply -f infrastructure/kubernetes/base/secrets.yaml
kubectl apply -f infrastructure/kubernetes/base/secrets/postgres-tls-secret.yaml
kubectl apply -f infrastructure/kubernetes/base/secrets/redis-tls-secret.yaml
kubectl apply -f infrastructure/kubernetes/base/configs/postgres-init-config.yaml
kubectl apply -f infrastructure/kubernetes/base/configmaps/postgres-logging-config.yaml
echo "✅ Security configurations applied"
''',
labels=['security'],
auto_init=True)
# =============================================================================
# LOAD KUBERNETES MANIFESTS
# =============================================================================
# Load Kubernetes manifests using Kustomize
k8s_yaml(kustomize('infrastructure/kubernetes/overlays/dev'))
@@ -74,7 +109,7 @@ def build_python_service(service_name, service_path):
# Sync service code
sync('./services/' + service_path, '/app'),
# Sync shared libraries
# Sync shared libraries (includes updated TLS connection code)
sync('./shared', '/app/shared'),
# Sync scripts
@@ -123,25 +158,73 @@ build_python_service('demo-session-service', 'demo_session')
# RESOURCE DEPENDENCIES & ORDERING
# =============================================================================
# Databases and infrastructure should start first
k8s_resource('auth-db', labels=['databases'])
k8s_resource('tenant-db', labels=['databases'])
k8s_resource('training-db', labels=['databases'])
k8s_resource('forecasting-db', labels=['databases'])
k8s_resource('sales-db', labels=['databases'])
k8s_resource('external-db', labels=['databases'])
k8s_resource('notification-db', labels=['databases'])
k8s_resource('inventory-db', labels=['databases'])
k8s_resource('recipes-db', labels=['databases'])
k8s_resource('suppliers-db', labels=['databases'])
k8s_resource('pos-db', labels=['databases'])
k8s_resource('orders-db', labels=['databases'])
k8s_resource('production-db', labels=['databases'])
k8s_resource('demo-session-db', labels=['databases'])
# Security setup must complete before databases start
k8s_resource('auth-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('tenant-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('training-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('forecasting-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('sales-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('external-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('notification-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('inventory-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('recipes-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('suppliers-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('pos-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('orders-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('production-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('alert-processor-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('demo-session-db', resource_deps=['security-setup'], labels=['databases'])
k8s_resource('redis', labels=['infrastructure'])
k8s_resource('redis', resource_deps=['security-setup'], labels=['infrastructure'])
k8s_resource('rabbitmq', labels=['infrastructure'])
# Verify TLS certificates are mounted correctly
local_resource('verify-tls',
cmd='''
echo "🔍 Verifying TLS configuration..."
sleep 5 # Wait for pods to be ready
# Check if auth-db pod exists and has TLS certs
AUTH_POD=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/name=auth-db -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
if [ -n "$AUTH_POD" ]; then
echo " Checking PostgreSQL TLS certificates..."
kubectl exec -n bakery-ia "$AUTH_POD" -- ls -la /tls/ 2>/dev/null && \
echo " ✅ PostgreSQL TLS certificates mounted" || \
echo " ⚠️ PostgreSQL TLS certificates not found (pods may still be starting)"
fi
# Check if redis pod exists and has TLS certs
REDIS_POD=$(kubectl get pods -n bakery-ia -l app.kubernetes.io/name=redis -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
if [ -n "$REDIS_POD" ]; then
echo " Checking Redis TLS certificates..."
kubectl exec -n bakery-ia "$REDIS_POD" -- ls -la /tls/ 2>/dev/null && \
echo " ✅ Redis TLS certificates mounted" || \
echo " ⚠️ Redis TLS certificates not found (pods may still be starting)"
fi
echo "✅ TLS verification complete"
''',
resource_deps=['auth-db', 'redis'],
auto_init=True,
trigger_mode=TRIGGER_MODE_MANUAL,
labels=['security'])
# Verify PVCs are bound
local_resource('verify-pvcs',
cmd='''
echo "🔍 Verifying PersistentVolumeClaims..."
kubectl get pvc -n bakery-ia | grep -E "NAME|db-pvc" || echo " ⚠️ PVCs not yet bound"
PVC_COUNT=$(kubectl get pvc -n bakery-ia -o json | jq '.items | length')
echo " Found $PVC_COUNT PVCs"
echo "✅ PVC verification complete"
''',
resource_deps=['auth-db'],
auto_init=True,
trigger_mode=TRIGGER_MODE_MANUAL,
labels=['security'])
# Nominatim geocoding service (excluded in dev via kustomize patches)
# Uncomment these if you want to test nominatim locally
# k8s_resource('nominatim',
@@ -178,33 +261,10 @@ k8s_resource('production-migration', resource_deps=['production-db'], labels=['m
k8s_resource('alert-processor-migration', resource_deps=['alert-processor-db'], labels=['migrations'])
k8s_resource('demo-session-migration', resource_deps=['demo-session-db'], labels=['migrations'])
# Alert processor DB
k8s_resource('alert-processor-db', labels=['databases'])
# =============================================================================
# DEMO INITIALIZATION JOBS
# =============================================================================
# Demo seed jobs run in strict order to ensure data consistency across services:
#
# Helm Hook Weight Order (5-40):
# Weight 5: demo-seed-users → Creates demo user accounts (with staff) in auth service
# Weight 10: demo-seed-tenants → Creates demo tenant records (depends on users)
# Weight 15: demo-seed-tenant-members → Links staff users to tenants (depends on users & tenants)
# Weight 10: demo-seed-subscriptions → Creates enterprise subscriptions for demo tenants
# Weight 15: demo-seed-inventory → Creates ingredients & finished products (depends on tenants)
# Weight 15: demo-seed-recipes → Creates recipes using ingredient IDs (depends on inventory)
# Weight 15: demo-seed-suppliers → Creates suppliers with price lists for ingredients (depends on inventory)
# Weight 21: demo-seed-purchase-orders → Creates demo POs in various states (depends on suppliers)
# Weight 15: demo-seed-sales → Creates historical sales data using finished product IDs (depends on inventory)
# Weight 15: demo-seed-ai-models → Creates fake AI model entries (depends on inventory)
# Weight 20: demo-seed-stock → Creates stock batches with expiration dates (depends on inventory)
# Weight 22: demo-seed-quality-templates → Creates quality check templates (depends on production migration)
# Weight 25: demo-seed-customers → Creates customer records (depends on orders migration)
# Weight 25: demo-seed-equipment → Creates production equipment (depends on production migration)
# Weight 30: demo-seed-production-batches → Creates production batches (depends on recipes, equipment)
# Weight 30: demo-seed-orders → Creates orders with line items (depends on customers)
# Weight 35: demo-seed-procurement → Creates procurement plans (depends on orders migration)
# Weight 40: demo-seed-forecasts → Creates demand forecasts (depends on forecasting migration)
# Demo seed jobs run in strict order to ensure data consistency across services
# Weight 5: Seed users (auth service) - includes staff users
k8s_resource('demo-seed-users',
@@ -246,11 +306,6 @@ k8s_resource('demo-seed-suppliers',
resource_deps=['suppliers-migration', 'demo-seed-inventory'],
labels=['demo-init'])
# Weight 21: Seed purchase orders (uses suppliers and demonstrates auto-approval workflow)
k8s_resource('demo-seed-purchase-orders',
resource_deps=['suppliers-migration', 'demo-seed-suppliers'],
labels=['demo-init'])
# Weight 15: Seed sales (uses finished product IDs from inventory)
k8s_resource('demo-seed-sales',
resource_deps=['sales-migration', 'demo-seed-inventory'],
@@ -296,11 +351,6 @@ k8s_resource('demo-seed-procurement',
resource_deps=['orders-migration', 'demo-seed-tenants'],
labels=['demo-init'])
# Weight 35: Seed POS configurations (pos service)
k8s_resource('demo-seed-pos-configs',
resource_deps=['pos-migration', 'demo-seed-tenants'],
labels=['demo-init'])
# Weight 40: Seed demand forecasts (forecasting service)
k8s_resource('demo-seed-forecasts',
resource_deps=['forecasting-migration', 'demo-seed-tenants'],
@@ -367,17 +417,11 @@ k8s_resource('alert-processor-service',
resource_deps=['alert-processor-migration', 'redis', 'rabbitmq'],
labels=['services'])
k8s_resource('alert-processor-api',
resource_deps=['alert-processor-migration', 'redis'],
labels=['services'])
k8s_resource('demo-session-service',
resource_deps=['demo-session-migration', 'redis'],
labels=['services'])
# Apply environment variable patch to demo-session-service with the inventory image
# Note: This fetches the CURRENT image tag dynamically when the resource runs
# Runs after both services are deployed to ensure correct image tag is used
local_resource('patch-demo-session-env',
cmd='''
# Wait a moment for deployments to stabilize
@@ -391,16 +435,13 @@ local_resource('patch-demo-session-env',
echo "✅ Set CLONE_JOB_IMAGE to: $INVENTORY_IMAGE"
''',
resource_deps=['demo-session-service', 'inventory-service'], # Wait for BOTH services
auto_init=True, # Run automatically on Tilt startup
resource_deps=['demo-session-service', 'inventory-service'],
auto_init=True,
labels=['config'])
# =============================================================================
# DATA INITIALIZATION JOBS (External Service v2.0)
# =============================================================================
# External data initialization job loads 24 months of historical data
# This should run AFTER external migration but BEFORE external-service starts
k8s_resource('external-data-init',
resource_deps=['external-migration', 'redis'],
labels=['data-init'])
@@ -408,12 +449,10 @@ k8s_resource('external-data-init',
# =============================================================================
# CRONJOBS
# =============================================================================
k8s_resource('demo-session-cleanup',
resource_deps=['demo-session-service'],
labels=['cronjobs'])
# External data rotation cronjob (runs monthly on 1st at 2am UTC)
k8s_resource('external-data-rotation',
resource_deps=['external-service'],
labels=['cronjobs'])
@@ -421,9 +460,6 @@ k8s_resource('external-data-rotation',
# =============================================================================
# GATEWAY & FRONTEND
# =============================================================================
# Gateway and Frontend depend on services being ready
# Access via ingress: http://localhost (frontend) and http://localhost/api (gateway)
k8s_resource('gateway',
resource_deps=['auth-service'],
labels=['frontend'])
@@ -463,14 +499,43 @@ watch_settings(
'**/.coverage',
'**/dist/**',
'**/build/**',
'**/*.egg-info/**'
'**/*.egg-info/**',
# Ignore TLS certificate files (don't trigger rebuilds)
'**/infrastructure/tls/**/*.pem',
'**/infrastructure/tls/**/*.cnf',
'**/infrastructure/tls/**/*.csr',
'**/infrastructure/tls/**/*.srl',
]
)
# Print security status on startup
print("""
✅ Security setup complete!
Database Security Features Active:
🔐 TLS encryption: PostgreSQL and Redis
🔑 Strong passwords: 32-character cryptographic
💾 Persistent storage: PVCs for all databases
🔒 Column encryption: pgcrypto extension
📋 Audit logging: PostgreSQL query logging
Access your application:
Frontend: http://localhost:3000 (or via ingress)
Gateway: http://localhost:8000 (or via ingress)
Verify security:
kubectl get pvc -n bakery-ia
kubectl get secrets -n bakery-ia | grep tls
kubectl logs -n bakery-ia <db-pod> | grep SSL
Security documentation:
docs/SECURITY_IMPLEMENTATION_COMPLETE.md
docs/DATABASE_SECURITY_ANALYSIS_REPORT.md
======================================
""")
# Optimize for local development
# - Automatically stream logs from services with errors
# - Group resources by labels for better organization
#
# Note: You may see "too many open files" warnings on macOS with many services.
# This is a Kind/Kubernetes limitation and doesn't affect service functionality.
# To work on specific services only, use: tilt up <service-name> <service-name>