DATABASE_URL=postgres://postgres:postgres@localhost:5432/yggdrasil

# tracing 日志过滤器。支持逗号分隔的细粒度语法，例如：
#   RUST_LOG=info                        全局 info 级
#   RUST_LOG=info,yggdrasil=debug        本项目 debug，其余 info
#   RUST_LOG=warn,hyper=warn,sqlx=warn   降噪第三方库
# 不设时默认 info（见 main.rs）。
RUST_LOG=info

# ─────────────────────────────────────────────────────────────
# Rate Limit 限流配置
#
# 采用 token bucket（令牌桶）模型：
#   PER_SEC = 稳态补充速率（每秒补充的令牌数）
#   BURST   = 桶容量（允许瞬间累积的最大请求数）
# 例如 PER_SEC=1、BURST=5：每秒补 1 个令牌，最多攒 5 个，可短时 1 秒内打 5 个请求。
# ─────────────────────────────────────────────────────────────
# 严格限流：覆盖登录、注册、评论预检、搜索等敏感/查询接口。
RATE_LIMIT_STRICT_PER_SEC=1
RATE_LIMIT_STRICT_BURST=5
# 上传限流：仅 /api/upload（图片上传）。
RATE_LIMIT_UPLOAD_PER_SEC=2
RATE_LIMIT_UPLOAD_BURST=15
# 图片访问限流：仅 GET /uploads/*（图片读取与处理）。
RATE_LIMIT_IMAGE_PER_SEC=10
RATE_LIMIT_IMAGE_BURST=50
# 评论限流：仅 POST 创建评论（与上面的“评论预检”不是同一个桶）。
RATE_LIMIT_COMMENT_PER_SEC=1
RATE_LIMIT_COMMENT_BURST=5
# 宽松桶：当真实客户端 IP 无法识别（值为 "unknown"）时，由 check_strict_limit 自动改用此桶。
# 触发条件通常是 TRUSTED_PROXY_COUNT=0 且调用方为 Dioxus server function（拿不到 TCP 对端地址）。
# 此时所有匿名请求共享同一个桶，因此阈值必须更高，否则会误杀正常用户。
RATE_LIMIT_UNKNOWN_PER_SEC=30
RATE_LIMIT_UNKNOWN_BURST=100

# ─────────────────────────────────────────────────────────────
# Security 安全相关
# ─────────────────────────────────────────────────────────────
# 写请求（POST/PUT/PATCH/DELETE）CSRF 校验的可信来源。
# 生产环境设为你的源站，例如 https://your-domain.example。
# 不设：回退到请求的 Host 头 + X-Forwarded-Proto。
# ⚠️ 安全提示：反向代理后若 Host 头可被客户端影响，回退路径可能被 CSRF 绕过。
#    生产环境强烈建议显式设置此变量。
APP_BASE_URL=
# 是否给会话 cookie 加 Secure 标志。识别 true/1/yes（其余均视为 false）。
# 启用后浏览器仅在 HTTPS 下发送 cookie，HTTP 生产环境必开。
COOKIE_SECURE=false
# 应用前方的反向代理层数，用于从 X-Forwarded-For 提取真实客户端 IP。
# 直接对外服务时为 0；经过一层代理（如 nginx/Caddy）时为 1。
# ⚠️ 设错的安全后果：
#    设得比实际大 → 信任客户端伪造的 IP，限流可被绕过；
#    设得比实际小 → 取到代理 IP 而非客户端 IP，限流对错对象。
TRUSTED_PROXY_COUNT=0
# 单条 SQL 查询的服务端超时秒数。超时由 PostgreSQL 服务端取消该查询（不是客户端断连）。
# 仅对经连接池（DB_POOL）建立的连接生效；作用是防止单条慢查询长时间占用连接拖垮池。
# 需注意：PostgreSQL 的总连接数受 max_connections 限制，本超时不影响已占连接的计费。
STATEMENT_TIMEOUT_SECS=30

# ─────────────────────────────────────────────────────────────
# WebP 编码配置（仅上传转码 / 图片格式转换时生效）
# ─────────────────────────────────────────────────────────────
# 质量：0.0（最小体积）到 100.0（最佳质量），默认 85.0。
# 越界值会被 clamp（截断）到合法范围并打 WARN 日志，不会报错。
WEBP_QUALITY=85.0
# 编码方法：0（最快）到 6（最佳质量/压缩率），默认 2。
# 越界值同样 clamp 到 0–6。
WEBP_METHOD=2

# 每用户最大并发会话数（默认 5，最小 1）。
# 超过上限时按最旧优先删除（LRU 式淘汰）——新设备登录会让最老的会话自动失效。
MAX_SESSIONS_PER_USER=5

# 数据库连接池大小（默认 20）。
# 不应超过 PostgreSQL 的 max_connections；多实例部署时按 (max_connections / 实例数) 估上限。
DB_POOL_SIZE=20

# 启动时数据库连接重试窗口，单位秒（默认 30）。
# 服务器在启动期间等待 PostgreSQL 可达的最长时间，超时则友好退出（不 panic）。
# 内部以 500ms 固定间隔轮询，因此 30s 约重试 60 次。
# 适用于 DB 启动比 app 慢的场景（docker-compose 无 healthcheck、本机冷启动 Postgres 等）。
# 仅影响启动；运行时连接失败走独立的快速失败策略（1.6s、指数退避），以避免级联故障。
MIGRATE_STARTUP_TIMEOUT_SECS=30

# SSR 页面缓存时长，单位秒（默认 3600，即 1 小时）。
# src/ssr_cache.rs 维护了一个全局 generation 计数器，每次文章写入时自增，
# 但 Dioxus 0.7 暴露的 API 无法把它接入增量 SSR 缓存的 key。在该 API 可用前，
# 此 TTL 是唯一有效的 SSR 缓存失效手段——意味着文章更新后最长可能滞后 TTL 秒才可见。
SSR_CACHE_SECS=3600

# HTTP 响应压缩算法。逗号分隔，大小写不敏感。
# 支持：gzip、brotli（可简写为 br）、deflate、zstd。
# 示例值（四项全开）等价于 "all"，也是不设环境变量时的默认。
# 用 "none" 或 "off" 关闭压缩。
COMPRESSION_ALGORITHMS=gzip,brotli,deflate,zstd

# ─────────────────────────────────────────────────────────────
# 图片响应缓存头（硬编码默认值，非环境变量）
# ─────────────────────────────────────────────────────────────
# 上传的原始图片资源：Cache-Control: public, max-age=31536000, immutable。
# 处理变体（?w=、?format= 等查询参数生成的衍生图）：缓存 24 小时。
# 失效方式：
#   - 原始上传：更改其文件路径；
#   - 处理变体：更改处理参数（查询串不同即视为新资源）。

# ─────────────────────────────────────────────────────────────
# 上传图片尺寸/像素上限（运行时环境变量，启动时读一次）
# ─────────────────────────────────────────────────────────────
# 上传与动态处理(?w= 等)在 header 阶段统一校验(JPEG/PNG/WebP/GIF 同一路径),
# 超限直接 400 拒绝。这两个值同时也是图片解码的安全护栏(防超大图撑爆内存)。
# 只设下限防误调到危险小值,无上限(完全信任运维);低于下限会 clamp 并打 WARN。
# 注:读取侧 GET /uploads/* 的无参数取原图分支不查像素(只卡 20MB 字节)。
# 图片单边(宽或高)尺寸上限,单位像素。默认 8192,下限 512。
MAX_IMAGE_DIMENSION=8192
# 图片总像素上限。默认 50_000_000(约 7000×7000),下限 1_000_000。
# ⚠️ 此值决定单图解码内存缓冲(max_alloc = pixels × 4 + 1MB),
#    默认 50M 像素对应约 200MB/图;上调前确认部署环境内存与并发上传量。
MAX_IMAGE_PIXELS=50000000

# ─────────────────────────────────────────────────────────────
# 图片磁盘缓存上限（uploads/.cache/，后台清理任务每小时扫描一次）
# ─────────────────────────────────────────────────────────────
# 最大总容量，单位 MB（默认 1024）。超限时按修改时间删除最旧的文件。
IMAGE_DISK_CACHE_MAX_MB=1024
# 文件最大保留时长，单位小时（默认 168，即 7 天）。超期的文件优先删除。
# ⚠️ 清理任务每小时运行一次，改了不会立即生效，最长需等 1 小时。
IMAGE_DISK_CACHE_MAX_AGE_HOURS=168

# ─────────────────────────────────────────────────────────────
# 图片尺寸缓存（blur-up 占位图的 aspect-ratio 来源）
# ─────────────────────────────────────────────────────────────
# 图片尺寸缓存的 TTL，单位秒（默认 86400，即 24 小时）。
# 服务端读取图片 header 拿真实宽高，用于生成 aspect-ratio 避免布局跳动。
# 图片尺寸永不变，理论可设很长，但缓存重启会清空。
IMAGE_DIMENSIONS_CACHE_TTL_SECS=86400

# Code Runner Configs
CODE_RUNNER_ALLOW_NETWORK=false
CODE_RUNNER_MAX_CONCURRENT=4
CODE_RUNNER_MAX_CPU_CORES=2.0
CODE_RUNNER_MAX_MEMORY_MB=1024
CODE_RUNNER_MAX_TIMEOUT_SECS=30
CODE_RUNNER_MAX_OUTPUT_BYTES=1048576
# 默认全开：注册表里的语言均可用。设置则收窄到逗号分隔列表（如 python,node）。
# CODE_RUNNER_LANGUAGES=python,node
DOCKER_SOCKET_PATH=/var/run/docker.sock

# Rate limits (governor keyed limiters)
# PER_SEC/BURST 控制单 IP 每秒突发；DAILY 为单 IP 每日总额。
# 注意：PER_SEC 必须是正整数（governor 不支持小数，非整数会回退到默认 1）。
RATE_LIMIT_CODE_EXEC_PER_SEC=1
RATE_LIMIT_CODE_EXEC_BURST=3
RATE_LIMIT_CODE_EXEC_DAILY=50
