diff --git a/.env.example b/.env.example index 5a0a72db9..43c21d2b2 100644 --- a/.env.example +++ b/.env.example @@ -1,73 +1,173 @@ -# Generate a random secret: https://generate-secret.vercel.app/32 or `openssl rand -base64 32` -AUTH_SECRET=**** +# yedir-ai environment template +# Copy this file to .env.local and fill real values locally or in your hosting platform. +# Never commit real secrets. -# Auth URL (optional in Vercel, required for self-hosted) -# Set to your application's public URL, e.g. https://your-domain.com -# Also accepted as NEXTAUTH_URL (deprecated, prefer AUTH_URL) -AUTH_URL= +# ----------------------------------------------------------------------------- +# Core / Auth +# ----------------------------------------------------------------------------- -# 仅在受信反向代理(如 Vercel、Nginx with validated Host header)后部署时设为 true -# 开启后禁用 next-auth 的 Host 头校验,非受信环境不要开启 +# Generate with: openssl rand -base64 32 +AUTH_SECRET=replace-with-random-secret + +# Public application URL. Required for production and self-hosted Auth.js. +AUTH_URL=https://your-domain.com +NEXT_PUBLIC_APP_URL=https://your-domain.com + +# Only enable behind a trusted reverse proxy with validated Host headers. AUTH_TRUST_HOST=false -# Google OAuth (optional) -# https://console.cloud.google.com/apis/credentials +# Optional OAuth providers. GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= -# Admin user credentials (used by create-admin.ts one-time setup script) -# Set both to provision the initial admin account; if omitted, auto-generated +# Optional initial admin provisioning. ADMIN_EMAIL= ADMIN_PASSWORD= -# The following keys below are automatically created and -# added to your environment when you deploy on Vercel +# Optional email verification. +RESEND_API_KEY= +RESEND_FROM_EMAIL= +EMAIL_VERIFICATION_SECRET= -# Instructions to create an AI Gateway API key here: https://vercel.com/ai-gateway -# API key required for non-Vercel deployments -# For Vercel deployments, OIDC tokens are used automatically -# https://vercel.com/ai-gateway -AI_GATEWAY_API_KEY=**** +# Optional scheduled job protection. +CRON_SECRET= +# ----------------------------------------------------------------------------- +# Database +# ----------------------------------------------------------------------------- -# Instructions to create a Vercel Blob Store here: https://vercel.com/docs/vercel-blob -BLOB_READ_WRITE_TOKEN=**** +POSTGRES_URL=postgres://user:password@localhost:5432/yedir_ai -# Instructions to create a PostgreSQL database here: https://vercel.com/docs/postgres -POSTGRES_URL=**** +# Production-safe defaults used by lib/db/index.ts. +POSTGRES_MAX_CONNECTIONS=10 +POSTGRES_IDLE_TIMEOUT_SECONDS=20 +POSTGRES_CONNECT_TIMEOUT_SECONDS=5 +# ----------------------------------------------------------------------------- +# Object Storage +# ----------------------------------------------------------------------------- -# Instructions to create a Redis store here: -# https://vercel.com/docs/redis -REDIS_URL=**** +# Vercel Blob fallback. +BLOB_READ_WRITE_TOKEN= -# DashScope / 通义千问配置 -# 请求地址(阿里云 DashScope OpenAI 兼容接口) +# S3-compatible storage fallback. Database-configured storage takes precedence. +S3_ENDPOINT= +S3_REGION=auto +S3_BUCKET= +S3_ACCESS_KEY_ID= +S3_SECRET_ACCESS_KEY= +S3_PUBLIC_URL= + +# ----------------------------------------------------------------------------- +# AI Providers +# ----------------------------------------------------------------------------- + +AI_GATEWAY_API_KEY= +NEXT_PUBLIC_DEFAULT_CHAT_MODEL= + +# DashScope / Qwen OpenAI-compatible endpoint. DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 +DASHSCOPE_API_KEY= -# API Key(请在本地 .env.local 和 服务器环境中填写真实值,不要把真实 Key 提交到代码仓库) -DASHSCOPE_API_KEY=your-dashscope-api-key - -# 第三方 GPT5 提供方配置(OpenAI 兼容接口) -# API 基础地址(例如:https://api.huandutech.com) -GTP5_API_URL=https://api.huandutech.com - -# API Key(请在本地 .env.local 和 服务器环境中填写真实值,不要把真实 Key 提交到代码仓库) -GTP5_API_KEY=your-gtp5-api-key - -# 模型名称(例如:gpt-5-nano) +# Third-party GPT-compatible provider. +GTP5_API_URL= +GTP5_API_KEY= GTP5_MODEL=gpt-5-nano -# Tripo3D(可选) -# 优先使用系统设置-本地AI里的 `tripo-3d` 提供商;若未配置则回退到环境变量 -TRIPO_API_KEY=your-tripo-api-key +# FAL image/video/realtime providers. +FAL_KEY= +FAL_API_KEY= +FAL_BASE_URL=https://fal.run +FAL_MODEL= +FAL_REALTIME_MODEL= + +# 3D / CAD providers. +TRIPO_API_KEY= TRIPO_BASE_URL=https://api.tripo3d.ai/v2/openapi - -# KittyCAD / Zoo Text-to-CAD(可选) -# 优先使用系统设置-本地AI里的 `kittycad-cad` 提供商;若未配置则回退到环境变量 -KITTYCAD_API_TOKEN=your-kittycad-api-token +WORLDLABS_API_KEY= +WORLDLABS_BASE_URL= +WORLDLABS_IMPORT_TOKEN= +WORLDLABS_KEY_POOL_IMPORT_TOKEN= +KITTYCAD_API_TOKEN= +KITTYCAD_API_KEY= KITTYCAD_BASE_URL=https://api.zoo.dev +ZOO_API_TOKEN= +ZOO_BASE_URL=https://api.zoo.dev -# FAL.ai(可选) -# 用于图片生成和编辑;若未配置则回退到系统设置中的 AI 提供商 -FAL_KEY=your-fal-ai-key +# RUXA / video callback. +RUXA_CALLBACK_URL= + +# ----------------------------------------------------------------------------- +# Product Planning Integrations +# ----------------------------------------------------------------------------- + +PRODUCT_PLANNING_DETAIL_PLUS_BASE_URL= +PRODUCT_PLANNING_DETAIL_PLUS_INTERNAL_BASE_URL= +PRODUCT_PLANNING_DETAIL_PLUS_API_KEY= +PRODUCT_PLANNING_QA_TOKEN= +TAOBAO_API_KEY= +TAOBAO_API_SECRET= +TAOBAO_SALE_API_TOKEN= + +PRODUCT_PLANNING_DB_HOST= +PRODUCT_PLANNING_DB_PORT=3306 +PRODUCT_PLANNING_DB_NAME= +PRODUCT_PLANNING_DB_USER= +PRODUCT_PLANNING_DB_PASSWORD= +PRODUCT_PLANNING_DB_CHARSET=utf8mb4 +PRODUCT_PLANNING_DB_SSL=false + +# ----------------------------------------------------------------------------- +# Home Performance / Queues +# ----------------------------------------------------------------------------- + +CANVAS_IMAGE_TASK_CONCURRENCY=3 +CANVAS_IMAGE_TASK_BATCH_DISPATCH_INTERVAL_MS=1000 +EXTERNAL_IMAGE_API_MAX_CONCURRENT=3 +EXTERNAL_IMAGE_API_MAX_QUEUE=20 +EXTERNAL_IMAGE_API_QUEUE_TIMEOUT_MS=120000 + +# ----------------------------------------------------------------------------- +# Agent / PSD Runtime +# ----------------------------------------------------------------------------- + +AGENT_FORCE_LLM_PLANNER=false +AGENT_FORCE_QWEN3VL_FALLBACK=false +AGENT_IMAGE_GEN_LLM_OPTIMIZER_ENABLED=true +AGENT_LLM_PROMPT_OPTIMIZER_ENABLED=true +AGENT_REPLACEMENT_PARALLEL_WORKER_COUNT=2 +AGENT_PSD_LOCAL_CACHE_DIR= +AGENT_PSD_REMOTE_ASSET_CACHE_DISABLED=false +AGENT_PSD_REMOTE_ASSET_CACHE_MAX_BYTES= +AGENT_PSD_REMOTE_ASSET_CACHE_MAX_ENTRY_BYTES= +AGENT_PSD_REMOTE_ASSET_CACHE_TTL_MS= +AGENT_PSD_RENDER_PNG_COMPRESSION_LEVEL=6 +AGENT_PSD_RENDER_TASK_CONCURRENCY=2 + +# ----------------------------------------------------------------------------- +# Logging / Observability +# ----------------------------------------------------------------------------- + +# debug | info | warn | error | silent +LOG_LEVEL=info + +# Stack traces remain disabled in production unless explicitly enabled. +LOG_INCLUDE_STACK=false + +# Client logs are silent in production unless this is true. +NEXT_PUBLIC_ENABLE_CLIENT_LOGS=false + +# ----------------------------------------------------------------------------- +# Optional Jobs +# ----------------------------------------------------------------------------- + +VIDEO_ARCHIVE_DELAY_HOURS=24 + +# ----------------------------------------------------------------------------- +# Test / Local Dev +# ----------------------------------------------------------------------------- + +PORT=3001 +PLAYWRIGHT=false +CI_PLAYWRIGHT=false +PLAYWRIGHT_TEST_BASE_URL=http://127.0.0.1:3001 diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 6e18c3ec6..532094623 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -9,6 +9,9 @@ jobs: test: timeout-minutes: 30 runs-on: ubuntu-latest + if: >- + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository env: AUTH_SECRET: ${{ secrets.AUTH_SECRET }} POSTGRES_URL: ${{ secrets.POSTGRES_URL }} @@ -22,32 +25,15 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 + cache: "pnpm" - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: - version: latest + version: 9.12.3 run_install: false - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - uses: actions/cache@v3 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - uses: actions/setup-node@v4 - with: - node-version: lts/* - cache: "pnpm" - - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/README.md b/README.md index 4df063825..75932a39a 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,118 @@ - - Next.js 14 and App Router-ready AI chatbot. -

Chat SDK

-
+# yedir-ai -

- Chat SDK is a free, open-source template built with Next.js and the AI SDK that helps you quickly build powerful chatbot applications. -

+yedir-ai 是一个面向商业化交付的 AI 设计工作台。它把 Lovart 风格的新首页、无限画布、Agent 工作流、图像生成与编辑、3D/CAD、本地 AI 配置中心和后台治理能力整合到同一个 Next.js 应用中。 -

- Read Docs · - Features · - Model Providers · - Deploy Your Own · - Running locally -

-
+这个仓库已经不再定位为通用 Chat 模板。旧 Chat 页面入口已移除,`/api/chat` 目前保留为 Canvas/Agent 等内部生成链路使用。 -## Features +## 当前能力 -- [Next.js](https://nextjs.org) App Router - - Advanced routing for seamless navigation and performance - - React Server Components (RSCs) and Server Actions for server-side rendering and increased performance -- [AI SDK](https://ai-sdk.dev/docs/introduction) - - Unified API for generating text, structured objects, and tool calls with LLMs - - Hooks for building dynamic chat and generative user interfaces - - Supports xAI (default), OpenAI, Fireworks, and other model providers -- [shadcn/ui](https://ui.shadcn.com) - - Styling with [Tailwind CSS](https://tailwindcss.com) - - Component primitives from [Radix UI](https://radix-ui.com) for accessibility and flexibility -- Data Persistence - - [Neon Serverless Postgres](https://vercel.com/marketplace/neon) for saving chat history and user data - - [Vercel Blob](https://vercel.com/storage/blob) for efficient file storage -- [Auth.js](https://authjs.dev) - - Simple and secure authentication +- **Lovart 风格首页**:静态轻量壳优先渲染,站点配置、精选图、项目、教程和会员信息通过客户端渐进加载。 +- **Canvas/Agent 工作台**:支持多模态生成、图片编辑、素材编排、Agent 模式和项目化创作流程。 +- **图像与视频生成链路**:支持 Gemini、Volcano、Qwen、FAL、RUXA、Krea、Runway、Midjourney 等可配置供应商。 +- **3D / CAD 能力**:集成 Tripo3D、World Labs、KittyCAD/Zoo,并支持后台模型别名和 Key 池配置。 +- **后台设置中心**:本地 AI 设置已拆分为领域组件,支持折叠持久化、状态摘要、快捷目录和统一 section shell。 +- **生产治理**:包含类型检查、lint、日志脱敏、首页公开接口缓存/降级、仓库污染物检查和 CI 质量门禁。 -## Model Providers +## 技术栈 -This template uses the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) to access multiple AI models through a unified interface. The default configuration includes [xAI](https://x.ai) models (`grok-2-vision-1212`, `grok-3-mini`) routed through the gateway. +- Next.js 16 App Router +- React 19 RC +- TypeScript +- Tailwind CSS + Radix UI +- Drizzle ORM + Postgres +- Auth.js +- Vercel Blob / S3-compatible object storage +- Playwright +- Ultracite / Biome -### AI Gateway Authentication +## 快速开始 -**For Vercel deployments**: Authentication is handled automatically via OIDC tokens. - -**For non-Vercel deployments**: You need to provide an AI Gateway API key by setting the `AI_GATEWAY_API_KEY` environment variable in your `.env.local` file. - -With the [AI SDK](https://ai-sdk.dev/docs/introduction), you can also switch to direct LLM providers like [OpenAI](https://openai.com), [Anthropic](https://anthropic.com), [Cohere](https://cohere.com/), and [many more](https://ai-sdk.dev/providers/ai-sdk-providers) with just a few lines of code. - -## Deploy Your Own - -You can deploy your own version of the Next.js AI Chatbot to Vercel with one click: - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/templates/next.js/nextjs-ai-chatbot) - -## Running locally - -You will need to use the environment variables [defined in `.env.example`](.env.example) to run Next.js AI Chatbot. It's recommended you use [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables) for this, but a `.env` file is all that is necessary. - -> Note: You should not commit your `.env` file or it will expose secrets that will allow others to control access to your various AI and authentication provider accounts. - -1. Install Vercel CLI: `npm i -g vercel` -2. Link local instance with Vercel and GitHub accounts (creates `.vercel` directory): `vercel link` -3. Download your environment variables: `vercel env pull` +准备 Node.js 20、pnpm 9.12.3 和 Postgres。 ```bash pnpm install -pnpm db:migrate # Setup database or apply latest database changes -pnpm dev +cp .env.example .env.local +pnpm db:migrate +AUTH_TRUST_HOST=true PORT=3001 pnpm dev ``` -Your app template should now be running on [localhost:3000](http://localhost:3000). +默认访问地址: + +```text +http://localhost:3001/ +``` + +后台设置页: + +```text +http://localhost:3001/settings +``` + +未登录访问后台会重定向到 `/login?callbackUrl=%2Fsettings`。 + +## 环境变量 + +先从 `.env.example` 复制到 `.env.local`,再按部署环境填写真实值。不要提交 `.env.local` 或任何真实密钥。 + +最小本地运行通常需要: + +- `AUTH_SECRET` +- `AUTH_URL` 或本地开发使用 `AUTH_TRUST_HOST=true` +- `POSTGRES_URL` +- `BLOB_READ_WRITE_TOKEN` 或一组 S3 配置 +- 至少一个可用 AI Provider Key,或在后台设置中配置供应商 + +更多分组说明见 [docs/deployment.md](docs/deployment.md)。 + +## 常用命令 + +```bash +pnpm dev +pnpm lint +pnpm check:logs +pnpm exec tsc --noEmit --pretty false +pnpm test +pnpm db:migrate +pnpm db:generate +``` + +推荐提交前至少运行: + +```bash +pnpm lint +pnpm check:logs +pnpm exec tsc --noEmit --pretty false +git diff --check +``` + +## 目录结构 + +```text +app/ Next.js routes, route handlers, admin pages +components/ UI, Canvas, home, editor and product modules +components/home/lovart/ Lovart home focused render sections +lib/ DB, AI providers, storage, observability, domain logic +docs/ Deployment, operations, architecture and feature notes +tests/ Playwright e2e and route-level tests +.github/workflows/ Quality gates and Playwright CI +``` + +## 部署与运维 + +- 生产部署建议使用受控反向代理,并只在 Host 头可信时设置 `AUTH_TRUST_HOST=true`。 +- 首页公开接口应保持快速返回,慢数据库或外部服务异常时返回缓存或 fallback。 +- 生产日志默认通过 `LOG_LEVEL=info` 控制,敏感字段会被 `lib/observability` 脱敏。 +- Playwright workflow 独立于基础质量门禁,避免把密钥依赖和 e2e 成本混入每次 lint/typecheck。 + +详细说明: + +- [部署指南](docs/deployment.md) +- [运维与质量门禁](docs/operations.md) +- [系统架构说明](docs/architecture.md) + +## 开发边界 + +- `/classic` 和 `/chat/[id]` 旧 Chat UI 已重定向到 `/`。 +- `/api/chat` 暂时是内部生成 API,不作为公开旧 Chat 页面入口。 +- Canvas、Agent、图像处理和后台设置仍有大型历史模块,后续应按领域继续拆分。 +- License 以仓库根目录 [LICENSE](LICENSE) 为准;本阶段未修改许可证和版权主体。 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 000000000..38233f645 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,78 @@ +# yedir-ai 架构说明 + +yedir-ai 是一个以 AI 设计工作台为核心的 Next.js 应用,主要由首页体验、Canvas/Agent 创作链路、后台设置中心、内部生成 API、公开轻量 API 和基础设施治理组成。 + +## 高层边界 + +```text +Browser + | + |-- / Lovart-style home shell + |-- /canvas/* Canvas and Agent workspace + |-- /settings Admin settings center + |-- /api/site-settings Public lightweight settings API + |-- /api/featured Public featured gallery API + |-- /api/chat Internal generation API + | +Next.js App Router + | + |-- Auth.js session, admin access, OAuth + |-- Drizzle/Postgres projects, settings, users, tasks + |-- Storage service DB S3 config, env S3, Vercel Blob fallback + |-- AI providers image, video, 3D, CAD, agent workflows + |-- Observability structured logs and redaction +``` + +## 首页 + +首页 `/` 优先渲染静态轻量壳,不在服务端阻塞等待 session、站点配置或个性化数据。站点配置、精选图、项目、会员和教程等数据通过客户端渐进加载。 + +公开首页接口应具备缓存、降级和观测头,避免数据库或外部服务波动拖慢首屏。 + +## Canvas / Agent + +Canvas 是主要创作工作区,承载图像生成、编辑、素材编排、Agent 自动规划、多模态输入和项目化保存。 + +Agent 能力依赖内部生成链路、模型供应商配置和素材/PSD 等领域模块。相关巨型模块仍是后续治理重点,拆分时应保持 API shape 和保存逻辑不变。 + +## 后台设置中心 + +`/settings` 是管理员配置入口。本地 AI 设置已按领域拆分为 planning、model3d、image-pipeline、runtime 等组件,并保留统一 section shell、状态摘要、快捷目录和折叠持久化。 + +后台保存逻辑、数据库 setting key 和 SWR key 应保持稳定,避免配置迁移风险。 + +## 内部生成 API + +`/api/chat` 目前不再对应旧 Chat UI,而是 Canvas/Agent 的内部生成 API。旧页面 `/classic` 和 `/chat/[id]` 已重定向到 `/`。 + +未来若要彻底替换 `/api/chat`,应先把 Canvas/Agent 调用方迁移到专用生成接口,再删除旧协议。 + +## 公开轻量 API + +首页相关公开接口包括: + +- `/api/site-settings?scope=home` +- `/api/featured` +- `/api/nav-links` +- `/api/home-animation` +- `/api/auth-settings` + +这些接口应快速返回,必要时使用 stale cache 或 fallback。响应头应保留 `X-Cache`、`X-Fallback`、`Server-Timing`,方便判断慢点来自缓存、DB 还是降级。 + +## 数据与存储 + +Postgres 是主数据源。连接池默认使用有限连接数、短连接超时和 `prepare: false`,避免数据库不可用时拖垮公开接口。 + +对象存储优先使用数据库中的 S3 配置;环境变量 S3 和 Vercel Blob 是 fallback。日志中不应输出完整 endpoint、bucket key、签名 URL 或原图 URL。 + +## 质量与安全治理 + +主质量门禁包括: + +- `pnpm lint` +- `pnpm check:logs` +- `pnpm exec tsc --noEmit --pretty false` +- `git diff --check` +- tracked 污染物检查 + +日志通过 `lib/observability` 结构化输出并脱敏。当前只治理了第一批高风险链路,Canvas 和 `/api/chat` 日志二期仍待推进。 diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 000000000..c735f5993 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,93 @@ +# yedir-ai 部署指南 + +本文档用于生产或准生产环境部署。所有真实密钥只应配置在运行环境中,不要提交到 Git。 + +## 运行环境 + +- Node.js 20 +- pnpm 9.12.3 +- Postgres +- 可选 Redis +- Vercel Blob 或 S3-compatible 对象存储 +- 至少一个可用 AI Provider,或在后台设置中配置供应商 + +## 基础步骤 + +```bash +pnpm install --frozen-lockfile +pnpm db:migrate +pnpm build +pnpm start +``` + +本地开发: + +```bash +AUTH_TRUST_HOST=true PORT=3001 pnpm dev +``` + +## 环境变量分组 + +### Core / Auth + +必须配置 `AUTH_SECRET` 和生产域名 `AUTH_URL`。只有在受信反向代理后部署,并确认 Host 头不会被用户伪造时,才允许设置 `AUTH_TRUST_HOST=true`。 + +Google、钉钉、邮箱验证等登录能力可以通过后台设置和环境变量组合启用。管理员初始化使用 `ADMIN_EMAIL` / `ADMIN_PASSWORD`,完成后建议移除或轮换。 + +### Database + +主数据库使用 `POSTGRES_URL`。连接池默认值来自 `lib/db/index.ts`: + +- `POSTGRES_MAX_CONNECTIONS=10` +- `POSTGRES_IDLE_TIMEOUT_SECONDS=20` +- `POSTGRES_CONNECT_TIMEOUT_SECONDS=5` + +生产环境可按数据库规格调整,但不建议无上限放大连接数。 + +### Object Storage + +优先使用后台数据库中的存储配置;环境变量 S3 和 `BLOB_READ_WRITE_TOKEN` 作为 fallback。 + +S3 公网访问建议配置 `S3_PUBLIC_URL`,避免把内部 endpoint 暴露给前端或用户。 + +### AI Providers + +大多数供应商都可以在后台设置中配置。环境变量适合作为 bootstrap 或 fallback,例如 `DASHSCOPE_API_KEY`、`FAL_KEY`、`TRIPO_API_KEY`、`KITTYCAD_API_TOKEN`。 + +不要在日志、README、issue 或截图中暴露真实 API Key、签名 URL、OAuth code、session、cookie。 + +### Logging + +生产建议: + +```env +LOG_LEVEL=info +LOG_INCLUDE_STACK=false +NEXT_PUBLIC_ENABLE_CLIENT_LOGS=false +``` + +日志会经过 `lib/observability` 脱敏。需要排查问题时,优先临时提高服务端 `LOG_LEVEL`,不要开启浏览器生产日志。 + +## 反向代理与安全 + +- 代理层应保留正确的 `X-Forwarded-*` 头。 +- 只在可信代理后启用 `AUTH_TRUST_HOST=true`。 +- 上传和生成接口可能处理大文件,代理需要配置足够的 body size 和超时时间。 +- 对管理端、支付、生成任务回调和定时任务接口使用独立密钥或登录权限保护。 + +## 部署后烟测 + +```bash +curl -I https://your-domain.com/ +curl -I https://your-domain.com/classic +curl -I https://your-domain.com/chat/test-id +curl -I https://your-domain.com/settings +curl -I "https://your-domain.com/api/site-settings?scope=home" +``` + +预期: + +- `/` 返回 200。 +- `/classic` 和 `/chat/test-id` 重定向到 `/`。 +- `/settings` 未登录重定向到登录页。 +- 首页公开接口带有 `X-Cache` / `X-Fallback` / `Server-Timing` 等观测头。 diff --git a/docs/operations.md b/docs/operations.md new file mode 100644 index 000000000..0bd122b4b --- /dev/null +++ b/docs/operations.md @@ -0,0 +1,78 @@ +# yedir-ai 运维与质量门禁 + +本文档记录日常开发、合并前检查、性能烟测和常见故障处理方式。 + +## 合并前检查 + +```bash +pnpm lint +pnpm check:logs +pnpm exec tsc --noEmit --pretty false +git diff --check +``` + +污染物检查: + +```bash +git ls-files | rg '(^|/)\\.DS_Store$|\\.swp$|\\.env\\.local$|^\\.claude/|^migration-backup|^tsconfig\\.tsbuildinfo$' || true +``` + +预期无输出。 + +## CI + +`.github/workflows/lint.yml` 是基础质量门禁,负责 lint、日志治理、类型检查、diff hygiene 和 tracked 污染物检查。 + +Playwright workflow 独立运行,避免 e2e 依赖、浏览器安装和 secrets 影响基础门禁反馈速度。 + +## 日志治理 + +新增或修改已治理文件时不要使用裸 `console.*`。使用: + +```ts +import { createLogger } from "@/lib/observability/logger"; + +const logger = createLogger("scope-name"); +logger.info("event name", { count: 1 }); +logger.error("event failed", error); +``` + +客户端使用 `createClientLogger`。生产环境默认静默,除非显式设置 `NEXT_PUBLIC_ENABLE_CLIENT_LOGS=true`。 + +`pnpm check:logs` 会检查已治理文件是否重新引入裸 console,并验证 token、API Key、URL、base64、password 等敏感值不会明文输出。 + +## 首页性能烟测 + +```bash +AUTH_TRUST_HOST=true PORT=3001 pnpm dev +curl -I --max-time 30 http://127.0.0.1:3001/ +curl -I --max-time 30 "http://127.0.0.1:3001/api/site-settings?scope=home" +curl -I --max-time 30 "http://127.0.0.1:3001/api/featured?page=1&pageSize=24" +``` + +首页 HTML 应快速返回。公开轻量接口在数据库慢或不可用时应快速返回缓存或 fallback,不应长时间挂住首屏。 + +## 路由回归烟测 + +```bash +curl -I http://127.0.0.1:3001/ +curl -I http://127.0.0.1:3001/classic +curl -I http://127.0.0.1:3001/chat/test-id +curl -I http://127.0.0.1:3001/settings +curl -I -X POST http://127.0.0.1:3001/api/files/upload +``` + +预期: + +- `/` 返回 200。 +- `/classic` 和 `/chat/test-id` 返回 307 到 `/`。 +- `/settings` 未登录返回 307 到 `/login?callbackUrl=%2Fsettings`。 +- 上传接口未登录返回 401。 + +## 常见故障 + +- `.next/dev/lock` 阻止启动:已有 dev server 持锁,先确认进程归属,不要误杀其他工作区服务。 +- 首页接口慢:先看 `Server-Timing`、`X-Cache`、`X-Fallback`,再查数据库连接池和公开接口 fallback。 +- 登录 Host 错误:生产配置 `AUTH_URL`;仅在可信代理后设置 `AUTH_TRUST_HOST=true`。 +- 上传失败:确认后台存储配置、环境变量 S3 fallback 或 `BLOB_READ_WRITE_TOKEN` 至少一组可用。 +- 日志泄露风险:不要把完整 prompt、OAuth token、签名 URL、cookie、request body 放进日志 message。