auto-save 2026-05-15 15:21 (+1, ~9)

This commit is contained in:
2026-05-15 15:21:20 +08:00
parent 7ee9ea2303
commit f7cc49a455
10 changed files with 540 additions and 24 deletions

View File

@@ -32,11 +32,14 @@ cp deploy/.env.production.example deploy/.env.production
Fill `deploy/.env.production` with the real production keys. Keep this file out of git.
Create the production login file. Replace the username and password as needed:
Create the production web login values in `deploy/.env.production`. Replace the password as needed and keep the session secret private:
```bash
printf 'skg:%s\n' "$(openssl passwd -apr1 'change-this-password')" > deploy/.htpasswd
chmod 644 deploy/.htpasswd
WEB_AUTH_USERNAME=skg
WEB_AUTH_PASSWORD=change-this-password
WEB_AUTH_SESSION_SECRET=$(openssl rand -hex 32)
WEB_AUTH_COOKIE_NAME=skg_marketing_session
WEB_AUTH_COOKIE_SECURE=true
```
Then start:
@@ -49,7 +52,8 @@ Verify:
```bash
curl -I https://marketing.skg.com
curl https://marketing.skg.com/api/health
curl -I https://marketing.skg.com/login/
curl -i https://marketing.skg.com/api/health
docker compose -f docker-compose.prod.yml ps
```
@@ -64,7 +68,7 @@ docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -
## Runtime Notes
- `web` is a static Next export served by Nginx.
- `web` requires Nginx Basic Auth for the whole site and then proxies `/api/` to `skg-marketing-api:4291`; avoid the generic hostname `api` because the web container also joins the shared Coolify network.
- `web` exposes `/login/` publicly. All workspace routes redirect to `/login/` until the FastAPI session cookie passes Nginx `auth_request`; `/api/` returns JSON 401 when unauthenticated and then proxies to `skg-marketing-api:4291` after login.
- `api` is only on the internal project network and stores jobs under `/data/jobs`.
- Server-side job files persist in `./data/jobs` on the VPS.
- Large uploads are allowed up to `2g` at the Nginx proxy layer.

View File

@@ -536,7 +536,7 @@
<tr>
<td>生产站点</td>
<td><code>https://marketing.skg.com</code></td>
<td>公司域名已解析到 VPS <code>76.13.31.179</code>。线上由既有 Coolify / Traefik 负责 HTTPS 入口,项目 <code>web</code> 容器用 Nginx 承载静态前端、执行 Basic Auth 登录,并把 <code>/api/</code> 反代到 FastAPI</td>
<td>公司域名已解析到 VPS <code>76.13.31.179</code>。线上由既有 Coolify / Traefik 负责 HTTPS 入口,项目 <code>web</code> 容器用 Nginx 承载静态前端;未登录访问工作台跳转 <code>/login/</code><code>/api/</code> 通过 <code>auth_request</code> 校验 FastAPI 会话 Cookie 后再反代</td>
</tr>
<tr>
<td>生产部署</td>
@@ -591,6 +591,7 @@
<table>
<tbody>
<tr><td><code>web/app/page.tsx</code></td><td>产品工作台主状态jobs、activeJobId、按 job 隔离的 selectedFrames/详情面板状态、clipboard、ReactFlow 节点和边;负责打开/找回画布工作面板。</td></tr>
<tr><td><code>web/app/login/page.tsx</code></td><td>生产登录页:账号密码表单、保持登录、错误/成功状态,以及参考风格库 14 的四个动画角色互动。</td></tr>
<tr><td><code>web/components/nodes/index.tsx</code></td><td>DAG 节点定义Input、VisualLab、Audio、Compose以及画布工作面板 KeyframePanel / VideoFramePanel旧 Keyframe/Storyboard/VideoGen 组件保留但不再挂主画布。</td></tr>
<tr><td><code>web/components/audio-strip.tsx</code></td><td>底部吸附音频条:可拖拽调整高度;播放原音频时移动指针,逐个高亮英文/中文字幕节点和对应波形,并在右侧固定显示按原音频时长生成的 SKG 英文产品口播和 MiniMax 随机英文配音。</td></tr>
<tr><td><code>web/components/lightbox.tsx</code></td><td>关键帧素材准备面板:清洗、统一主体候选、参考帧网格、六张主体重绘图、每帧去主体场景图、纵向 6 行产品融合镜头工作表和审核。</td></tr>
@@ -605,7 +606,7 @@
<h3>后端核心</h3>
<table>
<tbody>
<tr><td><code>api/main.py</code></td><td>FastAPI 单文件后端状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 英文配音、文件返回。</td></tr>
<tr><td><code>api/main.py</code></td><td>FastAPI 单文件后端:登录会话、状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、音频文案改写、MiniMax 英文配音、文件返回。</td></tr>
<tr><td><code>api/product_library/skg-products</code></td><td>内置 SKG 白底产品图库:<code>manifest.json</code> 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图,<code>images/</code> 存 45 张参考图。</td></tr>
<tr><td><code>jobs/&lt;jobId&gt;/state.json</code></td><td>运行时状态文件,不在源码列表里,但刷新恢复依赖它。</td></tr>
<tr><td><code>jobs/&lt;jobId&gt;/audio.wav</code></td><td>拆轨得到的原始音频,底部 Audio Strip 会通过只读接口拉取并在浏览器里解码成波形峰值。</td></tr>
@@ -806,6 +807,7 @@ SubjectAsset {
<tr><th>功能</th><th>接口</th><th>前端调用</th><th>说明</th></tr>
</thead>
<tbody>
<tr><td>网页登录</td><td><code>POST /auth/login</code><code>GET /auth/check</code><code>POST /auth/logout</code></td><td><code>web/app/login/page.tsx</code>、Nginx <code>auth_request</code></td><td>登录页提交账号密码到 <code>/api/auth/login</code>,后端设置 HttpOnly 会话 Cookie生产 Nginx 对工作台和 <code>/api/</code><code>/auth/check</code> 做统一校验,未登录页面跳 <code>/login/</code>API 返回 JSON 401。</td></tr>
<tr><td>历史列表</td><td><code>GET /jobs</code></td><td><code>listJobs</code></td><td>所有 job 精简列表id/url/status/thumbnail/mtime…按 state.json mtime 倒序。前端 URL 无 <code>?job=</code> 时拉它回填全部历史;带 <code>limit</code> 可截断。</td></tr>
<tr><td>创建任务</td><td><code>POST /jobs</code></td><td><code>createJob</code></td><td>提交 TK 链接,后台开始下载,停在 downloaded 等用户点解析。</td></tr>
<tr><td>上传视频</td><td><code>POST /jobs/upload</code></td><td><code>uploadJob</code></td><td>保存 source.mp4然后同样进入下载完成状态。</td></tr>
@@ -941,14 +943,15 @@ SubjectAsset {
<div class="changelog">
<article class="change">
<header>
<h3>2026-05-15 · 生产站点增加登录保护</h3>
<h3>2026-05-15 · 生产站点增加应用内登录页</h3>
<span class="tag gray">Runtime</span>
<span class="tag blue">Security</span>
<span class="tag rose">UI</span>
</header>
<div class="body">
<p><strong>问题:</strong>公司域名部署后任何人知道地址都能打开工作台并调用生成能力。</p>
<p><strong>改动:</strong>在生产 <code>web</code> Nginx 容器增加 Basic Auth整站和 <code>/api/</code> 统一要求账号密码;哈希文件挂载自服务器 <code>/opt/skg-marketing-studio/deploy/.htpasswd</code>,明文密码只保存在服务器 root 说明文件,不入库</p>
<p><strong>影响:</strong><code>docker-compose.prod.yml</code><code>deploy/nginx.conf</code><code>.gitignore</code><code>.project.json</code><code>RULES.md</code><code>docs/deploy-vps.md</code><code>docs/source-analysis.html</code></p>
<p><strong>改动:</strong>把浏览器 Basic Auth 改为应用内登录页:前端新增 <code>web/app/login/page.tsx</code>,参考风格库 <code>14 动画角色登录</code> 做四个几何角色、鼠标视线跟随、输入 / 显示密码 / 错误 / 成功状态反馈;后端新增 <code>/auth/login</code><code>/auth/check</code><code>/auth/logout</code>,使用 HttpOnly Cookie + HMAC 会话签名;生产 Nginx 通过 <code>auth_request</code> 保护工作台和 <code>/api/</code></p>
<p><strong>影响:</strong><code>api/main.py</code><code>web/app/login/page.tsx</code><code>web/app/globals.css</code><code>web/lib/api.ts</code><code>docker-compose.prod.yml</code><code>deploy/nginx.conf</code><code>deploy/.env.production.example</code><code>api/.env.example</code><code>.project.json</code><code>RULES.md</code><code>docs/deploy-vps.md</code><code>docs/source-analysis.html</code></p>
</div>
</article>
<article class="change">