chore: bootstrap repo tooling, dependency and quality gates
uv-managed PEP 621 project with ruff, mypy (strict on packages/domain and packages/llm), pytest with coverage, and import-linter contracts that mechanically enforce the dependency rules of 架构文档 §4.2 -- including the two forbidden edges (compliance and identity must not depend on business domains). CI, pre-commit and a detect-secrets baseline gate every push; .env is gitignored before anything is ever staged.
This commit is contained in:
Executable
+85
@@ -0,0 +1,85 @@
|
||||
# =============================================================================
|
||||
# 美搭 backend — environment template
|
||||
# =============================================================================
|
||||
# Copy to `.env` and fill in real values. `.env` is git-ignored and MUST NEVER
|
||||
# be committed (架构文档 §11.2: 密钥全部走 SSM/KMS,禁止进代码与镜像).
|
||||
# In dev/staging/prod these variables are injected by SSM/KMS, not by a file.
|
||||
# Every variable below is documented; NO real values appear in this file.
|
||||
# =============================================================================
|
||||
|
||||
# --- Application ------------------------------------------------------------
|
||||
APP_ENV=local # local | dev | staging | prod (架构文档 §14.2)
|
||||
APP_NAME=meida-backend
|
||||
API_PREFIX=/api/v1 # 架构文档 §9.1 基础路径;/v1/* 作为别名同样可用
|
||||
DEBUG=true
|
||||
LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
|
||||
LOG_JSON=true # false => human-readable console renderer
|
||||
|
||||
# --- Database (PostgreSQL 16 + pgvector) ------------------------------------
|
||||
# Async driver is required (SQLAlchemy 2.0 asyncio + asyncpg).
|
||||
DATABASE_URL=postgresql+asyncpg://meida:meida@localhost:55432/meida
|
||||
DB_POOL_SIZE=10
|
||||
DB_MAX_OVERFLOW=20
|
||||
DB_ECHO=false
|
||||
|
||||
# --- Redis 7 (cache / quota counters / celery broker) -----------------------
|
||||
REDIS_URL=redis://localhost:56379/0
|
||||
CELERY_BROKER_URL=redis://localhost:56379/1
|
||||
CELERY_RESULT_BACKEND=redis://localhost:56379/2
|
||||
|
||||
# --- Auth (架构文档 §9.1: JWT access 15min + 可撤销 refresh) ----------------
|
||||
JWT_SECRET= # REQUIRED. >=32 random chars. Generate: openssl rand -hex 32
|
||||
JWT_ALGORITHM=HS256
|
||||
JWT_ACCESS_TTL_SECONDS=900 # 15 minutes
|
||||
JWT_ISSUER=meida
|
||||
DEV_AUTH_ENABLED=true # MUST be false outside local/dev: enables POST /auth/dev-token
|
||||
|
||||
# --- LLM gateway: routing (架构文档 §8.1) -----------------------------------
|
||||
LLM_PRIMARY_PROVIDER=deepseek # DeepSeek 为主 (TD-04)
|
||||
LLM_BACKUP_PROVIDER=zhipu # 智谱 GLM 为备(V1 未实现,仅结构占位)
|
||||
LLM_STRUCTURED_MAX_RETRIES=2 # 结构化输出校验失败的重试次数
|
||||
LLM_CIRCUIT_FAILURE_THRESHOLD=3 # 连续失败达到该值即熔断
|
||||
LLM_CIRCUIT_COOLDOWN_SECONDS=30 # 熔断冷却时长,之后半开探测
|
||||
# JSON 值一律用单引号包住:scripts/smoke.sh 会 `source .env`,
|
||||
# 裸的双引号会被 bash 剥掉,JSON 就此损坏。
|
||||
LLM_SCENE_OVERRIDES_JSON='{}' # 场景路由覆盖,JSON: {"agent_chat":{"max_tokens":900}}
|
||||
|
||||
# --- LLM gateway: DeepSeek (OpenAI-compatible) ------------------------------
|
||||
DEEPSEEK_API_KEY= # REQUIRED. sk-... Never commit.
|
||||
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
|
||||
DEEPSEEK_MODEL=deepseek-v4-flash # 默认模型,可用: deepseek-v4-flash / deepseek-v4-pro
|
||||
DEEPSEEK_TIMEOUT_SECONDS=30
|
||||
|
||||
# --- LLM gateway: 智谱 GLM (backup, not implemented in V1) ------------------
|
||||
ZHIPU_API_KEY=
|
||||
ZHIPU_BASE_URL=https://open.bigmodel.cn/api/paas/v4
|
||||
ZHIPU_MODEL=glm-4-flash
|
||||
ZHIPU_TIMEOUT_SECONDS=30
|
||||
|
||||
# --- LLM gateway: prompt caching discipline (架构文档 §7.2 缓存前缀纪律) ----
|
||||
# strict => 固定前缀含时间戳/随机ID/昵称时直接拒绝调用
|
||||
# warn => 只记录告警日志;off => 关闭(不建议)
|
||||
LLM_CACHE_PREFIX_MODE=strict
|
||||
PROMPTS_DIR=prompts
|
||||
|
||||
# --- LLM gateway: 成本归因与费率 (架构文档 §13, FR-BILL-08) -----------------
|
||||
# 单位:分/百万 token(cents per 1M tokens)。上线前必须以供应商实际价目表校准。
|
||||
LLM_COST_RATES_JSON='{"deepseek-v4-flash":{"input_cents_per_mtok":"14","cached_input_cents_per_mtok":"2","output_cents_per_mtok":"28"},"deepseek-v4-pro":{"input_cents_per_mtok":"200","cached_input_cents_per_mtok":"20","output_cents_per_mtok":"800"}}'
|
||||
LLM_DEFAULT_COST_RATE_JSON='{"input_cents_per_mtok":"100","cached_input_cents_per_mtok":"20","output_cents_per_mtok":"200"}'
|
||||
|
||||
# --- LLM gateway: 全局日成本熔断 (架构文档 §13 三道成本闸门) ----------------
|
||||
# 达到阈值后,非关键场景的 AI 调用被直接拒绝/降级,而不仅仅是告警。
|
||||
LLM_DAILY_BUDGET_ENABLED=true
|
||||
LLM_DAILY_BUDGET_CENTS=100000 # 1000 元/天
|
||||
LLM_BUDGET_TIMEZONE_OFFSET_HOURS=8 # 结算日按 UTC+8 (FR-BILL-01)
|
||||
|
||||
# --- Observability (架构文档 §15) -------------------------------------------
|
||||
OTEL_ENABLED=false
|
||||
OTEL_SERVICE_NAME=meida-api
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT= # e.g. http://localhost:4318
|
||||
PROMETHEUS_ENABLED=true
|
||||
|
||||
# --- Logging redaction (NFR-SEC-03) -----------------------------------------
|
||||
# Extra log field names to redact, comma separated. Built-in list already covers
|
||||
# phone / token / union_id / open_id / avatar_key / face image keys / diagnosis.
|
||||
LOG_EXTRA_REDACT_KEYS=
|
||||
Reference in New Issue
Block a user