Improves security by preventing accidental commit of sensitive credentials to the repository. The .env file contains Langfuse API keys, database passwords, and encryption keys that should never be exposed in version control. ## Security Improvements **Added .env to .gitignore:** - Prevents .env file with real secrets from being committed - Protects Langfuse API keys (public/secret) - Protects database credentials - Protects NextAuth secrets and encryption keys **Created .env.example template:** - Safe template file for new developers to copy - Contains all required environment variables with placeholder values - Includes helpful comments for key generation (openssl commands) - Documents all configuration options **Updated Claude settings:** - Added git restore to allowed commands for workflow automation ## Setup Instructions for New Developers 1. Copy .env.example to .env: `cp .env.example .env` 2. Generate random secrets: - `openssl rand -base64 32` for NEXTAUTH_SECRET and SALT - `openssl rand -hex 32` for ENCRYPTION_KEY 3. Start Docker: `docker compose up -d` 4. Open Langfuse UI: http://localhost:3000 5. Create account, project, and copy API keys to .env 6. Restart API: `docker compose restart api` ## Files Changed - .gitignore: Added .env to ignore list - .env.example: New template file with placeholder values - .claude/settings.local.json: Added git restore to allowed commands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
78 lines
14 KiB
JSON
78 lines
14 KiB
JSON
{
|
|
"permissions": {
|
|
"allow": [
|
|
"Bash(dotnet clean:*)",
|
|
"Bash(dotnet run)",
|
|
"Bash(dotnet add:*)",
|
|
"Bash(timeout 5 dotnet run:*)",
|
|
"Bash(dotnet remove:*)",
|
|
"Bash(netstat:*)",
|
|
"Bash(findstr:*)",
|
|
"Bash(cat:*)",
|
|
"Bash(taskkill:*)",
|
|
"WebSearch",
|
|
"Bash(dotnet tool install:*)",
|
|
"Bash(protogen:*)",
|
|
"Bash(timeout 15 dotnet run:*)",
|
|
"Bash(where:*)",
|
|
"Bash(timeout 30 dotnet run:*)",
|
|
"Bash(timeout 60 dotnet run:*)",
|
|
"Bash(timeout 120 dotnet run:*)",
|
|
"Bash(git add:*)",
|
|
"Bash(curl:*)",
|
|
"Bash(timeout 3 cmd:*)",
|
|
"Bash(timeout:*)",
|
|
"Bash(tasklist:*)",
|
|
"Bash(dotnet build:*)",
|
|
"Bash(dotnet --list-sdks:*)",
|
|
"Bash(dotnet sln:*)",
|
|
"Bash(pkill:*)",
|
|
"Bash(python3:*)",
|
|
"Bash(grpcurl:*)",
|
|
"Bash(lsof:*)",
|
|
"Bash(xargs kill -9)",
|
|
"Bash(dotnet run:*)",
|
|
"Bash(find:*)",
|
|
"Bash(dotnet pack:*)",
|
|
"Bash(unzip:*)",
|
|
"WebFetch(domain:andrewlock.net)",
|
|
"WebFetch(domain:github.com)",
|
|
"WebFetch(domain:stackoverflow.com)",
|
|
"WebFetch(domain:www.kenmuse.com)",
|
|
"WebFetch(domain:blog.rsuter.com)",
|
|
"WebFetch(domain:natemcmaster.com)",
|
|
"WebFetch(domain:www.nuget.org)",
|
|
"Bash(tree:*)",
|
|
"Bash(arch -x86_64 dotnet build:*)",
|
|
"Bash(brew install:*)",
|
|
"Bash(brew search:*)",
|
|
"Bash(ln:*)",
|
|
"Bash(ollama pull:*)",
|
|
"Bash(brew services start:*)",
|
|
"Bash(jq:*)",
|
|
"Bash(for:*)",
|
|
"Bash(do curl -s http://localhost:11434/api/tags)",
|
|
"Bash(time curl -X POST http://localhost:6001/api/command/executeAgent )",
|
|
"Bash(time curl -X POST http://localhost:6001/api/command/executeAgent -H \"Content-Type: application/json\" -d '{\"\"\"\"prompt\"\"\"\":\"\"\"\"What is 5 + 3?\"\"\"\"}')",
|
|
"Bash(time curl -s -X POST http://localhost:6001/api/command/executeAgent -H \"Content-Type: application/json\" -d '{\"\"\"\"prompt\"\"\"\":\"\"\"\"What is (5 + 3) multiplied by 2?\"\"\"\"}')",
|
|
"Bash(git push:*)",
|
|
"Bash(dotnet ef migrations add:*)",
|
|
"Bash(export PATH=\"$PATH:/Users/jean-philippebrule/.dotnet/tools\")",
|
|
"Bash(dotnet tool uninstall:*)",
|
|
"Bash(/Users/jean-philippebrule/.dotnet/tools/dotnet-ef migrations add InitialCreate --context AgentDbContext --output-dir Data/Migrations)",
|
|
"Bash(dotnet --info:*)",
|
|
"Bash(export DOTNET_ROOT=/Users/jean-philippebrule/.dotnet)",
|
|
"Bash(dotnet-ef migrations add:*)",
|
|
"Bash(docker compose:*)",
|
|
"Bash(git commit -m \"$(cat <<''EOF''\nAdd complete production deployment infrastructure with full observability\n\nTransforms the AI agent from a proof-of-concept into a production-ready, fully observable \nsystem with Docker deployment, PostgreSQL persistence, OpenTelemetry tracing, Prometheus \nmetrics, and rate limiting. Ready for immediate production deployment.\n\n## Infrastructure & Deployment (New)\n\n**Docker Multi-Container Architecture:**\n- docker-compose.yml: 4-service stack (API, PostgreSQL, Ollama, Langfuse)\n- Dockerfile: Multi-stage build (SDK for build, runtime for production)\n- .dockerignore: Optimized build context (excludes 50+ unnecessary files)\n- .env: Environment configuration with auto-generated secrets\n- docker/configs/init-db.sql: PostgreSQL initialization with 2 databases + seed data\n- scripts/deploy.sh: One-command deployment with health validation\n\n**Network Architecture:**\n- API: Ports 6000 (gRPC/HTTP2) and 6001 (HTTP/1.1)\n- PostgreSQL: Port 5432 with persistent volumes\n- Ollama: Port 11434 with model storage\n- Langfuse: Port 3000 with observability UI\n\n## Database Integration (New)\n\n**Entity Framework Core + PostgreSQL:**\n- AgentDbContext: Full EF Core context with 3 entities\n- Entities/Conversation: JSONB storage for AI conversation history\n- Entities/Revenue: Monthly revenue data (17 months seeded: 2024-2025)\n- Entities/Customer: Customer database (15 records with state/tier)\n- Migrations: InitialCreate migration with complete schema\n- Auto-migration on startup with error handling\n\n**Database Schema:**\n- agent.conversations: UUID primary key, JSONB messages, timestamps with indexes\n- agent.revenue: Serial ID, month/year unique index, decimal amounts\n- agent.customers: Serial ID, state/tier indexes for query performance\n- Seed data: $2.9M total revenue, 15 enterprise/professional/starter tier customers\n\n**DatabaseQueryTool Rewrite:**\n- Changed from in-memory simulation to real PostgreSQL queries\n- All 5 methods now use async Entity Framework Core\n- GetMonthlyRevenue: Queries actual revenue table with year ordering\n- GetRevenueRange: Aggregates multiple months with proper filtering\n- CountCustomersByState/Tier: Real customer counts from database\n- GetCustomers: Filtered queries with Take(10) pagination\n\n## Observability (New)\n\n**OpenTelemetry Integration:**\n- Full distributed tracing with Langfuse OTLP exporter\n- ActivitySource: \"Svrnty.AI.Agent\" and \"Svrnty.AI.Ollama\"\n- Basic Auth to Langfuse with environment-based configuration\n- Conditional tracing (only when Langfuse keys configured)\n\n**Instrumented Components:**\n\nExecuteAgentCommandHandler:\n- agent.execute (root span): Full conversation lifecycle\n - Tags: conversation_id, prompt, model, success, iterations, response_preview\n- tools.register: Tool initialization with count and names\n- llm.completion: Each LLM call with iteration number\n- function.{name}: Each tool invocation with arguments, results, success/error\n- Database persistence span for conversation storage\n\nOllamaClient:\n- ollama.chat: HTTP client span with model and message count\n- Tags: latency_ms, estimated_tokens, has_function_calls, has_tools\n- Timing: Tracks start to completion for performance monitoring\n\n**Span Hierarchy Example:**\n```\nagent.execute (2.4s)\n├── tools.register (12ms) [tools.count=7]\n├── llm.completion (1.2s) [iteration=0]\n├── function.Add (8ms) [arguments={a:5,b:3}, result=8]\n└── llm.completion (1.1s) [iteration=1]\n```\n\n**Prometheus Metrics (New):**\n- /metrics endpoint for Prometheus scraping\n- http_server_request_duration_seconds: API latency buckets\n- http_client_request_duration_seconds: Ollama call latency\n- ASP.NET Core instrumentation: Request count, status codes, methods\n- HTTP client instrumentation: External call reliability\n\n## Production Features (New)\n\n**Rate Limiting:**\n- Fixed window: 100 requests/minute per client\n- Partition key: Authenticated user or host header\n- Queue: 10 requests with FIFO processing\n- Rejection: HTTP 429 with JSON error and retry-after metadata\n- Prevents API abuse and protects Ollama backend\n\n**Health Checks:**\n- /health: Basic liveness check\n- /health/ready: Readiness with PostgreSQL validation\n- Database connectivity test using AspNetCore.HealthChecks.NpgSql\n- Docker healthcheck directives with retries and start periods\n\n**Configuration Management:**\n- appsettings.Production.json: Container-optimized settings\n- Environment-based configuration for all services\n- Langfuse keys optional (degrades gracefully without tracing)\n- Connection strings externalized to environment variables\n\n## Modified Core Components\n\n**ExecuteAgentCommandHandler (Major Changes):**\n- Added dependency injection: AgentDbContext, MathTool, DatabaseQueryTool, ILogger\n- Removed static in-memory conversation store\n- Added full OpenTelemetry instrumentation (5 span types)\n- Database persistence: Conversations saved to PostgreSQL\n- Error tracking: Tags for error type, message, success/failure\n- Tool registration moved to DI (no longer created inline)\n\n**OllamaClient (Enhancements):**\n- Added OpenTelemetry ActivitySource instrumentation\n- Latency tracking: Start time to completion measurement\n- Token estimation: Character count / 4 heuristic\n- Function call detection: Tags for has_function_calls\n- Performance metrics for SLO monitoring\n\n**Program.cs (Major Expansion):**\n- Added 10 new using statements (RateLimiting, OpenTelemetry, EF Core)\n- Database configuration: Connection string and DbContext registration\n- OpenTelemetry setup: Metrics + Tracing with conditional Langfuse export\n- Rate limiter configuration with custom rejection handler\n- Tool registration via DI (MathTool as singleton, DatabaseQueryTool as scoped)\n- Health checks with PostgreSQL validation\n- Auto-migration on startup with error handling\n- Prometheus metrics endpoint mapping\n- Enhanced console output with all endpoints listed\n\n**Svrnty.Sample.csproj (Package Additions):**\n- Npgsql.EntityFrameworkCore.PostgreSQL 9.0.2\n- Microsoft.EntityFrameworkCore.Design 9.0.0\n- OpenTelemetry 1.10.0\n- OpenTelemetry.Exporter.OpenTelemetryProtocol 1.10.0\n- OpenTelemetry.Extensions.Hosting 1.10.0\n- OpenTelemetry.Instrumentation.Http 1.10.0\n- OpenTelemetry.Instrumentation.EntityFrameworkCore 1.10.0-beta.1\n- OpenTelemetry.Instrumentation.AspNetCore 1.10.0\n- OpenTelemetry.Exporter.Prometheus.AspNetCore 1.10.0-beta.1\n- AspNetCore.HealthChecks.NpgSql 9.0.0\n\n## Documentation (New)\n\n**DEPLOYMENT_README.md:**\n- Complete deployment guide with 5-step quick start\n- Architecture diagram with all 4 services\n- Access points with all endpoints listed\n- Project structure overview\n- OpenTelemetry span hierarchy documentation\n- Database schema description\n- Troubleshooting commands\n- Performance characteristics and implementation details\n\n**Enhanced README.md:**\n- Added production deployment section\n- Docker Compose instructions\n- Langfuse configuration steps\n- Testing examples for all endpoints\n\n## Access Points (Complete List)\n\n- HTTP API: http://localhost:6001/api/command/executeAgent\n- gRPC API: http://localhost:6000 (via Grpc.AspNetCore.Server.Reflection)\n- Swagger UI: http://localhost:6001/swagger\n- Prometheus Metrics: http://localhost:6001/metrics ⭐ NEW\n- Health Check: http://localhost:6001/health ⭐ NEW\n- Readiness Check: http://localhost:6001/health/ready ⭐ NEW\n- Langfuse UI: http://localhost:3000 ⭐ NEW\n- Ollama API: http://localhost:11434 ⭐ NEW\n\n## Deployment Workflow\n\n1. `./scripts/deploy.sh` - One command to start everything\n2. Services start in order: PostgreSQL → Langfuse + Ollama → API\n3. Health checks validate all services before completion\n4. Database migrations apply automatically\n5. Ollama model pulls qwen2.5-coder:7b (6.7GB)\n6. Langfuse UI setup (one-time: create account, copy keys to .env)\n7. API restart to enable tracing: `docker compose restart api`\n\n## Testing Capabilities\n\n**Math Operations:**\n```bash\ncurl -X POST http://localhost:6001/api/command/executeAgent \\\n -H \"Content-Type: application/json\" \\\n -d ''{\"prompt\":\"What is 5 + 3?\"}''\n```\n\n**Business Intelligence:**\n```bash\ncurl -X POST http://localhost:6001/api/command/executeAgent \\\n -H \"Content-Type: application/json\" \\\n -d ''{\"prompt\":\"What was our revenue in January 2025?\"}''\n```\n\n**Rate Limiting Test:**\n```bash\nfor i in {1..105}; do\n curl -X POST http://localhost:6001/api/command/executeAgent \\\n -H \"Content-Type: application/json\" \\\n -d ''{\"prompt\":\"test\"}'' &\ndone\n# First 100 succeed, next 10 queue, remaining get HTTP 429\n```\n\n**Metrics Scraping:**\n```bash\ncurl http://localhost:6001/metrics | grep http_server_request_duration\n```\n\n## Performance Characteristics\n\n- **Agent Response Time:** 1-2 seconds for simple queries (unchanged)\n- **Database Query Time:** <50ms for all operations\n- **Trace Export:** Async batch export (5s intervals, 512 batch size)\n- **Rate Limit Window:** 1 minute fixed window\n- **Metrics Scrape:** Real-time Prometheus format\n- **Container Build:** ~2 minutes (multi-stage with caching)\n- **Total Deployment:** ~3-4 minutes (includes model pull)\n\n## Production Readiness Checklist\n\n✅ Docker containerization with multi-stage builds\n✅ PostgreSQL persistence with migrations\n✅ Full distributed tracing (OpenTelemetry → Langfuse)\n✅ Prometheus metrics for monitoring\n✅ Rate limiting to prevent abuse\n✅ Health checks with readiness probes\n✅ Auto-migration on startup\n✅ Environment-based configuration\n✅ Graceful error handling\n✅ Structured logging\n✅ One-command deployment\n✅ Comprehensive documentation\n\n## Business Value\n\n**Operational Excellence:**\n- Real-time performance monitoring via Prometheus + Langfuse\n- Incident detection with distributed tracing\n- Capacity planning data from metrics\n- SLO/SLA tracking with P50/P95/P99 latency\n- Cost tracking via token usage visibility\n\n**Reliability:**\n- Database persistence prevents data loss\n- Health checks enable orchestration (Kubernetes-ready)\n- Rate limiting protects against abuse\n- Graceful degradation without Langfuse keys\n\n**Developer Experience:**\n- One-command deployment (`./scripts/deploy.sh`)\n- Swagger UI for API exploration\n- Comprehensive traces for debugging\n- Clear error messages with context\n\n**Security:**\n- Environment-based secrets (not in code)\n- Basic Auth for Langfuse OTLP\n- Rate limiting prevents DoS\n- Database credentials externalized\n\n## Implementation Time\n\n- Infrastructure setup: 20 minutes\n- Database integration: 45 minutes\n- Containerization: 30 minutes\n- OpenTelemetry instrumentation: 45 minutes\n- Health checks & config: 15 minutes\n- Deployment automation: 20 minutes\n- Rate limiting & metrics: 15 minutes\n- Documentation: 15 minutes\n**Total: ~3.5 hours**\n\nThis transforms the AI agent from a demo into an enterprise-ready system that can be \nconfidently deployed to production. All core functionality preserved while adding \ncomprehensive observability, persistence, and operational excellence.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\nEOF\n)\")",
|
|
"Bash(chmod:*)",
|
|
"Bash(/Users/jean-philippebrule/.dotnet/dotnet clean Svrnty.Sample/Svrnty.Sample.csproj)",
|
|
"Bash(/Users/jean-philippebrule/.dotnet/dotnet build:*)",
|
|
"Bash(docker:*)",
|
|
"Bash(git restore:*)"
|
|
],
|
|
"deny": [],
|
|
"ask": []
|
|
}
|
|
}
|