Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/1025615864_baixingfalvzhushou.json
T

1 line
107 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "1025615864/baixingfalvzhushou", "files": {".env.example": {"c1eed528869ea31d43229df00a2aa8d60ec421a2": {"t": 1785747110.8012185, "n": 13094, "h": "e3e0fd4c2f770c90", "c": "# ==========================================\n# 百姓法律助手 - 本地开发环境变量模板\n# 使用说明:\n# 1. 复制此文件为 .env:cp .env.example .env\n# 2. 运行密钥生成脚本:bash scripts/generate_secrets.sh\n# 3. 将生成的密钥填入下方对应位置\n# 4. 不要将 .env 文件提交到 Git 仓库\n# ==========================================\n\n# ==========================================\n# 数据库配置 (PostgreSQL)\n# ==========================================\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=dev_password_change_me\nPOSTGRES_DB=baixing_law\nDATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/baixing_law\nDB_POOL_SIZE=30\nDB_MAX_OVERFLOW=40\nDB_POOL_RECYCLE=1800\nDB_POOL_TIMEOUT=30\nSQL_ECHO=false\nSLOW_QUERY_THRESHOLD_MS=100\nDB_ALLOW_RUNTIME_DDL=1\n\n# 微服务独立数据库连接(覆盖 DATABASE_URL,可选)\nUSER_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/user_service\nLEGAL_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/legal_service\nNEWS_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/news_service\nCOMMUNITY_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/community_service\nSEARCH_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/search_service\nRECOMMENDATION_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/recommendation_service\nNOTIFICATION_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/notification_service\nORDER_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/order_service\nPOINTS_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/points_service\nKNOWLEDGE_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/knowledge_service\nARCHIVE_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/archive_service\nAI_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/ai_service\nEMBEDDING_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/embedding_service\nPAYMENT_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/payment_channel\n\n# ==========================================\n# 安全配置 (Security)\n# ==========================================\nSECRET_KEY=dev_secret_key_change_me_run_generate_secrets_sh\nJWT_SECRET_KEY=dev_jwt_secret_key_change_me_run_generate_secrets_sh\nJWT_ALGORITHM=HS256\nJWT_ACCESS_TOKEN_EXPIRE_MINUTES=60\nJWT_REFRESH_TOKEN_EXPIRE_DAYS=7\nJWT_AUDIENCE=\nJWT_RSA_PRIVATE_KEY=\nJWT_RSA_PUBLIC_KEY=\nCSRF_SECRET_KEY=dev_csrf_secret_change_me\nCSRF_ENABLED=true\nCSRF_TOKEN_EXPIRE_HOURS=24\nCSRF_TOKEN_SIZE=32\nCARD_ENCRYPTION_KEY=\n# CSRF 保护的 HTTP 方法列表(默认 POST,PUT,PATCH,DELETE)\nCSRF_PROTECTED_METHODS=POST,PUT,PATCH,DELETE\n# CSRF 豁免路径列表(默认登录/注册/刷新令牌接口)\nCSRF_EXEMPT_PATHS=/api/auth/login,/api/auth/register,/api/auth/refresh,/api/user/login,/api/user/register,/api/user/logout\n# 邮箱重置密码签名密钥(用于生成密码重置 token 的 HMAC 签名)\nEMAIL_RESET_SECRET=baixing-reset-secret-key-2026\nPAYMENT_WEBHOOK_SECRET=dev_payment_webhook_secret_change_me\nMETRICS_AUTH_TOKEN=dev_metrics_token_change_me\nINTERNAL_API_KEY=dev-internal-api-key\n\n# ==========================================\n# 缓存与消息队列 (Redis)\n# ==========================================\nREDIS_URL=redis://:dev_redis_password_change_me@localhost:16379/0\nREDIS_PASSWORD=dev_redis_password_change_me\n\n# ==========================================\n# 网络与跨域 (Network & CORS)\n# ==========================================\nCORS_ALLOW_ORIGINS=[\"http://localhost:3000\",\"http://localhost:5173\"]\nCORS_ORIGINS=http://localhost:3000,http://localhost:5173\nCORS_ALLOW_CREDENTIALS=true\nTRUSTED_PROXIES=\n\n# ==========================================\n# 前端构建配置 (Frontend)\n# ==========================================\nVITE_API_BASE_URL=/api\nVITE_WS_URL=ws://localhost:8000/ws\nVITE_BACKEND_URL=http://localhost:8000\n\n# ==========================================\n# AI 服务配置 (AI Services)\n# ==========================================\n# 必填:OpenAI 兼容的 API Key(DeepSeek / OpenAI 等)\nOPENAI_API_KEY=sk-your-api-key-here\n# API 地址(DeepSeek 使用 https://api.deepseek.com/v1)\nOPENAI_BASE_URL=https://api.deepseek.com/v1\n# 模型名称(推荐 deepseek-chat 性价比高)\nAI_MODEL=deepseek-chat\n# AI 回退模型列表(JSON 数组或逗号分隔)\nAI_FALLBACK_MODELS=\n# 转写专用 API(可选,默认复用 OPENAI_API_KEY)\nOPENAI_TRANSCRIBE_API_KEY=\nOPENAI_TRANSCRIBE_BASE_URL=\n# 二级 LLM(可选,用于复杂推理任务)\nSECONDARY_LLM_URL=\nSECONDARY_LLM_KEY=\nSECONDARY_LLM_MODEL=deepseek-reasoner\n\n# Azure OpenAI(可选,作为备选 AI 提供者)\nAZURE_OPENAI_API_KEY=\nAZURE_OPENAI_BASE_URL=\nAZURE_OPENAI_MODEL=\n\n# AI 新闻摘要\nNEWS_AI_SUMMARY_ENABLED=false\nNEWS_AI_MAX_AGE=7\nNEWS_AI_BATCH_SIZE=50\nNEWS_AI_MAX_CONCURRENT=5\n# LLM 新闻摘要高级配置(启用多 LLM 提供者轮换)\nNEWS_AI_SUMMARY_LLM_ENABLED=false\nNEWS_AI_SUMMARY_LLM_RESPONSE_FORMAT=text\nNEWS_AI_SUMMARY_LLM_PROVIDERS_JSON=[]\nNEWS_AI_SUMMARY_LLM_PROVIDER_STRATEGY=random\nNEWS_AI_SUMMARY_WRITEBACK_ENABLED=false\nNEWS_REVIEW_POLICY_ENABLED=false\n\n# 语音转写\nVOICE_TRANSCRIBE_FORCE_ENABLED=false\nVOICE_TRANSCRIBE_PROVIDER=auto\n\n# RAG 配置\nRAG_LEVEL1_TIMEOUT_MS=500\nRAG_LEVEL2_TIMEOUT_MS=2000\nRAG_MIN_SIMILARITY=0.75\nRAG_TOP_K=5\nCHROMA_PERSIST_DIR=./chroma_db\n\n# AI 质量监控\nAI_QUALITY_REDIS_ENABLED=true\nAI_QUALITY_REDIS_KEY_PREFIX=ai_quality:\nAI_QUALITY_MAX_RECENT_LOGS=1000\nAI_QUALITY_TTL_SECONDS=604800\n\n# ==========================================\n# 语音识别 (Sherpa ASR)\n# ==========================================\nSHERPA_ASR_ENABLED=false\nSHERPA_ASR_MODE=off\nSHERPA_ASR_REMOTE_URL=\nSHERPA_ONNX_TOKENS=\nSHERPA_ONNX_WENET_CTC_MODEL=\nSHERPA_ONNX_WHISPER_ENCODER=\nSHERPA_ONNX_WHISPER_DECODER=\nSHERPA_ONNX_WHISPER_LANGUAGE=\nSHERPA_ONNX_WHISPER_TASK=transcribe\nSHERPA_ONNX_WHISPER_TAIL_PADDINGS=-1\nSHERPA_ONNX_NUM_THREADS=2\nSHERPA_ONNX_DECODING_METHOD=greedy_search\nSHERPA_ONNX_DEBUG=false\nSHERPA_ONNX_SAMPLE_RATE=16000\nSHERPA_ONNX_FEATURE_DIM=80\n\n# ==========================================\n# 微服务地址 (Service URLs)\n# ==========================================\nAI_SERVICE_URL=http://localhost:8005\nUSER_SERVICE_URL=http://localhost:8001\nORDER_SERVICE_URL=http://localhost:8004\nNEWS_SERVICE_URL=http://localhost:8006\nCOMMUNITY_SERVICE_URL=http://localhost:8007\nLEGAL_SERVICE_URL=http://localhost:8008\nSEARCH_SERVICE_URL=http://localhost:8009\nRECOMMENDATION_SERVICE_URL=http://localhost:8010\nNOTIFICATION_SERVICE_URL=http://localhost:8011\nPOINTS_SERVICE_URL=http://localhost:8012\nARCHIVE_SERVICE_URL=http://localhost:8013\nPAYMENT_SERVICE_URL=http://localhost:8002\nPAYMENT_CHANNEL_SERVICE_URL=http://localhost:8002\nEMBEDDING_SERVICE_URL=http://localhost:8003\nKNOWLEDGE_SERVICE_URL=http://localhost:8081\nBACKEND_URL=http://localhost:8000\n\n# ==========================================\n# 支付配置 (Payment)\n# ==========================================\n# 微信支付\nWECHATPAY_MCH_ID=your_mch_id\nWECHATPAY_MCH_SERIAL_NO=\nWECHATPAY_API_V3_KEY=\nWECHATPAY_PRIVATE_KEY=\nWECHATPAY_PUBLIC_KEY=\nWECHATPAY_CERTIFICATES_URL=https://api.mch.weixin.qq.com/v3/certificates\nWECHATPAY_NOTIFY_URL=\nWECHATPAY_CERT_REFRESH_ENABLED=false\nWECHATPAY_CERT_REFRESH_INTERVAL_SECONDS=86400\n# 微信支付回调 IP 白名单(逗号分隔)\nWECHATPAY_CALLBACK_IPS=203.205.219.0/24,203.205.220.0/24,203.205.221.0/24,203.205.222.0/24,203.205.223.0/24\n# 支付宝\nALIPAY_APP_ID=your_app_id\nALIPAY_PRIVATE_KEY=\nALIPAY_PUBLIC_KEY=\nALIPAY_GATEWAY_URL=https://openapi.alipay.com/gateway.do\nALIPAY_NOTIFY_URL=\nALIPAY_RETURN_URL=\n# 支付宝回调 IP 白名单(逗号分隔)\nALIPAY_CALLBACK_IPS=103.52.76.0/24,103.52.77.0/24,110.76.16.0/24,110.76.17.0/24,110.76.18.0/24,110.76.19.0/24,110.76.20.0/24,110.76.21.0/24,110.76.22.0/24,110.76.23.0/24\n# IkunPay\nIKUNPAY_PID=\nIKUNPAY_KEY=\nIKUNPAY_GATEWAY_URL=https://ikunpay.com/submit.php\nIKUNPAY_NOTIFY_URL=\nIKUNPAY_RETURN_URL=\nIKUNPAY_DEFAULT_TYPE=\n# IkunPay 回调 IP 白名单(逗号分隔)\nIKUNPAY_CALLBACK_IPS=\n\n# ==========================================\n# 通知配置 (Notification)\n# ==========================================\n# 邮件 (SMTP)\nSMTP_HOST=\nSMTP_PORT=587\nSMTP_USER=\nSMTP_PASSWORD=\nSMTP_FROM=noreply@baixinglaw.com\n# 短信\nSMS_PROVIDER=\nSMS_ACCESS_KEY_ID=\nSMS_ACCESS_KEY_SECRET=\nSMS_SIGN_NAME=\nSMS_TEMPLATE_CODE=\n\n# ==========================================\n# 监控配置 (Monitoring)\n# ==========================================\nSENTRY_DSN=\nSENTRY_ENVIRONMENT=development\nSENTRY_RELEASE=1.0.0\nSENTRY_TRACES_SAMPLE_RATE=0.1\nSENTRY_PROFILES_SAMPLE_RATE=0.0\nPROMETHEUS_ENABLED=true\nPROMETHEUS_PORT=8001\nGRAFANA_ADMIN_USER=admin\nGRAFANA_ADMIN_PASSWORD=admin123\nOTEL_EXPORTER_OTLP_ENDPOINT=\nMONITORING_DIR=monitoring\n\n# ==========================================\n# 关键事件告警 (Critical Events)\n# ==========================================\nCRITICAL_EVENTS_WEBHOOK_URL=\nCRITICAL_EVENTS_WEBHOOK_BEARER=\nCRITICAL_EVENTS_WEBHOOK_HEADER_NAME=\nCRITICAL_EVENTS_WEBHOOK_HEADER_VALUE=\nCRITICAL_EVENTS_TIMEOUT_SECONDS=3.0\n\n# ==========================================\n# 对象存储 (S3 / MinIO)\n# ==========================================\nSTORAGE_PROVIDER=s3\nSTORAGE_S3_ENDPOINT_URL=http://localhost:9000\nSTORAGE_S3_BUCKET=baixing-uploads\nSTORAGE_S3_REGION=us-east-1\nSTORAGE_S3_ACCESS_KEY_ID=minioadmin\nSTORAGE_S3_SECRET_ACCESS_KEY=minioadmin\nSTORAGE_S3_PREFIX=uploads\nSTORAGE_PUBLIC_BASE_URL=http://localhost:9000/baixing-uploads\nMINIO_ROOT_USER=minioadmin\nMINIO_ROOT_PASSWORD=minioadmin\n\n# ==========================================\n# 文件上传配置 (Upload)\n# ==========================================\nUPLOAD_DIR=./uploads\nUPLOAD_IMAGE_MODERATION_ENABLED=true\nUPLOAD_VIRUS_SCAN_ENABLED=true\nUPLOAD_VIRUS_SCAN_FAIL_OPEN=false\nUPLOAD_ALLOW_LOCAL_STORAGE=false\n# 允许病毒扫描模拟模式(仅开发环境,生产环境必须配置 ClamAV)\nUPLOAD_VIRUS_SCAN_ALLOW_MOCK=false\n\n# ==========================================\n# 图片审核 (Image Moderation)\n# ==========================================\nIMAGE_MODERATION_PROVIDER=\nALIYUN_ACCESS_KEY_ID=\nALIYUN_ACCESS_KEY_SECRET=\nALIYUN_GREEN_ENDPOINT=green.cn-shanghai.aliyuncs.com\nTENCENT_SECRET_ID=\nTENCENT_SECRET_KEY=\n\n# ==========================================\n# 向量存储 (Vector Store)\n# ==========================================\nVECTOR_STORE_TYPE=chroma\nEMBEDDING_DIMENSION=768\n\n# ==========================================\n# Kafka 事件流\n# ==========================================\nKAFKA_ENABLED=true\nKAFKA_BOOTSTRAP_SERVERS=localhost:9092\nENABLE_KAFKA=false\nENABLE_KAFKA_PRODUCER=false\nENABLE_KAFKA_CONSUMER=false\n\n# ==========================================\n# gRPC 配置\n# ==========================================\nENABLE_GRPC_SERVER=false\nENABLE_GRPC_CLIENT=false\nGRPC_PORT=50051\nGRPC_USE_TLS=false\n\n# ==========================================\n# 事务与事件 (Saga / Outbox)\n# ==========================================\nENABLE_SAGA_PERSISTENCE=false\nENABLE_OUTBOX=true\nOUTBOX_POLL_INTERVAL=5\n\n# ==========================================\n# 会员管理 (Membership)\n# ==========================================\nENABLE_MEMBERSHIP_EXPIRY_CHECK=true\n\n# ==========================================\n# 定时任务调度 (Task Scheduler)\n# ==========================================\nSETTLEMENT_JOB_ENABLED=false\nSETTLEMENT_JOB_INTERVAL_SECONDS=3600\nREVIEW_TASK_SLA_JOB_ENABLED=false\nREVIEW_TASK_SLA_SCAN_INTERVAL_SECONDS=60\n\n# ==========================================\n# WebSocket 配置\n# ==========================================\nWS_MAX_CONNECTIONS_PER_IP=5\nWS_MAX_CONNECTIONS_PER_USER=3\nWS_MESSAGE_RATE_LIMIT=30\nWS_MESSAGE_RATE_WINDOW=60\nWS_MAX_MESSAGE_SIZE=10240\nWS_CONNECTION_TIMEOUT=300\nWS_PING_TIMEOUT=60\nWS_MAX_RECONNECT_ATTEMPTS=3\nWS_RECONNECT_BACKOFF=5\n\n# ==========================================\n# 服务发现 (Consul)\n# ==========================================\nCONSUL_ENABLED=false\nSERVICE_HOST=localhost\nSERVICE_PORT=8080\n\n# ==========================================\n# 日志脱敏 (Log Masking)\n# ==========================================\nLOG_MASK_LEVEL=standard\nLOG_MASK_DISABLE_IN_DEBUG=true\n# 额外的日志脱敏字段列表(逗号分隔,默认已包含 password,secret,token,key,authorization 等)\nLOG_MASK_FIELDS=\n\n# ==========================================\n# 日志级别 (Log Level)\n# ==========================================\nLOG_LEVEL=INFO\n\n# ==========================================\n# 限流配置 (Rate Limiting)\n# ==========================================\nRATE_LIMIT_PER_MINUTE=60\nRATE_LIMIT_PER_SECOND=10\n\n# ==========================================\n# 环境标识 (Environment)\n# ==========================================\nENVIRONMENT=development\nAPP_ENV=development\n# Consul 服务发现注册时使用的环境标签\nENV=development\nVERSION=2.0.0\nDEBUG=true\n\n# ==========================================\n# 内部开关 (Internal Flags)\n# ==========================================\nENV_FILE=\n_BAIXING_FORCE_VERIFY=\n\n# ==========================================\n# 容器资源限制 (Docker Compose Resource Limits)\n# ==========================================\n# PostgreSQL 数据库\nDB_CPU_LIMIT=1\nDB_MEMORY_LIMIT=1G\n# Redis 缓存\nREDIS_CPU_LIMIT=0.5\nREDIS_MEMORY_LIMIT=512M\n# 后端服务\nBACKEND_CPU_LIMIT=2\nBACKEND_MEMORY_LIMIT=2G\n\n# ==========================================\n# 端到端测试 (E2E Testing)\n# ==========================================\n# 设为 1 时自动初始化 E2E 测试种子数据\nE2E_SEED=0\n\n# ==========================================\n# 冒烟测试配置 (Smoke Test - ikunpay_smoke.py)\n# ==========================================\n# 冒烟测试后端地址\nBACKEND_BASE_URL=http://127.0.0.1:8000\n# 测试用普通用户凭据\nUSER_USERNAME=user1\nUSER_PASSWORD=user123\n# 测试用管理员凭据\nADMIN_USERNAME=admin\nADMIN_PASSWORD=admin123"}, "cdcd065d5d5cfd41685ef66a05e0e7b622f28b79": {"t": 1785770469.9616334, "n": 13094, "h": "e3e0fd4c2f770c90", "c": "# ==========================================\n# 百姓法律助手 - 本地开发环境变量模板\n# 使用说明:\n# 1. 复制此文件为 .env:cp .env.example .env\n# 2. 运行密钥生成脚本:bash scripts/generate_secrets.sh\n# 3. 将生成的密钥填入下方对应位置\n# 4. 不要将 .env 文件提交到 Git 仓库\n# ==========================================\n\n# ==========================================\n# 数据库配置 (PostgreSQL)\n# ==========================================\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=dev_password_change_me\nPOSTGRES_DB=baixing_law\nDATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/baixing_law\nDB_POOL_SIZE=30\nDB_MAX_OVERFLOW=40\nDB_POOL_RECYCLE=1800\nDB_POOL_TIMEOUT=30\nSQL_ECHO=false\nSLOW_QUERY_THRESHOLD_MS=100\nDB_ALLOW_RUNTIME_DDL=1\n\n# 微服务独立数据库连接(覆盖 DATABASE_URL,可选)\nUSER_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/user_service\nLEGAL_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/legal_service\nNEWS_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/news_service\nCOMMUNITY_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/community_service\nSEARCH_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/search_service\nRECOMMENDATION_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/recommendation_service\nNOTIFICATION_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/notification_service\nORDER_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/order_service\nPOINTS_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/points_service\nKNOWLEDGE_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/knowledge_service\nARCHIVE_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/archive_service\nAI_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/ai_service\nEMBEDDING_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/embedding_service\nPAYMENT_DATABASE_URL=postgresql+asyncpg://postgres:dev_password_change_me@localhost:5433/payment_channel\n\n# ==========================================\n# 安全配置 (Security)\n# ==========================================\nSECRET_KEY=dev_secret_key_change_me_run_generate_secrets_sh\nJWT_SECRET_KEY=dev_jwt_secret_key_change_me_run_generate_secrets_sh\nJWT_ALGORITHM=HS256\nJWT_ACCESS_TOKEN_EXPIRE_MINUTES=60\nJWT_REFRESH_TOKEN_EXPIRE_DAYS=7\nJWT_AUDIENCE=\nJWT_RSA_PRIVATE_KEY=\nJWT_RSA_PUBLIC_KEY=\nCSRF_SECRET_KEY=dev_csrf_secret_change_me\nCSRF_ENABLED=true\nCSRF_TOKEN_EXPIRE_HOURS=24\nCSRF_TOKEN_SIZE=32\nCARD_ENCRYPTION_KEY=\n# CSRF 保护的 HTTP 方法列表(默认 POST,PUT,PATCH,DELETE)\nCSRF_PROTECTED_METHODS=POST,PUT,PATCH,DELETE\n# CSRF 豁免路径列表(默认登录/注册/刷新令牌接口)\nCSRF_EXEMPT_PATHS=/api/auth/login,/api/auth/register,/api/auth/refresh,/api/user/login,/api/user/register,/api/user/logout\n# 邮箱重置密码签名密钥(用于生成密码重置 token 的 HMAC 签名)\nEMAIL_RESET_SECRET=baixing-reset-secret-key-2026\nPAYMENT_WEBHOOK_SECRET=dev_payment_webhook_secret_change_me\nMETRICS_AUTH_TOKEN=dev_metrics_token_change_me\nINTERNAL_API_KEY=dev-internal-api-key\n\n# ==========================================\n# 缓存与消息队列 (Redis)\n# ==========================================\nREDIS_URL=redis://:dev_redis_password_change_me@localhost:16379/0\nREDIS_PASSWORD=dev_redis_password_change_me\n\n# ==========================================\n# 网络与跨域 (Network & CORS)\n# ==========================================\nCORS_ALLOW_ORIGINS=[\"http://localhost:3000\",\"http://localhost:5173\"]\nCORS_ORIGINS=http://localhost:3000,http://localhost:5173\nCORS_ALLOW_CREDENTIALS=true\nTRUSTED_PROXIES=\n\n# ==========================================\n# 前端构建配置 (Frontend)\n# ==========================================\nVITE_API_BASE_URL=/api\nVITE_WS_URL=ws://localhost:8000/ws\nVITE_BACKEND_URL=http://localhost:8000\n\n# ==========================================\n# AI 服务配置 (AI Services)\n# ==========================================\n# 必填:OpenAI 兼容的 API Key(DeepSeek / OpenAI 等)\nOPENAI_API_KEY=sk-your-api-key-here\n# API 地址(DeepSeek 使用 https://api.deepseek.com/v1)\nOPENAI_BASE_URL=https://api.deepseek.com/v1\n# 模型名称(推荐 deepseek-chat 性价比高)\nAI_MODEL=deepseek-chat\n# AI 回退模型列表(JSON 数组或逗号分隔)\nAI_FALLBACK_MODELS=\n# 转写专用 API(可选,默认复用 OPENAI_API_KEY)\nOPENAI_TRANSCRIBE_API_KEY=\nOPENAI_TRANSCRIBE_BASE_URL=\n# 二级 LLM(可选,用于复杂推理任务)\nSECONDARY_LLM_URL=\nSECONDARY_LLM_KEY=\nSECONDARY_LLM_MODEL=deepseek-reasoner\n\n# Azure OpenAI(可选,作为备选 AI 提供者)\nAZURE_OPENAI_API_KEY=\nAZURE_OPENAI_BASE_URL=\nAZURE_OPENAI_MODEL=\n\n# AI 新闻摘要\nNEWS_AI_SUMMARY_ENABLED=false\nNEWS_AI_MAX_AGE=7\nNEWS_AI_BATCH_SIZE=50\nNEWS_AI_MAX_CONCURRENT=5\n# LLM 新闻摘要高级配置(启用多 LLM 提供者轮换)\nNEWS_AI_SUMMARY_LLM_ENABLED=false\nNEWS_AI_SUMMARY_LLM_RESPONSE_FORMAT=text\nNEWS_AI_SUMMARY_LLM_PROVIDERS_JSON=[]\nNEWS_AI_SUMMARY_LLM_PROVIDER_STRATEGY=random\nNEWS_AI_SUMMARY_WRITEBACK_ENABLED=false\nNEWS_REVIEW_POLICY_ENABLED=false\n\n# 语音转写\nVOICE_TRANSCRIBE_FORCE_ENABLED=false\nVOICE_TRANSCRIBE_PROVIDER=auto\n\n# RAG 配置\nRAG_LEVEL1_TIMEOUT_MS=500\nRAG_LEVEL2_TIMEOUT_MS=2000\nRAG_MIN_SIMILARITY=0.75\nRAG_TOP_K=5\nCHROMA_PERSIST_DIR=./chroma_db\n\n# AI 质量监控\nAI_QUALITY_REDIS_ENABLED=true\nAI_QUALITY_REDIS_KEY_PREFIX=ai_quality:\nAI_QUALITY_MAX_RECENT_LOGS=1000\nAI_QUALITY_TTL_SECONDS=604800\n\n# ==========================================\n# 语音识别 (Sherpa ASR)\n# ==========================================\nSHERPA_ASR_ENABLED=false\nSHERPA_ASR_MODE=off\nSHERPA_ASR_REMOTE_URL=\nSHERPA_ONNX_TOKENS=\nSHERPA_ONNX_WENET_CTC_MODEL=\nSHERPA_ONNX_WHISPER_ENCODER=\nSHERPA_ONNX_WHISPER_DECODER=\nSHERPA_ONNX_WHISPER_LANGUAGE=\nSHERPA_ONNX_WHISPER_TASK=transcribe\nSHERPA_ONNX_WHISPER_TAIL_PADDINGS=-1\nSHERPA_ONNX_NUM_THREADS=2\nSHERPA_ONNX_DECODING_METHOD=greedy_search\nSHERPA_ONNX_DEBUG=false\nSHERPA_ONNX_SAMPLE_RATE=16000\nSHERPA_ONNX_FEATURE_DIM=80\n\n# ==========================================\n# 微服务地址 (Service URLs)\n# ==========================================\nAI_SERVICE_URL=http://localhost:8005\nUSER_SERVICE_URL=http://localhost:8001\nORDER_SERVICE_URL=http://localhost:8004\nNEWS_SERVICE_URL=http://localhost:8006\nCOMMUNITY_SERVICE_URL=http://localhost:8007\nLEGAL_SERVICE_URL=http://localhost:8008\nSEARCH_SERVICE_URL=http://localhost:8009\nRECOMMENDATION_SERVICE_URL=http://localhost:8010\nNOTIFICATION_SERVICE_URL=http://localhost:8011\nPOINTS_SERVICE_URL=http://localhost:8012\nARCHIVE_SERVICE_URL=http://localhost:8013\nPAYMENT_SERVICE_URL=http://localhost:8002\nPAYMENT_CHANNEL_SERVICE_URL=http://localhost:8002\nEMBEDDING_SERVICE_URL=http://localhost:8003\nKNOWLEDGE_SERVICE_URL=http://localhost:8081\nBACKEND_URL=http://localhost:8000\n\n# ==========================================\n# 支付配置 (Payment)\n# ==========================================\n# 微信支付\nWECHATPAY_MCH_ID=your_mch_id\nWECHATPAY_MCH_SERIAL_NO=\nWECHATPAY_API_V3_KEY=\nWECHATPAY_PRIVATE_KEY=\nWECHATPAY_PUBLIC_KEY=\nWECHATPAY_CERTIFICATES_URL=https://api.mch.weixin.qq.com/v3/certificates\nWECHATPAY_NOTIFY_URL=\nWECHATPAY_CERT_REFRESH_ENABLED=false\nWECHATPAY_CERT_REFRESH_INTERVAL_SECONDS=86400\n# 微信支付回调 IP 白名单(逗号分隔)\nWECHATPAY_CALLBACK_IPS=203.205.219.0/24,203.205.220.0/24,203.205.221.0/24,203.205.222.0/24,203.205.223.0/24\n# 支付宝\nALIPAY_APP_ID=your_app_id\nALIPAY_PRIVATE_KEY=\nALIPAY_PUBLIC_KEY=\nALIPAY_GATEWAY_URL=https://openapi.alipay.com/gateway.do\nALIPAY_NOTIFY_URL=\nALIPAY_RETURN_URL=\n# 支付宝回调 IP 白名单(逗号分隔)\nALIPAY_CALLBACK_IPS=103.52.76.0/24,103.52.77.0/24,110.76.16.0/24,110.76.17.0/24,110.76.18.0/24,110.76.19.0/24,110.76.20.0/24,110.76.21.0/24,110.76.22.0/24,110.76.23.0/24\n# IkunPay\nIKUNPAY_PID=\nIKUNPAY_KEY=\nIKUNPAY_GATEWAY_URL=https://ikunpay.com/submit.php\nIKUNPAY_NOTIFY_URL=\nIKUNPAY_RETURN_URL=\nIKUNPAY_DEFAULT_TYPE=\n# IkunPay 回调 IP 白名单(逗号分隔)\nIKUNPAY_CALLBACK_IPS=\n\n# ==========================================\n# 通知配置 (Notification)\n# ==========================================\n# 邮件 (SMTP)\nSMTP_HOST=\nSMTP_PORT=587\nSMTP_USER=\nSMTP_PASSWORD=\nSMTP_FROM=noreply@baixinglaw.com\n# 短信\nSMS_PROVIDER=\nSMS_ACCESS_KEY_ID=\nSMS_ACCESS_KEY_SECRET=\nSMS_SIGN_NAME=\nSMS_TEMPLATE_CODE=\n\n# ==========================================\n# 监控配置 (Monitoring)\n# ==========================================\nSENTRY_DSN=\nSENTRY_ENVIRONMENT=development\nSENTRY_RELEASE=1.0.0\nSENTRY_TRACES_SAMPLE_RATE=0.1\nSENTRY_PROFILES_SAMPLE_RATE=0.0\nPROMETHEUS_ENABLED=true\nPROMETHEUS_PORT=8001\nGRAFANA_ADMIN_USER=admin\nGRAFANA_ADMIN_PASSWORD=admin123\nOTEL_EXPORTER_OTLP_ENDPOINT=\nMONITORING_DIR=monitoring\n\n# ==========================================\n# 关键事件告警 (Critical Events)\n# ==========================================\nCRITICAL_EVENTS_WEBHOOK_URL=\nCRITICAL_EVENTS_WEBHOOK_BEARER=\nCRITICAL_EVENTS_WEBHOOK_HEADER_NAME=\nCRITICAL_EVENTS_WEBHOOK_HEADER_VALUE=\nCRITICAL_EVENTS_TIMEOUT_SECONDS=3.0\n\n# ==========================================\n# 对象存储 (S3 / MinIO)\n# ==========================================\nSTORAGE_PROVIDER=s3\nSTORAGE_S3_ENDPOINT_URL=http://localhost:9000\nSTORAGE_S3_BUCKET=baixing-uploads\nSTORAGE_S3_REGION=us-east-1\nSTORAGE_S3_ACCESS_KEY_ID=minioadmin\nSTORAGE_S3_SECRET_ACCESS_KEY=minioadmin\nSTORAGE_S3_PREFIX=uploads\nSTORAGE_PUBLIC_BASE_URL=http://localhost:9000/baixing-uploads\nMINIO_ROOT_USER=minioadmin\nMINIO_ROOT_PASSWORD=minioadmin\n\n# ==========================================\n# 文件上传配置 (Upload)\n# ==========================================\nUPLOAD_DIR=./uploads\nUPLOAD_IMAGE_MODERATION_ENABLED=true\nUPLOAD_VIRUS_SCAN_ENABLED=true\nUPLOAD_VIRUS_SCAN_FAIL_OPEN=false\nUPLOAD_ALLOW_LOCAL_STORAGE=false\n# 允许病毒扫描模拟模式(仅开发环境,生产环境必须配置 ClamAV)\nUPLOAD_VIRUS_SCAN_ALLOW_MOCK=false\n\n# ==========================================\n# 图片审核 (Image Moderation)\n# ==========================================\nIMAGE_MODERATION_PROVIDER=\nALIYUN_ACCESS_KEY_ID=\nALIYUN_ACCESS_KEY_SECRET=\nALIYUN_GREEN_ENDPOINT=green.cn-shanghai.aliyuncs.com\nTENCENT_SECRET_ID=\nTENCENT_SECRET_KEY=\n\n# ==========================================\n# 向量存储 (Vector Store)\n# ==========================================\nVECTOR_STORE_TYPE=chroma\nEMBEDDING_DIMENSION=768\n\n# ==========================================\n# Kafka 事件流\n# ==========================================\nKAFKA_ENABLED=true\nKAFKA_BOOTSTRAP_SERVERS=localhost:9092\nENABLE_KAFKA=false\nENABLE_KAFKA_PRODUCER=false\nENABLE_KAFKA_CONSUMER=false\n\n# ==========================================\n# gRPC 配置\n# ==========================================\nENABLE_GRPC_SERVER=false\nENABLE_GRPC_CLIENT=false\nGRPC_PORT=50051\nGRPC_USE_TLS=false\n\n# ==========================================\n# 事务与事件 (Saga / Outbox)\n# ==========================================\nENABLE_SAGA_PERSISTENCE=false\nENABLE_OUTBOX=true\nOUTBOX_POLL_INTERVAL=5\n\n# ==========================================\n# 会员管理 (Membership)\n# ==========================================\nENABLE_MEMBERSHIP_EXPIRY_CHECK=true\n\n# ==========================================\n# 定时任务调度 (Task Scheduler)\n# ==========================================\nSETTLEMENT_JOB_ENABLED=false\nSETTLEMENT_JOB_INTERVAL_SECONDS=3600\nREVIEW_TASK_SLA_JOB_ENABLED=false\nREVIEW_TASK_SLA_SCAN_INTERVAL_SECONDS=60\n\n# ==========================================\n# WebSocket 配置\n# ==========================================\nWS_MAX_CONNECTIONS_PER_IP=5\nWS_MAX_CONNECTIONS_PER_USER=3\nWS_MESSAGE_RATE_LIMIT=30\nWS_MESSAGE_RATE_WINDOW=60\nWS_MAX_MESSAGE_SIZE=10240\nWS_CONNECTION_TIMEOUT=300\nWS_PING_TIMEOUT=60\nWS_MAX_RECONNECT_ATTEMPTS=3\nWS_RECONNECT_BACKOFF=5\n\n# ==========================================\n# 服务发现 (Consul)\n# ==========================================\nCONSUL_ENABLED=false\nSERVICE_HOST=localhost\nSERVICE_PORT=8080\n\n# ==========================================\n# 日志脱敏 (Log Masking)\n# ==========================================\nLOG_MASK_LEVEL=standard\nLOG_MASK_DISABLE_IN_DEBUG=true\n# 额外的日志脱敏字段列表(逗号分隔,默认已包含 password,secret,token,key,authorization 等)\nLOG_MASK_FIELDS=\n\n# ==========================================\n# 日志级别 (Log Level)\n# ==========================================\nLOG_LEVEL=INFO\n\n# ==========================================\n# 限流配置 (Rate Limiting)\n# ==========================================\nRATE_LIMIT_PER_MINUTE=60\nRATE_LIMIT_PER_SECOND=10\n\n# ==========================================\n# 环境标识 (Environment)\n# ==========================================\nENVIRONMENT=development\nAPP_ENV=development\n# Consul 服务发现注册时使用的环境标签\nENV=development\nVERSION=2.0.0\nDEBUG=true\n\n# ==========================================\n# 内部开关 (Internal Flags)\n# ==========================================\nENV_FILE=\n_BAIXING_FORCE_VERIFY=\n\n# ==========================================\n# 容器资源限制 (Docker Compose Resource Limits)\n# ==========================================\n# PostgreSQL 数据库\nDB_CPU_LIMIT=1\nDB_MEMORY_LIMIT=1G\n# Redis 缓存\nREDIS_CPU_LIMIT=0.5\nREDIS_MEMORY_LIMIT=512M\n# 后端服务\nBACKEND_CPU_LIMIT=2\nBACKEND_MEMORY_LIMIT=2G\n\n# ==========================================\n# 端到端测试 (E2E Testing)\n# ==========================================\n# 设为 1 时自动初始化 E2E 测试种子数据\nE2E_SEED=0\n\n# ==========================================\n# 冒烟测试配置 (Smoke Test - ikunpay_smoke.py)\n# ==========================================\n# 冒烟测试后端地址\nBACKEND_BASE_URL=http://127.0.0.1:8000\n# 测试用普通用户凭据\nUSER_USERNAME=user1\nUSER_PASSWORD=user123\n# 测试用管理员凭据\nADMIN_USERNAME=admin\nADMIN_PASSWORD=admin123"}, "768fa0056945db7525924df161bc879cc2edeeac": {"t": 1785770471.2830853, "n": 2174, "h": "c1dfce91d192118f", "c": "# ==========================================\n# 百姓法律助手 - 本地开发环境变量模板\n# 使用说明:\n# 1. 复制此文件为 .env:cp .env.example .env\n# 2. 运行密钥生成脚本:bash scripts/generate_secrets.sh\n# 3. 将生成的密钥填入下方对应位置\n# 4. 不要将 .env 文件提交到 Git 仓库\n# ==========================================\n\n# ==========================================\n# 数据库配置 (PostgreSQL)\n# ==========================================\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=dev_password_change_me\nPOSTGRES_DB=baixing_law\n\n# ==========================================\n# 安全配置 (Security)\n# ==========================================\nSECRET_KEY=dev_secret_key_change_me_run_generate_secrets_sh\nJWT_SECRET_KEY=dev_jwt_secret_key_change_me_run_generate_secrets_sh\nPAYMENT_WEBHOOK_SECRET=dev_payment_webhook_secret_change_me\nMETRICS_AUTH_TOKEN=dev_metrics_token_change_me\n\n# ==========================================\n# 缓存与消息队列 (Redis)\n# ==========================================\nREDIS_PASSWORD=dev_redis_password_change_me\n\n# ==========================================\n# 网络与跨域 (Network & CORS)\n# ==========================================\nCORS_ALLOW_ORIGINS=[\"http://localhost:3000\",\"http://localhost:5173\"]\n\n# ==========================================\n# 前端构建配置 (Frontend)\n# ==========================================\nVITE_API_BASE_URL=/api\nVITE_WS_URL=ws://localhost:8000/ws\n\n# ==========================================\n# AI 服务配置 (AI Services)\n# ==========================================\nOPENAI_API_KEY=sk-your-api-key-here\nOPENAI_BASE_URL=https://api.openai.com/v1\nAI_MODEL=deepseek-chat\n\n# ==========================================\n# 监控配置 (Monitoring)\n# ==========================================\nSENTRY_DSN=\nSENTRY_ENVIRONMENT=development\nSENTRY_RELEASE=1.0.0\nSENTRY_TRACES_SAMPLE_RATE=0.1\nSENTRY_PROFILES_SAMPLE_RATE=0.0\nPROMETHEUS_ENABLED=true\nPROMETHEUS_PORT=8001\nGRAFANA_ADMIN_USER=admin\nGRAFANA_ADMIN_PASSWORD=admin123\n\n# ==========================================\n# 环境标识 (Environment)\n# ==========================================\nENVIRONMENT=development\nVERSION=2.0.0\nDEBUG=true\nDB_ALLOW_RUNTIME_DDL=1\nAI_QUALITY_REDIS_ENABLED=true\nAI_QUALITY_REDIS_KEY_PREFIX=ai_quality:\nAI_QUALITY_MAX_RECENT_LOGS=1000\nAI_QUALITY_TTL_SECONDS=604800\n"}}, "docker-compose.dev.yml": {"c1eed528869ea31d43229df00a2aa8d60ec421a2": {"t": 1785747410.5766866, "n": 30655, "h": "678ccfca15e561e6", "c": "# 开发环境 Docker Compose - 包含所有服务,带热重载\n# 使用方式:docker compose -f docker-compose.dev.yml up -d\n\nname: baixing-dev\n\nx-base-logging: &base-logging\n driver: \"json-file\"\n options:\n max-size: \"50m\"\n max-file: \"3\"\n\nx-common-resource-limits: &common-resource-limits\n reservations:\n cpus: \"0.25\"\n memory: 256M\n\nx-backend-logging: &backend-logging\n driver: \"json-file\"\n options:\n max-size: \"100m\"\n max-file: \"5\"\n\nx-microservice-security: &microservice-security\n security_opt:\n - no-new-privileges:true\n cap_drop:\n - ALL\n cap_add:\n - NET_BIND_SERVICE\n\nservices:\n # PostgreSQL数据库\n db:\n image: pgvector/pgvector:pg15\n container_name: baixing_db_dev\n environment:\n POSTGRES_USER: ${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}\n POSTGRES_DB: ${POSTGRES_DB:-baixing_law}\n command: >\n postgres\n -c shared_preload_libraries='vector'\n volumes:\n - postgres_data_dev:/var/lib/postgresql/data\n - ./init-db:/docker-entrypoint-initdb.d\n ports:\n - \"5433:5432\"\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER:-postgres}\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${DB_CPU_LIMIT:-1}\n memory: ${DB_MEMORY_LIMIT:-1G}\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Redis缓存\n redis:\n image: redis:7-alpine\n container_name: baixing_redis_dev\n command: redis-server --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD must be set} --maxmemory 256mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data_dev:/data\n ports:\n - \"16379:6379\"\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD:-redis123}\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${REDIS_CPU_LIMIT:-0.5}\n memory: ${REDIS_MEMORY_LIMIT:-512M}\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Redis指标导出\n redis-exporter:\n image: oliver006/redis_exporter:v1.60.0\n container_name: baixing_redis_exporter_dev\n environment:\n REDIS_ADDR: redis://redis:6379\n REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD must be set}\n command:\n - \"--redis.addr=redis://redis:6379\"\n - \"--redis.password=${REDIS_PASSWORD:?REDIS_PASSWORD must be set}\"\n expose:\n - \"9121\"\n depends_on:\n - redis\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Kafka 事件流平台\n zookeeper:\n image: confluentinc/cp-zookeeper:7.5.0\n container_name: baixing_zookeeper_dev\n environment:\n ZOOKEEPER_CLIENT_PORT: 2181\n ZOOKEEPER_TICK_TIME: 2000\n volumes:\n - zookeeper_data_dev:/var/lib/zookeeper/data\n healthcheck:\n test: [\"CMD-SHELL\", \"echo ruok | nc localhost 2181 | grep imok\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n kafka:\n image: confluentinc/cp-kafka:7.5.0\n container_name: baixing_kafka_dev\n depends_on:\n zookeeper:\n condition: service_healthy\n ports:\n - \"9092:9092\"\n environment:\n KAFKA_BROKER_ID: 1\n KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181\n KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092\n KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT\n KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT\n KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1\n KAFKA_AUTO_CREATE_TOPICS_ENABLE: \"true\"\n KAFKA_LOG_RETENTION_HOURS: 24\n volumes:\n - kafka_data_dev:/var/lib/kafka/data\n healthcheck:\n test: [\"CMD-SHELL\", \"kafka-topics --bootstrap-server localhost:9092 --list\"]\n interval: 15s\n timeout: 10s\n retries: 5\n start_period: 30s\n deploy:\n resources:\n limits:\n cpus: \"1\"\n memory: 1G\n <<: *common-resource-limits\n logging: *backend-logging\n networks:\n - dev-network\n\n kafka-ui:\n image: provectuslabs/kafka-ui:latest\n container_name: baixing_kafka_ui_dev\n depends_on:\n kafka:\n condition: service_healthy\n ports:\n - \"8090:8080\"\n environment:\n KAFKA_CLUSTERS_0_NAME: local\n KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # MinIO 对象存储 (S3 兼容)\n minio:\n image: minio/minio:latest\n container_name: baixing_minio_dev\n command: server /data --console-address \":9001\"\n ports:\n - \"9000:9000\"\n - \"9001:9001\"\n environment:\n MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}\n MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}\n volumes:\n - minio_data_dev:/data\n healthcheck:\n test: [\"CMD\", \"mc\", \"ready\", \"local\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # MinIO 初始化 (创建 bucket)\n minio-init:\n image: minio/mc:latest\n container_name: baixing_minio_init_dev\n depends_on:\n minio:\n condition: service_healthy\n entrypoint: >\n /bin/sh -c \"\n mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin};\n mc mb --ignore-existing local/baixing-uploads;\n mc anonymous set download local/baixing-uploads;\n echo 'Bucket baixing-uploads created';\n \"\n networks:\n - dev-network\n\n # 后端服务\n backend:\n build:\n context: ./backend\n dockerfile: Dockerfile\n container_name: baixing_backend_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/${POSTGRES_DB:-baixing_law}\n JWT_SECRET_KEY: ${JWT_SECRET_KEY}\n JWT_ALGORITHM: ${JWT_ALGORITHM:-HS256}\n CSRF_SECRET_KEY: ${CSRF_SECRET_KEY}\n PAYMENT_WEBHOOK_SECRET: ${PAYMENT_WEBHOOK_SECRET}\n DEBUG: ${DEBUG:-true}\n CORS_ALLOW_ORIGINS: '[\"http://localhost:3000\",\"http://localhost:5173\"]'\n DB_ALLOW_RUNTIME_DDL: \"1\"\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n AI_QUALITY_REDIS_ENABLED: ${AI_QUALITY_REDIS_ENABLED:-true}\n AI_QUALITY_REDIS_KEY_PREFIX: ${AI_QUALITY_REDIS_KEY_PREFIX:-ai_quality:}\n AI_QUALITY_MAX_RECENT_LOGS: ${AI_QUALITY_MAX_RECENT_LOGS:-1000}\n AI_QUALITY_TTL_SECONDS: ${AI_QUALITY_TTL_SECONDS:-604800}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-placeholder}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}\n AI_MODEL: ${AI_MODEL:-deepseek-chat}\n AI_SERVICE_URL: ${AI_SERVICE_URL:-http://ai-service:8005}\n SENTRY_DSN: ${SENTRY_DSN}\n SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-development}\n SENTRY_RELEASE: ${SENTRY_RELEASE:-1.0.0}\n SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}\n SENTRY_PROFILES_SAMPLE_RATE: ${SENTRY_PROFILES_SAMPLE_RATE:-0.0}\n PROMETHEUS_ENABLED: ${PROMETHEUS_ENABLED:-true}\n PROMETHEUS_PORT: ${PROMETHEUS_PORT:-9091}\n METRICS_AUTH_TOKEN: ${METRICS_AUTH_TOKEN}\n ENVIRONMENT: ${ENVIRONMENT:-development}\n VERSION: ${VERSION:-2.0.0}\n STORAGE_PROVIDER: ${STORAGE_PROVIDER:-s3}\n STORAGE_S3_ENDPOINT_URL: http://minio:9000\n STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET:-baixing-uploads}\n STORAGE_S3_REGION: ${STORAGE_S3_REGION:-us-east-1}\n STORAGE_S3_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}\n STORAGE_S3_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin}\n STORAGE_PUBLIC_BASE_URL: http://localhost:9000/baixing-uploads\n STORAGE_S3_PREFIX: uploads\n ports:\n - \"8000:8000\"\n - \"9091:9091\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n minio:\n condition: service_healthy\n volumes:\n - ./backend:/app\n - ./data/sherpa_models:/app/data/sherpa_models:ro\n command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n deploy:\n resources:\n limits:\n cpus: ${BACKEND_CPU_LIMIT:-2}\n memory: ${BACKEND_MEMORY_LIMIT:-2G}\n pids: 200\n reservations:\n cpus: \"1\"\n memory: 512M\n logging: *backend-logging\n networks:\n - dev-network\n\n # Prometheus监控服务\n prometheus:\n image: prom/prometheus:v2.45.0\n container_name: baixing_prometheus_dev\n ports:\n - \"19090:9090\"\n volumes:\n - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - ./prometheus/ai-quality-alerts.yml:/etc/prometheus/ai-quality-alerts.yml:ro\n - ./prometheus/backend-alerts.yml:/etc/prometheus/backend-alerts.yml:ro\n - prometheus_data_dev:/prometheus\n command:\n - \"--config.file=/etc/prometheus/prometheus.yml\"\n - \"--storage.tsdb.path=/prometheus\"\n - \"--storage.tsdb.retention.time=15d\"\n - \"--web.enable-lifecycle\"\n depends_on:\n - backend\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Grafana监控面板\n grafana:\n image: grafana/grafana:10.0.0\n container_name: baixing_grafana_dev\n ports:\n - \"3001:3000\"\n environment:\n - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin}\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin123}\n - GF_DEFAULT_LANGUAGE=zh-Hans\n - GF_USERS_ALLOW_SIGN_UP=false\n volumes:\n - ./grafana/provisioning:/etc/grafana/provisioning:ro\n - ./grafana/dashboards:/etc/grafana/dashboards:ro\n - grafana_data_dev:/var/lib/grafana\n depends_on:\n - prometheus\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Alertmanager告警服务\n alertmanager:\n image: prom/alertmanager:v0.26.0\n container_name: baixing_alertmanager_dev\n ports:\n - \"9200:9093\"\n volumes:\n - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro\n - alertmanager_data_dev:/alertmanager\n command:\n - '--config.file=/etc/alertmanager/alertmanager.yml'\n - '--storage.path=/alertmanager'\n - '--web.external-url=http://localhost:9093'\n depends_on:\n - prometheus\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # 前端服务 (frontend-v2) - 开发模式\n frontend:\n build:\n context: ./frontend-v2\n dockerfile: Dockerfile.dev\n args:\n VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api}\n VITE_WS_URL: ${VITE_WS_URL:-ws://localhost:8000/ws}\n container_name: baixing_frontend_dev\n image: baixing-assistant-frontend-v2:dev\n ports:\n - \"3000:3000\"\n depends_on:\n - backend\n environment:\n - VITE_API_BASE_URL=${VITE_API_BASE_URL:-/api}\n - VITE_WS_URL=${VITE_WS_URL:-ws://localhost:8000/ws}\n - VITE_BACKEND_URL=http://backend:8000\n volumes:\n - ./frontend-v2:/app\n - /app/node_modules\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # ========================================\n # 微服务集群\n # ========================================\n\n # 法律服务 (8008)\n legal-service:\n build:\n context: ./services/legal-service\n dockerfile: Dockerfile\n container_name: baixing_legal_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/legal_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-}\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8008:8008\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/legal-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8008 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8008/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 社区服务 (8007)\n community-service:\n build:\n context: ./services/community-service\n dockerfile: Dockerfile\n container_name: baixing_community_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/community_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8007:8007\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/community-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8007 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8007/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 新闻服务 (8006)\n news-service:\n build:\n context: ./services/news-service\n dockerfile: Dockerfile\n container_name: baixing_news_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/news_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8006:8006\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/news-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8006 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8006/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 搜索服务 (8009)\n search-service:\n build:\n context: ./services/search-service\n dockerfile: Dockerfile\n container_name: baixing_search_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/search_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n NEWS_SERVICE_URL: http://news-service:8006\n COMMUNITY_SERVICE_URL: http://community-service:8007\n LEGAL_SERVICE_URL: http://legal-service:8008\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n DEBUG: \"true\"\n ports:\n - \"8009:8009\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/search-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8009 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8009/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 推荐服务 (8010)\n recommendation-service:\n build:\n context: ./services/recommendation-service\n dockerfile: Dockerfile\n container_name: baixing_recommendation_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/recommendation_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n NEWS_SERVICE_URL: http://news-service:8006\n COMMUNITY_SERVICE_URL: http://community-service:8007\n LEGAL_SERVICE_URL: http://legal-service:8008\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n DEBUG: \"true\"\n ports:\n - \"8010:8010\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/recommendation-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8010 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8010/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 通知服务 (8011)\n notification-service:\n build:\n context: ./services/notification-service\n dockerfile: Dockerfile\n container_name: baixing_notification_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/notification_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8011:8011\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/notification-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8011 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8011/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 用户服务 (8001)\n user-service:\n build:\n context: ./services/user-service\n dockerfile: Dockerfile\n container_name: baixing_user_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/user_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n JWT_SECRET_KEY: ${JWT_SECRET_KEY}\n CONSUL_ENABLED: \"false\"\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8001:8001\"\n - \"50051:50051\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/user-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8001/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 积分服务 (8012)\n points-service:\n build:\n context: ./services/points-service\n dockerfile: Dockerfile\n container_name: baixing_points_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/points_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8012:8012\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/points-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8012 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8012/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 知识库服务 (8081)\n knowledge-service:\n build:\n context: ./services/knowledge-service\n dockerfile: Dockerfile\n container_name: baixing_knowledge_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/knowledge_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8081:8081\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/knowledge-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8081 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8081/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 归档服务 (8013)\n archive-service:\n build:\n context: ./services/archive-service\n dockerfile: Dockerfile\n container_name: baixing_archive_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/archive_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8013:8013\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/archive-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8013 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8013/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 订单服务 (8004)\n order-service:\n build:\n context: ./services/order-service\n dockerfile: Dockerfile\n container_name: baixing_order_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/order_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8004:8004\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/order-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8004 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8004/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # AI 对话服务 (8005)\n ai-service:\n build:\n context: ./services/ai-service\n dockerfile: Dockerfile\n container_name: baixing_ai_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/${POSTGRES_DB:-baixing_law}\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-placeholder}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.deepseek.com/v1}\n AI_MODEL: ${AI_MODEL:-deepseek-chat}\n ENABLE_KAFKA_PRODUCER: \"false\"\n ENABLE_KAFKA_CONSUMER: \"false\"\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n ARCHIVE_SERVICE_URL: http://archive-service:8013\n EMBEDDING_SERVICE_URL: http://embedding-service:8003\n INTERNAL_API_KEY: ${INTERNAL_API_KEY:-dev-internal-api-key}\n USER_SERVICE_URL: http://user-service:8001\n BACKEND_URL: http://backend:8000\n AI_SERVICE_URL: http://ai-service:8005\n VECTOR_STORE_TYPE: chroma\n ports:\n - \"8005:8005\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n volumes:\n - ./services/ai-service:/app\n - ./services/ai-service/data:/app/data\n command: uvicorn app.main:app --host 0.0.0.0 --port 8005 --reload\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8005/health/live\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 向量嵌入服务 (8003)\n embedding-service:\n build:\n context: ./services/embedding-service\n dockerfile: Dockerfile\n container_name: baixing_embedding_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/embedding_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8003:8003\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/embedding-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8003 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8003/health/live', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 支付通道服务 (8002)\n payment-channel-service:\n build:\n context: ./services/payment-channel-service\n dockerfile: Dockerfile\n container_name: baixing_payment_channel_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/payment_channel\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8002:8002\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/payment-channel-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8002/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 账务服务 (8014)\n payment-accounting-service:\n build:\n context: ./services/payment-accounting-service\n dockerfile: Dockerfile\n container_name: baixing_payment_accounting_service_dev\n environment:\n ACCOUNTING_DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/payment_accounting\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/payment_accounting\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8014:8014\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/payment-accounting-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8014 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8014/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\nvolumes:\n postgres_data_dev:\n redis_data_dev:\n prometheus_data_dev:\n grafana_data_dev:\n alertmanager_data_dev:\n zookeeper_data_dev:\n kafka_data_dev:\n minio_data_dev:\n schemathesis_results_dev:\n driver: local\n etcd_data_dev:\n driver: local\n\nnetworks:\n dev-network:\n driver: bridge"}, "cdcd065d5d5cfd41685ef66a05e0e7b622f28b79": {"t": 1785770472.2996166, "n": 30655, "h": "678ccfca15e561e6", "c": "# 开发环境 Docker Compose - 包含所有服务,带热重载\n# 使用方式:docker compose -f docker-compose.dev.yml up -d\n\nname: baixing-dev\n\nx-base-logging: &base-logging\n driver: \"json-file\"\n options:\n max-size: \"50m\"\n max-file: \"3\"\n\nx-common-resource-limits: &common-resource-limits\n reservations:\n cpus: \"0.25\"\n memory: 256M\n\nx-backend-logging: &backend-logging\n driver: \"json-file\"\n options:\n max-size: \"100m\"\n max-file: \"5\"\n\nx-microservice-security: &microservice-security\n security_opt:\n - no-new-privileges:true\n cap_drop:\n - ALL\n cap_add:\n - NET_BIND_SERVICE\n\nservices:\n # PostgreSQL数据库\n db:\n image: pgvector/pgvector:pg15\n container_name: baixing_db_dev\n environment:\n POSTGRES_USER: ${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}\n POSTGRES_DB: ${POSTGRES_DB:-baixing_law}\n command: >\n postgres\n -c shared_preload_libraries='vector'\n volumes:\n - postgres_data_dev:/var/lib/postgresql/data\n - ./init-db:/docker-entrypoint-initdb.d\n ports:\n - \"5433:5432\"\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER:-postgres}\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${DB_CPU_LIMIT:-1}\n memory: ${DB_MEMORY_LIMIT:-1G}\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Redis缓存\n redis:\n image: redis:7-alpine\n container_name: baixing_redis_dev\n command: redis-server --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD must be set} --maxmemory 256mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data_dev:/data\n ports:\n - \"16379:6379\"\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD:-redis123}\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${REDIS_CPU_LIMIT:-0.5}\n memory: ${REDIS_MEMORY_LIMIT:-512M}\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Redis指标导出\n redis-exporter:\n image: oliver006/redis_exporter:v1.60.0\n container_name: baixing_redis_exporter_dev\n environment:\n REDIS_ADDR: redis://redis:6379\n REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD must be set}\n command:\n - \"--redis.addr=redis://redis:6379\"\n - \"--redis.password=${REDIS_PASSWORD:?REDIS_PASSWORD must be set}\"\n expose:\n - \"9121\"\n depends_on:\n - redis\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Kafka 事件流平台\n zookeeper:\n image: confluentinc/cp-zookeeper:7.5.0\n container_name: baixing_zookeeper_dev\n environment:\n ZOOKEEPER_CLIENT_PORT: 2181\n ZOOKEEPER_TICK_TIME: 2000\n volumes:\n - zookeeper_data_dev:/var/lib/zookeeper/data\n healthcheck:\n test: [\"CMD-SHELL\", \"echo ruok | nc localhost 2181 | grep imok\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n kafka:\n image: confluentinc/cp-kafka:7.5.0\n container_name: baixing_kafka_dev\n depends_on:\n zookeeper:\n condition: service_healthy\n ports:\n - \"9092:9092\"\n environment:\n KAFKA_BROKER_ID: 1\n KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181\n KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092\n KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT\n KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT\n KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1\n KAFKA_AUTO_CREATE_TOPICS_ENABLE: \"true\"\n KAFKA_LOG_RETENTION_HOURS: 24\n volumes:\n - kafka_data_dev:/var/lib/kafka/data\n healthcheck:\n test: [\"CMD-SHELL\", \"kafka-topics --bootstrap-server localhost:9092 --list\"]\n interval: 15s\n timeout: 10s\n retries: 5\n start_period: 30s\n deploy:\n resources:\n limits:\n cpus: \"1\"\n memory: 1G\n <<: *common-resource-limits\n logging: *backend-logging\n networks:\n - dev-network\n\n kafka-ui:\n image: provectuslabs/kafka-ui:latest\n container_name: baixing_kafka_ui_dev\n depends_on:\n kafka:\n condition: service_healthy\n ports:\n - \"8090:8080\"\n environment:\n KAFKA_CLUSTERS_0_NAME: local\n KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # MinIO 对象存储 (S3 兼容)\n minio:\n image: minio/minio:latest\n container_name: baixing_minio_dev\n command: server /data --console-address \":9001\"\n ports:\n - \"9000:9000\"\n - \"9001:9001\"\n environment:\n MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}\n MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}\n volumes:\n - minio_data_dev:/data\n healthcheck:\n test: [\"CMD\", \"mc\", \"ready\", \"local\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # MinIO 初始化 (创建 bucket)\n minio-init:\n image: minio/mc:latest\n container_name: baixing_minio_init_dev\n depends_on:\n minio:\n condition: service_healthy\n entrypoint: >\n /bin/sh -c \"\n mc alias set local http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin};\n mc mb --ignore-existing local/baixing-uploads;\n mc anonymous set download local/baixing-uploads;\n echo 'Bucket baixing-uploads created';\n \"\n networks:\n - dev-network\n\n # 后端服务\n backend:\n build:\n context: ./backend\n dockerfile: Dockerfile\n container_name: baixing_backend_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/${POSTGRES_DB:-baixing_law}\n JWT_SECRET_KEY: ${JWT_SECRET_KEY}\n JWT_ALGORITHM: ${JWT_ALGORITHM:-HS256}\n CSRF_SECRET_KEY: ${CSRF_SECRET_KEY}\n PAYMENT_WEBHOOK_SECRET: ${PAYMENT_WEBHOOK_SECRET}\n DEBUG: ${DEBUG:-true}\n CORS_ALLOW_ORIGINS: '[\"http://localhost:3000\",\"http://localhost:5173\"]'\n DB_ALLOW_RUNTIME_DDL: \"1\"\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n AI_QUALITY_REDIS_ENABLED: ${AI_QUALITY_REDIS_ENABLED:-true}\n AI_QUALITY_REDIS_KEY_PREFIX: ${AI_QUALITY_REDIS_KEY_PREFIX:-ai_quality:}\n AI_QUALITY_MAX_RECENT_LOGS: ${AI_QUALITY_MAX_RECENT_LOGS:-1000}\n AI_QUALITY_TTL_SECONDS: ${AI_QUALITY_TTL_SECONDS:-604800}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-placeholder}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}\n AI_MODEL: ${AI_MODEL:-deepseek-chat}\n AI_SERVICE_URL: ${AI_SERVICE_URL:-http://ai-service:8005}\n SENTRY_DSN: ${SENTRY_DSN}\n SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-development}\n SENTRY_RELEASE: ${SENTRY_RELEASE:-1.0.0}\n SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}\n SENTRY_PROFILES_SAMPLE_RATE: ${SENTRY_PROFILES_SAMPLE_RATE:-0.0}\n PROMETHEUS_ENABLED: ${PROMETHEUS_ENABLED:-true}\n PROMETHEUS_PORT: ${PROMETHEUS_PORT:-9091}\n METRICS_AUTH_TOKEN: ${METRICS_AUTH_TOKEN}\n ENVIRONMENT: ${ENVIRONMENT:-development}\n VERSION: ${VERSION:-2.0.0}\n STORAGE_PROVIDER: ${STORAGE_PROVIDER:-s3}\n STORAGE_S3_ENDPOINT_URL: http://minio:9000\n STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET:-baixing-uploads}\n STORAGE_S3_REGION: ${STORAGE_S3_REGION:-us-east-1}\n STORAGE_S3_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}\n STORAGE_S3_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin}\n STORAGE_PUBLIC_BASE_URL: http://localhost:9000/baixing-uploads\n STORAGE_S3_PREFIX: uploads\n ports:\n - \"8000:8000\"\n - \"9091:9091\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n minio:\n condition: service_healthy\n volumes:\n - ./backend:/app\n - ./data/sherpa_models:/app/data/sherpa_models:ro\n command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n deploy:\n resources:\n limits:\n cpus: ${BACKEND_CPU_LIMIT:-2}\n memory: ${BACKEND_MEMORY_LIMIT:-2G}\n pids: 200\n reservations:\n cpus: \"1\"\n memory: 512M\n logging: *backend-logging\n networks:\n - dev-network\n\n # Prometheus监控服务\n prometheus:\n image: prom/prometheus:v2.45.0\n container_name: baixing_prometheus_dev\n ports:\n - \"19090:9090\"\n volumes:\n - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro\n - ./prometheus/ai-quality-alerts.yml:/etc/prometheus/ai-quality-alerts.yml:ro\n - ./prometheus/backend-alerts.yml:/etc/prometheus/backend-alerts.yml:ro\n - prometheus_data_dev:/prometheus\n command:\n - \"--config.file=/etc/prometheus/prometheus.yml\"\n - \"--storage.tsdb.path=/prometheus\"\n - \"--storage.tsdb.retention.time=15d\"\n - \"--web.enable-lifecycle\"\n depends_on:\n - backend\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Grafana监控面板\n grafana:\n image: grafana/grafana:10.0.0\n container_name: baixing_grafana_dev\n ports:\n - \"3001:3000\"\n environment:\n - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin}\n - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin123}\n - GF_DEFAULT_LANGUAGE=zh-Hans\n - GF_USERS_ALLOW_SIGN_UP=false\n volumes:\n - ./grafana/provisioning:/etc/grafana/provisioning:ro\n - ./grafana/dashboards:/etc/grafana/dashboards:ro\n - grafana_data_dev:/var/lib/grafana\n depends_on:\n - prometheus\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 100\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Alertmanager告警服务\n alertmanager:\n image: prom/alertmanager:v0.26.0\n container_name: baixing_alertmanager_dev\n ports:\n - \"9200:9093\"\n volumes:\n - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro\n - alertmanager_data_dev:/alertmanager\n command:\n - '--config.file=/etc/alertmanager/alertmanager.yml'\n - '--storage.path=/alertmanager'\n - '--web.external-url=http://localhost:9093'\n depends_on:\n - prometheus\n deploy:\n resources:\n limits:\n cpus: \"0.25\"\n memory: 256M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # 前端服务 (frontend-v2) - 开发模式\n frontend:\n build:\n context: ./frontend-v2\n dockerfile: Dockerfile.dev\n args:\n VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api}\n VITE_WS_URL: ${VITE_WS_URL:-ws://localhost:8000/ws}\n container_name: baixing_frontend_dev\n image: baixing-assistant-frontend-v2:dev\n ports:\n - \"3000:3000\"\n depends_on:\n - backend\n environment:\n - VITE_API_BASE_URL=${VITE_API_BASE_URL:-/api}\n - VITE_WS_URL=${VITE_WS_URL:-ws://localhost:8000/ws}\n - VITE_BACKEND_URL=http://backend:8000\n volumes:\n - ./frontend-v2:/app\n - /app/node_modules\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n pids: 50\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # ========================================\n # 微服务集群\n # ========================================\n\n # 法律服务 (8008)\n legal-service:\n build:\n context: ./services/legal-service\n dockerfile: Dockerfile\n container_name: baixing_legal_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/legal_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-}\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8008:8008\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/legal-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8008 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8008/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 社区服务 (8007)\n community-service:\n build:\n context: ./services/community-service\n dockerfile: Dockerfile\n container_name: baixing_community_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/community_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8007:8007\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/community-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8007 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8007/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 新闻服务 (8006)\n news-service:\n build:\n context: ./services/news-service\n dockerfile: Dockerfile\n container_name: baixing_news_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/news_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8006:8006\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/news-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8006 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8006/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 搜索服务 (8009)\n search-service:\n build:\n context: ./services/search-service\n dockerfile: Dockerfile\n container_name: baixing_search_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/search_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n NEWS_SERVICE_URL: http://news-service:8006\n COMMUNITY_SERVICE_URL: http://community-service:8007\n LEGAL_SERVICE_URL: http://legal-service:8008\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n DEBUG: \"true\"\n ports:\n - \"8009:8009\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/search-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8009 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8009/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 推荐服务 (8010)\n recommendation-service:\n build:\n context: ./services/recommendation-service\n dockerfile: Dockerfile\n container_name: baixing_recommendation_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/recommendation_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n NEWS_SERVICE_URL: http://news-service:8006\n COMMUNITY_SERVICE_URL: http://community-service:8007\n LEGAL_SERVICE_URL: http://legal-service:8008\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n DEBUG: \"true\"\n ports:\n - \"8010:8010\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/recommendation-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8010 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8010/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 通知服务 (8011)\n notification-service:\n build:\n context: ./services/notification-service\n dockerfile: Dockerfile\n container_name: baixing_notification_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/notification_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8011:8011\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/notification-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8011 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8011/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 用户服务 (8001)\n user-service:\n build:\n context: ./services/user-service\n dockerfile: Dockerfile\n container_name: baixing_user_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/user_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n JWT_SECRET_KEY: ${JWT_SECRET_KEY}\n CONSUL_ENABLED: \"false\"\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8001:8001\"\n - \"50051:50051\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/user-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8001/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 积分服务 (8012)\n points-service:\n build:\n context: ./services/points-service\n dockerfile: Dockerfile\n container_name: baixing_points_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/points_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8012:8012\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/points-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8012 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8012/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 知识库服务 (8081)\n knowledge-service:\n build:\n context: ./services/knowledge-service\n dockerfile: Dockerfile\n container_name: baixing_knowledge_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/knowledge_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8081:8081\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/knowledge-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8081 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8081/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 归档服务 (8013)\n archive-service:\n build:\n context: ./services/archive-service\n dockerfile: Dockerfile\n container_name: baixing_archive_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/archive_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8013:8013\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/archive-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8013 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8013/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 订单服务 (8004)\n order-service:\n build:\n context: ./services/order-service\n dockerfile: Dockerfile\n container_name: baixing_order_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/order_service\n REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8004:8004\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/order-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8004 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8004/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # AI 对话服务 (8005)\n ai-service:\n build:\n context: ./services/ai-service\n dockerfile: Dockerfile\n container_name: baixing_ai_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/${POSTGRES_DB:-baixing_law}\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-placeholder}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.deepseek.com/v1}\n AI_MODEL: ${AI_MODEL:-deepseek-chat}\n ENABLE_KAFKA_PRODUCER: \"false\"\n ENABLE_KAFKA_CONSUMER: \"false\"\n KNOWLEDGE_SERVICE_URL: http://knowledge-service:8081\n ARCHIVE_SERVICE_URL: http://archive-service:8013\n EMBEDDING_SERVICE_URL: http://embedding-service:8003\n INTERNAL_API_KEY: ${INTERNAL_API_KEY:-dev-internal-api-key}\n USER_SERVICE_URL: http://user-service:8001\n BACKEND_URL: http://backend:8000\n AI_SERVICE_URL: http://ai-service:8005\n VECTOR_STORE_TYPE: chroma\n ports:\n - \"8005:8005\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n volumes:\n - ./services/ai-service:/app\n - ./services/ai-service/data:/app/data\n command: uvicorn app.main:app --host 0.0.0.0 --port 8005 --reload\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8005/health/live\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 向量嵌入服务 (8003)\n embedding-service:\n build:\n context: ./services/embedding-service\n dockerfile: Dockerfile\n container_name: baixing_embedding_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/embedding_service\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8003:8003\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/embedding-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8003 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8003/health/live', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 支付通道服务 (8002)\n payment-channel-service:\n build:\n context: ./services/payment-channel-service\n dockerfile: Dockerfile\n container_name: baixing_payment_channel_service_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@db:5432/payment_channel\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8002:8002\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/payment-channel-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8002/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\n # 账务服务 (8014)\n payment-accounting-service:\n build:\n context: ./services/payment-accounting-service\n dockerfile: Dockerfile\n container_name: baixing_payment_accounting_service_dev\n environment:\n ACCOUNTING_DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/payment_accounting\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/payment_accounting\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n KAFKA_ENABLED: \"true\"\n KAFKA_BOOTSTRAP_SERVERS: kafka:29092\n DEBUG: \"true\"\n ports:\n - \"8014:8014\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n kafka:\n condition: service_healthy\n volumes:\n - ./services/payment-accounting-service:/app\n command: uvicorn app.main:app --host 0.0.0.0 --port 8014 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8014/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n <<: *microservice-security\n logging: *base-logging\n networks:\n - dev-network\n\nvolumes:\n postgres_data_dev:\n redis_data_dev:\n prometheus_data_dev:\n grafana_data_dev:\n alertmanager_data_dev:\n zookeeper_data_dev:\n kafka_data_dev:\n minio_data_dev:\n schemathesis_results_dev:\n driver: local\n etcd_data_dev:\n driver: local\n\nnetworks:\n dev-network:\n driver: bridge"}, "768fa0056945db7525924df161bc879cc2edeeac": {"t": 1785770473.60615, "n": 5126, "h": "68f53b052e5f12d7", "c": "# 开发环境 Docker Compose - 仅包含核心服务\n# 使用方式:docker compose -f docker-compose.dev.yml up -d\n# \n# 完整微服务集群请使用:docker compose -f docker-compose.yml up -d\n\nname: baixing-dev\n\nx-base-logging: &base-logging\n driver: \"json-file\"\n options:\n max-size: \"50m\"\n max-file: \"3\"\n\nx-common-resource-limits: &common-resource-limits\n reservations:\n cpus: \"0.25\"\n memory: 256M\n\nx-backend-logging: &backend-logging\n driver: \"json-file\"\n options:\n max-size: \"100m\"\n max-file: \"5\"\n\nservices:\n # PostgreSQL数据库\n db:\n image: postgres:15-alpine\n container_name: baixing_db_dev\n environment:\n POSTGRES_USER: ${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}\n POSTGRES_DB: ${POSTGRES_DB:-baixing_law}\n volumes:\n - postgres_data_dev:/var/lib/postgresql/data\n ports:\n - \"5433:5432\"\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER:-postgres}\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${DB_CPU_LIMIT:-1}\n memory: ${DB_MEMORY_LIMIT:-1G}\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # Redis缓存\n redis:\n image: redis:7-alpine\n container_name: baixing_redis_dev\n command: redis-server --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD must be set} --maxmemory 256mb --maxmemory-policy allkeys-lru\n volumes:\n - redis_data_dev:/data\n ports:\n - \"16379:6379\"\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD:-redis123}\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n deploy:\n resources:\n limits:\n cpus: ${REDIS_CPU_LIMIT:-0.5}\n memory: ${REDIS_MEMORY_LIMIT:-512M}\n <<: *common-resource-limits\n logging: *base-logging\n networks:\n - dev-network\n\n # 后端服务\n backend:\n build:\n context: ./backend\n dockerfile: Dockerfile\n container_name: baixing_backend_dev\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}@db:5432/${POSTGRES_DB:-baixing_law}\n JWT_SECRET_KEY: ${JWT_SECRET_KEY}\n JWT_ALGORITHM: ${JWT_ALGORITHM:-HS256}\n CSRF_SECRET_KEY: ${CSRF_SECRET_KEY}\n PAYMENT_WEBHOOK_SECRET: ${PAYMENT_WEBHOOK_SECRET}\n DEBUG: ${DEBUG:-true}\n CORS_ALLOW_ORIGINS: '[\"http://localhost:3000\",\"http://localhost:5173\"]'\n DB_ALLOW_RUNTIME_DDL: \"1\"\n REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD must be set}@redis:6379/0\n AI_QUALITY_REDIS_ENABLED: ${AI_QUALITY_REDIS_ENABLED:-true}\n AI_QUALITY_REDIS_KEY_PREFIX: ${AI_QUALITY_REDIS_KEY_PREFIX:-ai_quality:}\n AI_QUALITY_MAX_RECENT_LOGS: ${AI_QUALITY_MAX_RECENT_LOGS:-1000}\n AI_QUALITY_TTL_SECONDS: ${AI_QUALITY_TTL_SECONDS:-604800}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-placeholder}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}\n AI_MODEL: ${AI_MODEL:-deepseek-chat}\n SENTRY_DSN: ${SENTRY_DSN}\n SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-development}\n SENTRY_RELEASE: ${SENTRY_RELEASE:-1.0.0}\n SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}\n SENTRY_PROFILES_SAMPLE_RATE: ${SENTRY_PROFILES_SAMPLE_RATE:-0.0}\n PROMETHEUS_ENABLED: ${PROMETHEUS_ENABLED:-true}\n PROMETHEUS_PORT: ${PROMETHEUS_PORT:-8001}\n METRICS_AUTH_TOKEN: ${METRICS_AUTH_TOKEN}\n ENVIRONMENT: ${ENVIRONMENT:-development}\n VERSION: ${VERSION:-2.0.0}\n ports:\n - \"8000:8000\"\n - \"8001:8001\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n volumes:\n - ./backend:/app\n - ./data/sherpa_models:/app/data/sherpa_models:ro\n command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n deploy:\n resources:\n limits:\n cpus: ${BACKEND_CPU_LIMIT:-2}\n memory: ${BACKEND_MEMORY_LIMIT:-2G}\n logging: *backend-logging\n networks:\n - dev-network\n\n # 前端服务 (frontend-v2) - 开发模式\n frontend:\n build:\n context: ./frontend-v2\n dockerfile: Dockerfile.dev\n args:\n VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api}\n VITE_WS_URL: ${VITE_WS_URL:-ws://localhost:8000/ws}\n container_name: baixing_frontend_dev\n image: baixing-assistant-frontend-v2:dev\n ports:\n - \"3000:3000\"\n depends_on:\n - backend\n environment:\n - VITE_API_BASE_URL=${VITE_API_BASE_URL:-/api}\n - VITE_WS_URL=${VITE_WS_URL:-ws://localhost:8000/ws}\n volumes:\n - ./frontend-v2:/app\n - /app/node_modules\n deploy:\n resources:\n limits:\n cpus: \"0.5\"\n memory: 512M\n logging: *base-logging\n networks:\n - dev-network\n\nvolumes:\n postgres_data_dev:\n redis_data_dev:\n\nnetworks:\n dev-network:\n driver: bridge\n"}, "7c84bd070b1a7a3e5bc6d6de5704bd429e733638": {"t": 1785770474.879327, "n": 3354, "h": "86feb79c23cd34aa", "c": "# ============================================\n# 开发环境 Docker Compose\n# 简化版 - 用于本地开发测试\n# ============================================\n\nname: baixing-dev\n\nservices:\n # PostgreSQL数据库\n db:\n image: postgres:15-alpine\n container_name: baixing_dev_db\n environment:\n POSTGRES_USER: ${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-baixing_dev_2024}\n POSTGRES_DB: ${POSTGRES_DB:-baixing_law}\n POSTGRES_HOST_AUTH_METHOD: trust\n volumes:\n - baixing_dev_postgres:/var/lib/postgresql/data\n ports:\n - \"5433:5432\"\n networks:\n - baixing-dev-backend-network\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER:-postgres}\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n # Redis缓存\n redis:\n image: redis:7-alpine\n container_name: baixing_dev_redis\n command: redis-server --requirepass ${REDIS_PASSWORD:-baixing_redis_2024} --maxmemory 256mb\n volumes:\n - baixing_dev_redis:/data\n ports:\n - \"16379:6379\"\n networks:\n - baixing-dev-backend-network\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD:-baixing_redis_2024}\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n # 后端服务\n backend:\n image: baixing-dev-backend:latest\n container_name: baixing_dev_backend\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-baixing_dev_2024}@db:5432/${POSTGRES_DB:-baixing_law}\n PGSSLMODE: disable\n SECRET_KEY: ${JWT_SECRET_KEY:-dev-jwt-secret-key-for-local-testing-only-32chars}\n ALGORITHM: HS256\n DEBUG: \"true\"\n REDIS_URL: redis://:${REDIS_PASSWORD:-baixing_redis_2024}@redis:6379/0\n CSRF_SECRET_KEY: ${CSRF_SECRET_KEY:-dev-csrf-secret-key-for-local-testing-32chars}\n PAYMENT_WEBHOOK_SECRET: ${PAYMENT_WEBHOOK_SECRET:-dev-webhook-secret}\n METRICS_AUTH_TOKEN: ${METRICS_AUTH_TOKEN:-dev-metrics-token}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}\n AI_MODEL: ${AI_MODEL:-gpt-3.5-turbo}\n ENVIRONMENT: development\n # CORS 配置 - JSON格式\n CORS_ALLOW_ORIGINS: '[\"http://localhost:3000\",\"http://localhost:5173\",\"http://127.0.0.1:3000\"]'\n ports:\n - \"8000:8000\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n # volumes:\n # - baixing_dev_uploads:/app/uploads\n networks:\n - baixing-dev-backend-network\n command: uvicorn app.main:app --host 0.0.0.0 --port 8000\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n\n # 前端服务\n frontend:\n build:\n context: ./frontend-v2\n dockerfile: Dockerfile\n args:\n VITE_API_BASE_URL: /api\n VITE_WS_URL: ws://backend:8000/ws\n container_name: baixing_dev_frontend\n ports:\n - \"3000:3000\"\n depends_on:\n - backend\n environment:\n - VITE_API_BASE_URL=/api\n - VITE_WS_URL=ws://backend:8000/ws\n networks:\n - baixing-dev-backend-network\n\nnetworks:\n baixing-dev-backend-network:\n driver: bridge\n\nvolumes:\n baixing_dev_postgres:\n baixing_dev_redis:\n baixing_dev_uploads:\n"}, "e1fd979256f946ead0bec92d70d342ad58e37b1b": {"t": 1785770476.0743432, "n": 2983, "h": "f97573c833582d1f", "c": "# ============================================\n# 开发环境 Docker Compose\n# 简化版 - 用于本地开发测试\n# ============================================\n\nname: baixing-dev\n\nservices:\n # PostgreSQL数据库\n db:\n image: postgres:15-alpine\n container_name: baixing_dev_db\n environment:\n POSTGRES_USER: ${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-baixing_dev_2024}\n POSTGRES_DB: ${POSTGRES_DB:-baixing_law}\n volumes:\n - baixing_dev_postgres:/var/lib/postgresql/data\n ports:\n - \"5433:5432\"\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER:-postgres}\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n # Redis缓存\n redis:\n image: redis:7-alpine\n container_name: baixing_dev_redis\n command: redis-server --requirepass ${REDIS_PASSWORD:-baixing_redis_2024} --maxmemory 256mb\n volumes:\n - baixing_dev_redis:/data\n ports:\n - \"16379:6379\"\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"-a\", \"${REDIS_PASSWORD:-baixing_redis_2024}\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n\n # 后端服务\n backend:\n image: baixing-dev-backend:latest\n container_name: baixing_dev_backend\n environment:\n DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-baixing_dev_2024}@db:5432/${POSTGRES_DB:-baixing_law}\n SECRET_KEY: ${JWT_SECRET_KEY:-dev-jwt-secret-key-for-local-testing-only-32chars}\n ALGORITHM: HS256\n DEBUG: \"true\"\n REDIS_URL: redis://:${REDIS_PASSWORD:-baixing_redis_2024}@redis:6379/0\n CSRF_SECRET_KEY: ${CSRF_SECRET_KEY:-dev-csrf-secret-key-for-local-testing-32chars}\n PAYMENT_WEBHOOK_SECRET: ${PAYMENT_WEBHOOK_SECRET:-dev-webhook-secret}\n METRICS_AUTH_TOKEN: ${METRICS_AUTH_TOKEN:-dev-metrics-token}\n OPENAI_API_KEY: ${OPENAI_API_KEY:-}\n OPENAI_BASE_URL: ${OPENAI_BASE_URL:-https://api.openai.com/v1}\n AI_MODEL: ${AI_MODEL:-gpt-3.5-turbo}\n ENVIRONMENT: development\n # CORS 配置 - JSON格式\n CORS_ALLOW_ORIGINS: '[\"http://localhost:3000\",\"http://localhost:5173\",\"http://127.0.0.1:3000\"]'\n ports:\n - \"8000:8000\"\n depends_on:\n db:\n condition: service_healthy\n redis:\n condition: service_healthy\n volumes:\n - baixing_dev_uploads:/app/uploads\n command: uvicorn app.main:app --host 0.0.0.0 --port 8000\n healthcheck:\n test: [\"CMD\", \"python\", \"-c\", \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"]\n interval: 30s\n timeout: 10s\n retries: 3\n start_period: 40s\n\n # 前端服务 (可选 - 网络问题时可本地运行)\n # frontend:\n # build:\n # context: ./frontend-v2\n # dockerfile: Dockerfile\n # container_name: baixing_dev_frontend\n # ports:\n # - \"3000:3000\"\n # depends_on:\n # - backend\n # environment:\n # - VITE_API_BASE_URL=/api\n # - VITE_WS_URL=ws://localhost:8000/ws\n\nvolumes:\n baixing_dev_postgres:\n baixing_dev_redis:\n baixing_dev_uploads:\n"}}}}