Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions .env.prod.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# TaskFlow Production Environment (Managed Services)
# Copy to .env.prod and fill in your values
# Usage: ./scripts/deploy-prod.sh

# =============================================================================
# NEON POSTGRESQL (Required)
# =============================================================================
# Create 4 databases in Neon Console: https://console.neon.tech/
#
# Steps:
# 1. Create a Neon project
# 2. Create 4 databases: sso_db, taskflow_db, chatkit_db, notification_db
# 3. Copy the connection strings below
#
# Architecture:
# - sso_db: Auth (users, sessions) - consumed by SSO Platform
# - taskflow_db: Core business (tasks, projects, workers) - consumed by API, MCP
# - chatkit_db: Chat (threads, messages) - consumed by API ChatKit routes
# - notification_db: Notifications - consumed by Notification Service

# SSO Database (Better Auth)
NEON_SSO_DATABASE_URL=postgresql://neondb_owner:xxx@ep-xxx.us-east-1.aws.neon.tech/sso_db?sslmode=require

# API Database (Tasks, Projects, Workers, Audit)
NEON_API_DATABASE_URL=postgresql://neondb_owner:xxx@ep-xxx.us-east-1.aws.neon.tech/taskflow_db?sslmode=require

# ChatKit Database (Chat threads, messages)
NEON_CHATKIT_DATABASE_URL=postgresql://neondb_owner:xxx@ep-xxx.us-east-1.aws.neon.tech/chatkit_db?sslmode=require

# Notification Database (Notification Service)
NEON_NOTIFICATION_DATABASE_URL=postgresql://neondb_owner:xxx@ep-xxx.us-east-1.aws.neon.tech/notification_db?sslmode=require

# =============================================================================
# UPSTASH REDIS (Required)
# =============================================================================
# Create ONE Redis database: https://console.upstash.com/
# You'll use it for both Dapr pub/sub AND SSO rate limiting
#
# From Upstash Console, copy these values:

# --- For Dapr Pub/Sub (standard Redis protocol) ---
# Found under "Connect" > "Redis" tab
UPSTASH_REDIS_HOST=your-redis-xxx.upstash.io:6379
UPSTASH_REDIS_PASSWORD=your-upstash-password

# --- For SSO Rate Limiting (Upstash REST API) ---
# Found under "Connect" > "REST API" tab
REDIS_URL=https://your-redis-xxx.upstash.io
REDIS_TOKEN=AXxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# =============================================================================
# APPLICATION SECRETS (Required)
# =============================================================================

# Better Auth secret for JWT signing (SSO uses this to sign JWTs)
# Generate with: openssl rand -hex 32
BETTER_AUTH_SECRET=your-32-char-secret-here

# =============================================================================
# OPENAI (Required for AI features)
# =============================================================================

# OpenAI API key (for ChatKit AI responses)
# Get from: https://platform.openai.com/api-keys
OPENAI_API_KEY=sk-proj-xxx

# ChatKit domain key (for frontend authentication)
# Use default for local dev, generate unique for production
NEXT_PUBLIC_CHATKIT_DOMAIN_KEY=domain_pk_local_dev

# =============================================================================
# SMTP EMAIL (Optional - for email verification)
# =============================================================================
# Required if you want email verification in SSO
# Works with Gmail, SendGrid, Mailgun, etc.

# Gmail SMTP (use App Password, not regular password)
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USER=your-email@gmail.com
# SMTP_PASS=your-app-password
# SMTP_SECURE=false
# EMAIL_FROM=no-reply@yourdomain.com

# SendGrid SMTP
# SMTP_HOST=smtp.sendgrid.net
# SMTP_PORT=587
# SMTP_USER=apikey
# SMTP_PASS=your-sendgrid-api-key
# SMTP_SECURE=false
# EMAIL_FROM=no-reply@yourdomain.com

# Leave empty to disable email features
SMTP_PASS=

# =============================================================================
# PRODUCTION URLS (Optional - for custom domains)
# =============================================================================
# Uncomment and set these if deploying to a real domain

# BETTER_AUTH_URL=https://sso.yourdomain.com
# ALLOWED_ORIGINS=https://yourdomain.com,https://sso.yourdomain.com
# CORS_ORIGINS=https://yourdomain.com,https://sso.yourdomain.com
# NEXT_PUBLIC_API_URL=https://api.yourdomain.com
# NEXT_PUBLIC_SSO_URL=https://sso.yourdomain.com

# =============================================================================
# QUICK START
# =============================================================================
#
# 1. Copy this file:
# cp .env.prod.example .env.prod
#
# 2. Create Neon databases:
# - Go to https://console.neon.tech/
# - Create project, then 4 databases (sso_db, taskflow_db, chatkit_db, notification_db)
# - Copy connection strings
#
# 3. Create Upstash Redis:
# - Go to https://console.upstash.com/
# - Create Redis database
# - Copy host and password
#
# 4. Generate secrets:
# openssl rand -hex 32 # Run twice for BETTER_AUTH_SECRET and JWT_SECRET
#
# 5. Get OpenAI key:
# - Go to https://platform.openai.com/api-keys
#
# 6. Deploy:
# ./scripts/deploy-prod.sh --port-forward
#
# =============================================================================
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
.env.development.local
.env.test.local
.env.production.local
.env.prod

npm-debug.log*
yarn-debug.log*
Expand Down
232 changes: 232 additions & 0 deletions docs/dapr-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# Dapr Setup Guide for TaskFlow

This guide covers setting up Dapr for TaskFlow on Minikube/Kubernetes.

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────────────────┐
│ KUBERNETES CLUSTER │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ DAPR CONTROL PLANE │ │
│ │ (dapr-system namespace) │ │
│ │ - dapr-operator - dapr-sentry │ │
│ │ - dapr-placement - dapr-sidecar-injector │ │
│ │ - dapr-scheduler (3x) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ TaskFlow API Pod │ │ Notification Svc │ │
│ │ ┌───────┐ ┌──────┐ │ │ ┌───────┐ ┌──────┐ │ │
│ │ │ API │ │ Dapr │ │ │ │ Notif │ │ Dapr │ │ │
│ │ │ │◀┼▶Sidecar│─────▶│ │◀┼▶Sidecar│ │ │
│ │ │ :8000 │ │ :3500│ │ │ │ :8001 │ │ :3500│ │ │
│ │ └───────┘ └──────┘ │ │ └───────┘ └──────┘ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ ▲ │
│ │ Dapr Pub/Sub │ │
│ └───────────┬───────────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Redis │ (local) or Kafka (production) │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```

## Prerequisites

- Minikube installed and running
- kubectl configured
- Helm 3.x installed

## Step 1: Start Minikube

```bash
# Start minikube with enough resources
minikube start --cpus=4 --memory=8192

# Verify
kubectl cluster-info
```

## Step 2: Install Dapr on Kubernetes via Helm

```bash
# Add Dapr Helm repo
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update

# Install Dapr control plane (v1.15 for stability)
helm upgrade --install dapr dapr/dapr \
--version=1.15 \
--namespace dapr-system \
--create-namespace \
--wait

# Verify installation (all pods should be Running 1/1)
kubectl get pods -n dapr-system
```

Expected output:
```
NAME READY STATUS RESTARTS AGE
dapr-operator-xxx 1/1 Running 0 1m
dapr-placement-server-0 1/1 Running 0 1m
dapr-scheduler-server-0 1/1 Running 0 1m
dapr-scheduler-server-1 1/1 Running 0 1m
dapr-scheduler-server-2 1/1 Running 0 1m
dapr-sentry-xxx 1/1 Running 0 1m
dapr-sidecar-injector-xxx 1/1 Running 0 1m
```

## Step 3: Install Dapr Dashboard (Optional)

```bash
helm install dapr-dashboard dapr/dapr-dashboard --namespace dapr-system

# Access dashboard
kubectl port-forward service/dapr-dashboard 8080:8080 -n dapr-system
# Open http://localhost:8080
```

## Step 4: Deploy TaskFlow with Dapr

```bash
cd helm/taskflow

# Install TaskFlow (includes Redis, Dapr components)
helm upgrade --install taskflow . \
--namespace taskflow \
--create-namespace \
--set dapr.enabled=true \
--wait

# Verify pods have 2/2 containers (app + Dapr sidecar)
kubectl get pods -n taskflow
```

Expected output:
```
NAME READY STATUS RESTARTS AGE
taskflow-api-xxx 2/2 Running 0 1m
notification-service-xxx 2/2 Running 0 1m
redis-xxx 1/1 Running 0 1m
...
```

## Step 5: Verify Dapr Components

```bash
# List Dapr components
kubectl get components -n taskflow

# Should show:
# taskflow-pubsub pubsub.redis
# taskflow-scheduler scheduler.cron
```

## Step 6: Test Pub/Sub Flow

```bash
# Port forward the API
kubectl port-forward svc/taskflow-api 8000:8000 -n taskflow &

# Create a task with due_date (triggers reminder scheduling)
curl -X POST http://localhost:8000/api/projects/1/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"title": "Test Dapr Integration",
"due_date": "2025-12-12T10:00:00Z",
"is_recurring": true,
"recurrence_pattern": "daily",
"recurrence_trigger": "on_due_date"
}'

# Check Dapr sidecar logs for pub/sub activity
kubectl logs -l app.kubernetes.io/component=api -c daprd -n taskflow --tail=50
```

## Step 7: Test Job Scheduling

The API schedules Dapr Jobs for:
1. **Recurring task spawn** - at exact `due_date`
2. **Reminders** - 24 hours before `due_date`

Check scheduled jobs:
```bash
# Check API logs for job scheduling
kubectl logs -l app.kubernetes.io/component=api -c api -n taskflow | grep DAPR-JOB
```

## Troubleshooting

### Pods stuck at 1/2 Ready
Dapr sidecar not injecting. Check:
```bash
# Verify Dapr is installed
kubectl get pods -n dapr-system

# Check sidecar injector logs
kubectl logs -l app=dapr-sidecar-injector -n dapr-system
```

### Pub/Sub not working
```bash
# Check component is loaded
kubectl get components -n taskflow

# Check Dapr logs
kubectl logs <pod-name> -c daprd -n taskflow
```

### Jobs not firing
```bash
# Check scheduler pods
kubectl get pods -n dapr-system | grep scheduler

# Check scheduler logs
kubectl logs -l app=dapr-scheduler-server -n dapr-system
```

## Production: Switch to Kafka

For production (Redpanda Cloud/Kafka):

```yaml
# values-production.yaml
dapr:
enabled: true
pubsub:
name: taskflow-pubsub
type: pubsub.kafka
brokers: "your-kafka-broker:9092"
consumerGroup: taskflow-group
authType: password
secretName: kafka-credentials
```

Then:
```bash
# Create Kafka credentials secret
kubectl create secret generic kafka-credentials \
--from-literal=username=your-username \
--from-literal=password=your-password \
-n taskflow

# Deploy with production values
helm upgrade --install taskflow . \
-f values-production.yaml \
--namespace taskflow
```

## Architecture Benefits

| Without Dapr | With Dapr |
|-------------|-----------|
| `pip install kafka-python` | HTTP to sidecar |
| Manual connection management | Automatic retries |
| Cron polling every 60s | Exact-time Jobs API |
| Hardcoded broker config | YAML component swap |
| Tight service coupling | Event-driven decoupling |
Loading
Loading