diff --git a/.memory/worklog.json b/.memory/worklog.json
index 6763a92..5f905c7 100644
--- a/.memory/worklog.json
+++ b/.memory/worklog.json
@@ -1,32 +1,5 @@
{
"entries": [
- {
- "files_changed": 3,
- "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 3 项未提交变更 · 最近提交:auto-save 2026-05-20 14:12 (~5)",
- "ts": "2026-05-20T06:13:58Z",
- "type": "session-heartbeat"
- },
- {
- "files_changed": 4,
- "hash": "f1c710e",
- "message": "fix: clear subject conversion panel",
- "ts": "2026-05-20T14:16:58+08:00",
- "type": "commit"
- },
- {
- "files_changed": 2,
- "hash": "9c97e2a",
- "message": "auto-save 2026-05-20 14:17 (+1, ~1)",
- "ts": "2026-05-20T14:18:01+08:00",
- "type": "commit"
- },
- {
- "files_changed": 2,
- "hash": "fd676c7",
- "message": "docs: record cleared conversion deployment",
- "ts": "2026-05-20T14:21:28+08:00",
- "type": "commit"
- },
{
"files_changed": 2,
"hash": "88034e8",
@@ -3207,6 +3180,31 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:auto-save 2026-05-26 07:04 (~4)",
"files_changed": 1
+ },
+ {
+ "ts": "2026-05-26T07:06:38+08:00",
+ "type": "commit",
+ "message": "feat: add Postgres-backed company persistence",
+ "hash": "c5ddfed",
+ "files_changed": 2
+ },
+ {
+ "ts": "2026-05-25T23:14:48Z",
+ "type": "session-heartbeat",
+ "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: add Postgres-backed company persistence",
+ "files_changed": 1
+ },
+ {
+ "ts": "2026-05-25T23:50:49Z",
+ "type": "session-heartbeat",
+ "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: add Postgres-backed company persistence",
+ "files_changed": 1
+ },
+ {
+ "ts": "2026-05-26T00:29:33Z",
+ "type": "session-heartbeat",
+ "message": "Codex 会话活跃 · 最近命令:codex · 分支 main · 1 项未提交变更 · 最近提交:feat: add Postgres-backed company persistence",
+ "files_changed": 1
}
]
}
diff --git a/.project.json b/.project.json
index 48cfa37..31de00e 100644
--- a/.project.json
+++ b/.project.json
@@ -33,7 +33,7 @@
"type" : "api_key"
},
{
- "description" : "生产网页登录备用账号;飞书免登录为主路径,备用账号密码只放服务器 \/root\/skg-marketing-studio-login.txt,后端会话密钥只放服务器 deploy\/.env.production 的 WEB_AUTH_SESSION_SECRET",
+ "description" : "生产网页登录备用账号已停用,当前只允许飞书免登录;如需紧急恢复,需在服务器 deploy\/.env.production 显式开启 PASSWORD_AUTH_ENABLED=true。备用账号密码只放服务器 \/root\/skg-marketing-studio-login.txt,后端会话密钥只放服务器 deploy\/.env.production 的 WEB_AUTH_SESSION_SECRET",
"name" : "WEB_LOGIN",
"storage" : "\/root\/skg-marketing-studio-login.txt \/ deploy\/.env.production",
"type" : "web_login"
@@ -73,7 +73,7 @@
"label" : "SKG 营销内容生产平台",
"password" : "",
"url" : "https:\/\/marketing.skg.com\/login\/",
- "username" : "飞书免登录;备用账号见 credentials.WEB_LOGIN"
+ "username" : "仅飞书免登录;密码登录已停用"
},
"stack" : [
"Next.js + Vue\/Vite canvas + FastAPI + Postgres + Python(yt-dlp\/ffmpeg) + OpenAI-compatible LLM + GPT Image 2 + Azure OpenAI TTS + Seedance\/Kling\/Veo video gateway"
diff --git a/RULES.md b/RULES.md
index b4f6515..3fae135 100644
--- a/RULES.md
+++ b/RULES.md
@@ -83,12 +83,13 @@
- 当前音频解析:`https://ai.skg.com/azure/v1` 的 `gpt-4o-transcribe` 当前返回 `DeploymentNotFound`,且官方 Azure OpenAI transcription 路径探测也未返回可用部署;生产临时复制本地成功策略,直接使用容器内多语言 `faster-whisper` 真实转写,默认语种为 `auto`,支持中文、英文和其他多语言原文识别,关闭 Gemini 多模态音频兜底。拿到真实 Azure ASR deployment 名后再恢复 `ASR_REMOTE_ENABLED=true`,并保持 `ASR_LANGUAGE` 为空或 `auto`,除非明确只想强制单一语种。
- 持久化目录:服务器 `./data/jobs` 挂载到后端 `/data/jobs`;全局资源中心持久化在 `./data/asset_library`、`./data/prompt_library` 和 `./data/_trash`;Postgres 数据目录为服务器 `./data/postgres`,部署脚本通过 `pg_dump` 产出 `/opt/skg-marketing-studio-backups/skg-marketing-postgres-*.sql.gz`
- TikTok 下载登录态:公开视频默认不带 cookies 直接下载,生产环境变量必须显式保持 `YTDLP_COOKIES_FILE=`、`YTDLP_COOKIES_FROM_BROWSER=` 为空,防止容器读取不存在的浏览器 cookies。只有 TikTok 明确要求登录态时,才使用服务器私有 cookies 文件 `./secrets/tiktok_cookies.txt` 挂载到 API 容器 `/run/secrets/tiktok_cookies.txt` 并配置 `YTDLP_COOKIES_FILE=/run/secrets/tiktok_cookies.txt`;`yt-dlp` 会在任务结束时回写 cookies,因此不要把该挂载设为只读;不要使用云端浏览器读取方案,也不要把 cookies 入库。生产容器严禁使用 `YTDLP_COOKIES_FROM_BROWSER=chrome`。
-- 登录凭证:生产入口以飞书免登录为主;飞书 OAuth 的 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` 只放服务器 `deploy/.env.production`,回调地址固定为 `https://marketing.skg.com/api/auth/feishu/callback` 并需要在飞书开放平台应用安全设置中登记。登录页读取 `/api/auth/config` 后,如果检测到飞书客户端并且 `feishu_enabled=true`,会自动跳转 `/api/auth/feishu/start`,普通浏览器仍保留“飞书免登录”按钮和备用账号。原账号密码登录保留为备用入口,用户名写下方快捷登录,密码明文备份只放服务器 `/root/skg-marketing-studio-login.txt`,`WEB_AUTH_PASSWORD` / `WEB_AUTH_SESSION_SECRET` 只放服务器 `deploy/.env.production`。开启 `AUTH_DATA_ISOLATION_ENABLED=true` 后,新建任务、素材任务和一键出片记录按登录用户隔离;历史无 owner 的旧任务只对备用账号可见,飞书用户互不可见。
+- 登录凭证:生产入口只允许飞书免登录;飞书 OAuth 的 `FEISHU_APP_ID` / `FEISHU_APP_SECRET` 只放服务器 `deploy/.env.production`,回调地址固定为 `https://marketing.skg.com/api/auth/feishu/callback` 并需要在飞书开放平台应用安全设置中登记。登录页读取 `/api/auth/config` 后,如果检测到飞书客户端并且 `feishu_enabled=true`,会自动跳转 `/api/auth/feishu/start`,普通浏览器显示“飞书免登录”按钮;生产 `PASSWORD_AUTH_ENABLED=false` 时账号密码表单不展示,`POST /auth/login` 不可用,旧密码 Cookie 会失效。原账号密码只作为紧急备用配置保留在服务器 `/root/skg-marketing-studio-login.txt` 和 `deploy/.env.production`,如需临时恢复必须显式改为 `PASSWORD_AUTH_ENABLED=true` 并重启 API。开启 `AUTH_DATA_ISOLATION_ENABLED=true` 后,新建任务、素材任务和一键出片记录按登录用户隔离;历史无 owner 的旧任务不再通过密码账号访问,后续应走迁移/认领。
- 禁止手动裸 `rsync --delete` 到服务器;必须使用 `./scripts/deploy-prod-safe.sh`。如遇极端情况必须手动同步,命令必须同时包含 protect/exclude:`.git`、`.memory`、`.logs`、`.pids`、`data`、`jobs`、`secrets`、`api/jobs`、`api/.env`、`api/.env.local`、`api/.env.production`、`deploy/.env.production`、`web/node_modules`、`web/.next`、`web/out`。不要把本地 `api/.env` 或 `deploy/.env.production` 覆盖到 `/opt/skg-marketing-studio`,也不要删除服务器 `data/jobs`,否则会清空案例、登录和模型配置。
## 快捷登录
- 登录地址:`https://marketing.skg.com/login/`
- 主路径:飞书免登录
+- 密码登录:生产已停用
- 备用用户名:`skg`
- 备用密码:见服务器 `/root/skg-marketing-studio-login.txt`(不入库)
- 说明:当前是生产入口应用内登录页;飞书 App Secret、数据库密码、API Key、服务器 root 密码不要写这里
@@ -139,7 +140,8 @@
- `AZURE_OPENAI_BASE_URL` / `AZURE_OPENAI_API_KEY`:微软 Azure OpenAI 协议配音网关;本地未单独配置 Key 时回退复用 `LLM_API_KEY`
- `AZURE_TTS_MODEL` / `AZURE_TTS_VOICE_ID` / `AZURE_TTS_VOICE_POOL` / `AZURE_TTS_PATH` / `AZURE_TTS_PATHS`:Azure OpenAI TTS 模型、默认音色、音色池和 OpenAI 协议语音路径;后端会按 `AZURE_TTS_PATHS` 依次尝试,便于区分路径不对和整条语音服务不可用
- `POE_API_KEY` / `VIDEO_API_KEY`:视频生成通道 Key,只能放本地环境变量
-- `WEB_AUTH_USERNAME` / `WEB_AUTH_PASSWORD` / `WEB_AUTH_SESSION_SECRET`:生产备用网页登录和会话签名配置;密码和 session secret 只放服务器环境变量,不入库。即使只开飞书免登录,也必须配置 `WEB_AUTH_SESSION_SECRET` 用于签名会话 Cookie。
+- `PASSWORD_AUTH_ENABLED`:生产密码登录总开关;当前固定为 `false`,只允许飞书免登录。若应急恢复密码入口,必须显式改成 `true` 并重启 API。
+- `WEB_AUTH_USERNAME` / `WEB_AUTH_PASSWORD` / `WEB_AUTH_SESSION_SECRET`:生产备用网页登录和会话签名配置;密码和 session secret 只放服务器环境变量,不入库。当前密码入口被 `PASSWORD_AUTH_ENABLED=false` 禁用;即使只开飞书免登录,也必须配置 `WEB_AUTH_SESSION_SECRET` 用于签名会话 Cookie。
- `FEISHU_APP_ID` / `FEISHU_APP_SECRET`:飞书免登录 OAuth 应用凭证;只放服务器 `deploy/.env.production` 或本地 `api/.env`,不入库。
- `FEISHU_REDIRECT_URI`:飞书 OAuth 回调地址,生产固定为 `https://marketing.skg.com/api/auth/feishu/callback`。
- `FEISHU_OAUTH_SCOPE`:飞书 OAuth 授权范围;默认空值,按飞书应用后台已开权限执行。
diff --git a/api/main.py b/api/main.py
index cccb486..cf02bf6 100644
--- a/api/main.py
+++ b/api/main.py
@@ -251,6 +251,7 @@ WEB_AUTH_PASSWORD = os.getenv("WEB_AUTH_PASSWORD", "").strip()
WEB_AUTH_SESSION_SECRET = os.getenv("WEB_AUTH_SESSION_SECRET", "").strip()
WEB_AUTH_COOKIE_NAME = os.getenv("WEB_AUTH_COOKIE_NAME", "skg_marketing_session").strip() or "skg_marketing_session"
WEB_AUTH_COOKIE_SECURE = os.getenv("WEB_AUTH_COOKIE_SECURE", "true").strip().lower() not in {"0", "false", "no"}
+PASSWORD_AUTH_ENABLED = os.getenv("PASSWORD_AUTH_ENABLED", "true").strip().lower() not in {"0", "false", "no", "off"}
FEISHU_APP_ID = (os.getenv("FEISHU_APP_ID") or os.getenv("FEISHU_CLIENT_ID") or "").strip()
FEISHU_APP_SECRET = (os.getenv("FEISHU_APP_SECRET") or os.getenv("FEISHU_CLIENT_SECRET") or "").strip()
FEISHU_REDIRECT_URI = os.getenv("FEISHU_REDIRECT_URI", "").strip()
@@ -274,7 +275,7 @@ FEISHU_ALLOWED_TENANT_KEYS = os.getenv("FEISHU_ALLOWED_TENANT_KEYS", "").strip()
AUTH_DATA_ISOLATION_ENABLED = os.getenv("AUTH_DATA_ISOLATION_ENABLED", "true").strip().lower() not in {"0", "false", "no", "off"}
VIDEO_QUEUE_MAX_CONCURRENT = max(1, int(os.getenv("VIDEO_QUEUE_MAX_CONCURRENT", "2").strip() or "2"))
VIDEO_QUEUE_MAX_CONCURRENT_PER_USER = max(1, int(os.getenv("VIDEO_QUEUE_MAX_CONCURRENT_PER_USER", "1").strip() or "1"))
-PASSWORD_AUTH_CONFIGURED = bool(WEB_AUTH_USERNAME and WEB_AUTH_PASSWORD and WEB_AUTH_SESSION_SECRET)
+PASSWORD_AUTH_CONFIGURED = PASSWORD_AUTH_ENABLED and bool(WEB_AUTH_USERNAME and WEB_AUTH_PASSWORD and WEB_AUTH_SESSION_SECRET)
FEISHU_AUTH_CONFIGURED = bool(FEISHU_APP_ID and FEISHU_APP_SECRET and WEB_AUTH_SESSION_SECRET)
WEB_AUTH_CONFIGURED = bool(PASSWORD_AUTH_CONFIGURED or FEISHU_AUTH_CONFIGURED)
diff --git a/deploy/.env.production.example b/deploy/.env.production.example
index 9394e77..aaf8524 100644
--- a/deploy/.env.production.example
+++ b/deploy/.env.production.example
@@ -16,6 +16,7 @@ POSTGRES_PASSWORD=
DATABASE_URL=postgresql://skg_marketing:CHANGE_ME@postgres:5432/skg_marketing
# Web login. Keep real password and session secret only on the server.
+PASSWORD_AUTH_ENABLED=false
WEB_AUTH_USERNAME=skg
WEB_AUTH_PASSWORD=
WEB_AUTH_SESSION_SECRET=
diff --git a/docs/source-analysis.html b/docs/source-analysis.html
index 28cadab..92e3ad8 100644
--- a/docs/source-analysis.html
+++ b/docs/source-analysis.html
@@ -536,7 +536,7 @@
| 生产站点 |
https://marketing.skg.com |
- 公司域名已解析到 VPS 76.13.31.179。线上由既有 Coolify / Traefik 负责 HTTPS 入口,项目 web 容器用 Nginx 承载静态前端;登录后根路径直接进入 Vue / Vite 个人生成画布,/canvas/ 只作为旧链接兼容跳转到根路径。/login/、/_next/、/assets/、/skg-logo-black.svg、/oasis-source/ 为公开登录页资源,未登录访问工作台跳转 /login/。登录页优先走飞书免登录,回调为 /api/auth/feishu/callback;账号密码保留为备用入口。/api/ 通过 auth_request 校验 FastAPI 会话 Cookie 后再反代,后端按 Cookie 里的用户身份隔离 Job 和 AgentRun 数据。 |
+ 公司域名已解析到 VPS 76.13.31.179。线上由既有 Coolify / Traefik 负责 HTTPS 入口,项目 web 容器用 Nginx 承载静态前端;登录后根路径直接进入 Vue / Vite 个人生成画布,/canvas/ 只作为旧链接兼容跳转到根路径。/login/、/_next/、/assets/、/skg-logo-black.svg、/oasis-source/ 为公开登录页资源,未登录访问工作台跳转 /login/。登录页只允许飞书免登录,回调为 /api/auth/feishu/callback;生产通过 PASSWORD_AUTH_ENABLED=false 停用账号密码入口。/api/ 通过 auth_request 校验 FastAPI 会话 Cookie 后再反代,后端按 Cookie 里的用户身份隔离 Job 和 AgentRun 数据。 |
| 画布构建 |
@@ -622,7 +622,7 @@
AdRecreationBoard 主题切换 | 左侧中段 65px 胶囊工具条上方图标组里有 Sun / Moon 图标按钮,切换 skg-board-theme--light 类名,并把选择写入 localStorage["skg-board-theme"]。暗色仍是默认模式;明亮模式只改变工作台外观,不改变任务、素材、分镜、模型调用或接口数据。 |
SourceReferenceBuildPanel | 旧的“相似主体 / 主体模板”大面板代码仍保留在文件里,方便以后恢复模板库复用、入库命名和自定义视图选择;但当前源视频工作区主路径已经由 SourceSubjectPipeline 承接,不再在页面下方渲染这块,避免和“参考帧池 → 转换层 → 主体元素”重复。 |
web/components/media-asset-tile.tsx | 项目内媒体素材缩略图基底组件:图片、视频、抽帧、产品图、相似主体图、首尾帧和视频候选默认从这里获得统一交互。组件负责缩略图显示、顶层固定浮层 hover 放大、删除按钮、下载/重新生成等操作按钮、忙碌遮罩、图片/视频共用预览,以及按场景启用原生视频播放 controls,避免每个新板块重复手写不同的媒体交互。hover 预览支持 previewPlacement 和 previewMaxWidth,视频候选可让操作按钮常显,保证下载入口不是隐藏语义;参考帧池用左侧紧凑预览避免遮住转换层;画面胶片是例外:为了保持胶片原位浏览,不使用额外弹出预览,只让胶片缩略图自己在轨道内放大。 |
- web/app/login/page.tsx | 生产登录页:先读取 /api/auth/config,飞书 OAuth 配好时显示“飞书免登录”主按钮,账号密码表单保留为备用入口;如果 feishu_enabled=true 且浏览器 UA 命中飞书 / Lark 客户端,会在登录页自动跳转 /api/auth/feishu/start,让飞书客户端内打开应用时不需要再点一次按钮;登录成功后由后端设置 HttpOnly 会话 Cookie。当前只在原版 Digital Oasis 动态背景上叠加一个组合登录框,桌面端左侧是动态角色,右侧是图标化登录区;面板左上角只展示官网 SKG 字标,不再并列中文系统名。 |
+ web/app/login/page.tsx | 生产登录页:先读取 /api/auth/config,飞书 OAuth 配好时显示“飞书免登录”主按钮;只有后端返回 password_enabled=true 时才展示账号密码表单。当前生产 PASSWORD_AUTH_ENABLED=false,所以普通浏览器也只显示飞书入口;如果 feishu_enabled=true 且浏览器 UA 命中飞书 / Lark 客户端,会在登录页自动跳转 /api/auth/feishu/start,让飞书客户端内打开应用时不需要再点一次按钮;登录成功后由后端设置 HttpOnly 会话 Cookie。当前只在原版 Digital Oasis 动态背景上叠加一个组合登录框,桌面端左侧是动态角色,右侧是图标化登录区;面板左上角只展示官网 SKG 字标,不再并列中文系统名。 |
web/app/login/layout.tsx | 登录路由专属 layout:覆盖全站默认网页标题和描述为空,避免 /login 继承工作台 metadata 后在页面源码里继续出现登录界面文字以外的文案。 |
web/components/login/oasis-canvas.tsx | 登录页全屏动态视觉层:用 iframe 直接承载下载包 web/public/oasis-source/index.html 的原 WebGPU / Three.js 草场源码;父级登录页只覆盖自己的文案和表单,并在捕获阶段把全局鼠标坐标同时用原生事件和 postMessage 转发给 iframe,避免登录面板或输入框遮挡时草地失去鼠标响应。 |
web/public/oasis-source/index.html | 从下载包 remix-3d-website-the-digital-o 复制来的原始视觉源码。嵌入登录页时会隐藏 demo 站自己的导航、文字和设置面板,保留原多段滚动背景变化、WebGPU 草场、景深、风动和鼠标交互源码;末端阶段保留,只禁用原 footer 出现时把 canvas 上移的逻辑,避免底部露黑边。 |
@@ -1078,7 +1078,7 @@ ProductRefStateItem {
| 功能 | 接口 | 前端调用 | 说明 |
- | 网页登录 / 飞书免登录 | GET /auth/config、GET /auth/feishu/start、GET /auth/feishu/callback、POST /auth/login、GET /auth/check、GET /auth/me、POST /auth/logout | web/app/login/page.tsx、Nginx auth_request | 登录页先读 /api/auth/config 判断是否显示飞书按钮;飞书客户端内且 feishu_enabled=true 时前端自动跳转授权入口,普通浏览器保留手动按钮和备用账号。飞书 OAuth 成功后后端用 open_id / union_id / email 生成多用户会话并设置 HttpOnly Cookie。账号密码登录保留为备用方式。生产 Nginx 对工作台和 /api/ 调 /auth/check 做统一校验,未登录页面跳 /login/?next=$request_uri,API 返回 JSON 401。 |
+ | 网页登录 / 飞书免登录 | GET /auth/config、GET /auth/feishu/start、GET /auth/feishu/callback、POST /auth/login、GET /auth/check、GET /auth/me、POST /auth/logout | web/app/login/page.tsx、Nginx auth_request | 登录页先读 /api/auth/config 判断是否显示飞书按钮和密码表单;飞书客户端内且 feishu_enabled=true 时前端自动跳转授权入口,普通浏览器保留手动飞书按钮。飞书 OAuth 成功后后端用 open_id / union_id / email 生成多用户会话并设置 HttpOnly Cookie。当前生产 PASSWORD_AUTH_ENABLED=false,因此 password_enabled=false,账号密码表单不展示,POST /auth/login 返回未配置。生产 Nginx 对工作台和 /api/ 调 /auth/check 做统一校验,未登录页面跳 /login/?next=$request_uri,API 返回 JSON 401。 |
| 运行配置 / 模型标注 | GET /health | getRuntimeHealth、ModelTrace | 返回 database 健康状态和 models:ASR、asr_language(默认 auto,表示中文/英文/多语言自动识别)、asr_base_url、asr_remote_enabled、asr_local_fallback_enabled、asr_audio_fallback_enabled、faster_whisper、本机 ASR、ASR fallback、翻译、GPT 改写、GPT 画面理解、产品视角识别 product_view、主图像模型 gpt-image-2、图片故障兜底 image_fallbacks、图片尺寸 image_size_options、短时熔断状态 image_circuit、主体 6 视图模型链路、Azure OpenAI TTS、视频别名、视频画幅 video_size_options、真实可用视频时长 video_duration_options、单条最大秒数 video_max_duration_seconds 和 Seedance 服务商。当前 REWRITE_MODEL、AUDIO_REWRITE_MODEL 和 VISION_MODEL 默认使用 gpt-4o;如果旧环境变量仍写 gemini-*,后端会归一化回 GPT_TEXT_MODEL / REWRITE_MODEL。语音只走 Azure OpenAI TTS,models.voice_tts_paths 会回传当前尝试的语音路径,方便区分路径错误和语音服务不可用。前端所有当前主路径里会调用模型的按钮旁显示模型名,点击弹出小窗口查看模型链路和输入输出逻辑;不返回 API Key、数据库密码或敏感凭证。 |
| 历史列表 | GET /jobs | listJobs | 当前登录用户可见 job 精简列表(id/url/status/thumbnail/mtime/owner…),按 state.json mtime 倒序。前端 URL 无 ?job= 时拉它回填本人历史;带 limit 可截断。开启数据隔离时,飞书用户只看到自己的任务,历史无 owner 的旧任务只对备用账号可见。 |
| 创建任务 | POST /jobs | createJob | 提交 TK 链接,后台开始下载;后端会把当前登录用户写入 Job.owner_*,后续详情、素材文件、删除和生成接口都通过统一中间件校验归属。下载阶段默认不带 cookies;生产环境必须显式保持 YTDLP_COOKIES_FILE= 和 YTDLP_COOKIES_FROM_BROWSER= 为空,避免容器内误读被打进镜像的开发 api/.env。 |
@@ -1241,6 +1241,18 @@ ProductRefStateItem {
变更记录
这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。
+
+
+ 2026-05-26 · 生产登录改为仅飞书
+ Auth
+ Ops
+
+
+
问题:飞书接入后继续保留共享密码入口,后续成员容易误用旧密码账号,导致新内容继续落到 password:skg,和飞书个人身份沉淀混在一起。
+
改动:api/main.py 新增 PASSWORD_AUTH_ENABLED 总开关;生产设为 false 后,/auth/config 返回 password_enabled=false,登录页不再展示账号密码表单,/auth/login 不再可用,旧密码 Cookie 会在校验时失效。WEB_AUTH_SESSION_SECRET 仍保留用于飞书会话签名,旧备用账号配置只作为应急恢复材料,不作为当前入口。
+
影响:新成员只能通过飞书登录,后续新建任务和画布都会绑定真实飞书 owner。旧 password:skg 数据不会自动归属到任何飞书用户,后续应通过公司可见/认领/管理员迁移处理。
+
+
2026-05-26 · 接入 Postgres 做公司内部沉淀