Files
hoelee 414bf31ba0 feat(n8n): W5 footer purchase-check webhook (公开只读) + docs
- W5 gets username ?u= → Customers→CustomerProducts → {username,known,purchases}
- 无 HMAC(密钥会下发客户端): 改用 CORS 限 drive.digikedai.com + 最小数据 + CF WAF 建议
- 复用现有 NOCODB_* env, 零新增 env
- 2 节点: webhook(GET, lastNode, CORS 头) + Code(w5-body.js)
- footer v2.6 动态行数据源; 待手动导入 n8n
- docs: N8N_WORKFLOWS + PROJECT_STATE 记录 W5 + 导入步骤
2026-08-28 18:24:42 +08:00

93 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Project State (Handoff) — 2026-08-25
> 交接文档:压缩/新会话后按此续做。**入口顺序:AGENTS.md → 本文件 → SECRETS.md(凭据)。**
> 本文件只记「状态与下一步」;API 怪癖/坑的唯一权威 = Hermes skill `alist-serve-resource` + `docs/API_INTEGRATION.md`。
## 凭据
全部集中在根目录 **`SECRETS.md`**(唯一凭据文件;把项目给别人 = 删它即可)。
表 ID / workflow ID 不是机密,见 `docs/DATABASE_SCHEMA.md` 与下文。
## 系统现状(2026-08-25 实测)
- 容器全绿:`alist-serve-resource`(healthy) · `nocodb` · `n8n` · `nginx-limit-alist` · `traefik-update-alist`(08-25 全部 redeploy)
- **公网上线 ✅**:`https://drive.digikedai.com` 经 CF Tunnel 全链路实测通
(/ping pong、/ 与 /login 均 200 AList SPA、/@manage 403 防护有效)
- W1–W4 四个 workflow 激活正常(postgres 复核 `activeVersionId` 全对齐;08-25 PUT 更新后仍对齐)
- **端到端实测通过 ✅(08-25)**:真实业务事件全链路——建 Customer→W1 自动开通+写回;
建 CP→W2 自动算 scopes(`/Class/Forex`);AList 真实登录/范围内 200/范围外 403;
CP 到期→W3 sweep 收权;Customer suspended→W1 禁用(客户 token 全 API 401);
active 恢复→重启用重算;人为漂移→W4 dryRun 只报告不写入 / 正式跑修复且幂等。
- **08-25 三处基础设施修复**:① AList `/user/update` 必须带 `username`(否则 400 静默不禁用)
→ w1/w3-body.js 已修并部署;② NocoDB 两 hook 改指 `http://n8n:5678`(原 auto.hoelee.com
走旧公网链路,VPS 卡顿时事件静默丢失),W2 hook 路径 `alist-cp-sync`→`alist-customerproduct-sync`
(原来一直 404);③ n8n API key 已入档 SECRETS.md。
- **n8n「执行消失」已结案**:容器 env `EXECUTIONS_DATA_SAVE_ON_SUCCESS=none`,成功执行不落库是配置使然,管道健康(详见下方结案记录)
- NocoDB 数据:Products 176 / Resources 171(商品目录健在);Customers/CustomerProducts 测试数据已清空(残留 1 行上个会话的 `e2e_test_01` 待用户处置);AList 仅 guest/hoelee(+e2e_test_01 残留)
## 已完成 ✅(细节见各 DESIGN 文档与 git log)
1. **Phase 1** AList stock v3.63.0 :5244(bridge_hoelee,4 只读挂载;旧 alist 已下线,compose 内注释保留)
2. **Phase 2** NocoDB base `AlistAccess`(`p3lzkresswyowqg`) 8 表(7 业务 + ReconcileLogs);脚本 `scripts/create_nocodb_schema.py` / `add_reconcilelogs_table.py`
3. **W1** 客户开通 + 5 状态 lifecycle(pending/active/suspended/expired/deleted)— 实测跑通;old/new 字段比对 loop guard + `sync_required` 强制重算 + writeBack 值比对守卫(`test_w1_lifecycle.js` 10 场景全过)
4. **W2** CustomerProduct 权限同步(调共享算法)— 实测跑通
5. **W3** 每 5 分钟 expiry sweep(`W3_DRY_RUN` / `ALIST_AUTO_DISABLE_ON_EXPIRE` 开关)— 实测跑通
6. **共享库** `n8n/shared/effective-grants.js` 单一事实源,构建期内联(`gen_w*.js`),三 workflow 零复制算法;union 语义:CP 派生 ∪ AccessGrants,同 path 取 MAX(expires_at),expiry 边界 `<= today`
7. **W4** 每日 03:00 全量对账 + ReconcileLogs 审计 — 本地 + 直连生产实测通过(dry-run→repair→复跑幂等;34 项 mock 测试过);单向同步 NocoDB=SOT,密码不随 repair 推送(方案 C)
8. 文档体系:ARCHITECTURE / PERMISSIONS / ADMIN_GUIDE / DATABASE_SCHEMA / N8N_WORKFLOWS 等;git 已推 Gitea
9. **公网链路切换(08-25)**:DSM 文件统一收进 `/volume1/docker/alist-digikedai/`(容器名全部未动——n8n `ALIST_URL` 硬依赖);CF Tunnel `drive.digikedai.com` 回源 `http://172.16.0.1:5246`;traefik 删除 `/login`→n8n 劫持路由(曾致登录页挂起);nginx 移除 drive 域不限速白名单(现吃默认 1.5MB/s + limit_conn 10/IP)。完整记录 = DSM `/volume1/docker/alist-digikedai/alist-serve-resource/NETWORK_ARCHITECTURE.md`
10. **W5 + footer v2.6(08-28)**:footer 动态购买行——本地解码用户 JWT 取 username → GET webhook `dk-purchase-check?u=` → NocoDB 查购买/到期 → 渲染。W5 源(`n8n/w5-body.js` + `gen_w5.js` → `W5-purchase-check.json`)已入库,**待用户手动导入 n8n + 激活**;footer v2.6 已部署线上(详见 dsm-resource-management `desc/DELIVERY_GUIDE.md` §7.10 + skill `alist-footer`)。实测 headless 9/9 PASS(含 CDP 模拟 W5 响应验证整链路)。安全= CORS 限 drive 域 + 最小数据 + 零新增 env(复用 NOCODB_*)
## 🔴 下一步(按序)
**(紧迫)手动导入 W5**:n8n → Import from File → `n8n/W5-purchase-check.json` → 激活 → 记 webhook URL
(`https://auto.hoelee.com/webhook/dk-purchase-check`)。测:`curl 'https://auto.hoelee.com/webhook/dk-purchase-check?u=tester'`
应回 `known:true` + 2 条 purchases。导入后 footer 动态行即自动上线(无需再改 footer)。
1. **补 n8n env 并 rebuild(Portainer stack 144,改 env 必须 rebuild)**:`NOCODB_TABLE_RECONCILELOGS=mktsb7le6fqr2u1` + `NOCODB_FK_RECONCILELOG_CUSTOMER=nc_jitu___Customers_id`(W4 审计落库当前被跳过);顺手加 `TZ=Asia/Kuala_Lumpur` 修 UTC 时区
2. **决策:auto.hoelee.com 是否退役/迁移**——n8n 公网访问现在只剩 UI 用途;hook 已容器化。若保留,建议迁到 CF Tunnel 新链路;若退役,同步删 VPS DNS + DSM 反代条目
3. **清理上个会话残留**:NocoDB Customer Id=8 `e2e_test_01` + AList user 17 / role `customer-e2e_test_01`
4. 公网限速实测:经 CF 后确认 nginx 限速按访客真实 IP 计(若 key 变 docker 内网 IP 全员共享一桶 → 调 traefik ipStrategy depth / nginx XFF)
5. 旧链路退役清理:旧 alist 数据目录、DSM 反代 access.hoelee.com 条目、VPS DNS、compose 注释块择机删
6. AList site_url 设为 `https://drive.digikedai.com`(分享链接需要)
7. 密码保持方案 C(客户可自改 AList 密码 → NocoDB plaintext 失真;不强制回写)
8. W2 不写 CP bookkeeping(sync_status/last_sync 永不更新)——现状可用;若未来有逻辑依赖这些字段再补写回节点
## 结案记录
- **CF Tunnel drive.digikedai.com 打不通(08-25 发现 → 当日结案)**
- 现象:公网 TCP/TLS 能建立但 HTTP 层零响应超时;DSM 内部链路对任意 Host 头都正常 → 不是 hostname 检查
- 根因:cloudflared 在 bridge_hoelee 网络,**容器→宿主机自身 LAN IP (192.168.1.1:5246) 被 DSM 防火墙 hairpin 丢弃**(日志 `dial tcp ... i/o timeout`);同隧道其他站点源是别的机器所以没事
- 修复:CF Dashboard 回源改 `http://172.16.0.1:5246`(docker0 网关=宿主机),实测公网 pong。备选:容器 DNS 名 `nginx-limit-alist:5246`
- 同场加映:traefik `rtr-alist-login` 把 GET /login 劫持到 n8n(:5678),n8n 无此路由 → 登录页挂起 499。已删路由 + 孤儿 middleware `mw-webhook-user-rewrite`(备份 dynamic.yml.bak-20260825)
- **n8n 执行管道停摆(08-23 报告 → 08-24 结案,误报)**
- 现象:webhook 全 200 但 executions 表零记录、schedule 无痕迹
- 根因:`EXECUTIONS_DATA_SAVE_ON_SUCCESS=none` → 成功执行从不落库,只有 error 会记(期间唯一入库记录恰是一条无关备份 workflow 的 error,完全吻合)
- 时间线:最后 success 记录 08-22 23:00:51Z ≈ 容器重建(08-23 01:21Z Started)前后;激活错位(activeVersionId)已在重建后修复
- 若要恢复可见性:env 改 `all` / `all-with-logs`(EXECUTIONS_DATA_PRUNE 已配,不会无限涨)
- 另注:DSM IP 已漂移为 `192.168.137.2`;Windows 直连内网端口(AList 5244 / NocoDB 10380 / n8n 5678)均通
## ⚠️ 坑速览(一行版;详情看 skill `alist-serve-resource` Pitfalls + API_INTEGRATION.md)
- AList:空 role 建用户必 400(先建 role)|base_path 必须 `/` 否则双重前缀全 403|delete 用 `?id=`|裸 token 无 Bearer
- NocoDB:link 查询必须 `(link.Id,eq,N)`|写 bt 链接要写 FK 列 `nc_jitu___*_id`|删行 DELETE+body|v1 列端点已废|SingleSelect 先建空列再 PATCH
- n8n:Code 节点 `$env` 可用、HTTP 表达式不行(Load Env 模式)|API 导入节点 id 必须 UUID 且顶层无 pinData|webhook 节点缺 webhookId 则生产 URL 不注册|激活真标志=DB 的 activeVersionId|执行消失假象=SAVE_ON_SUCCESS
- 环境:DSM IP 会漂移(连不上先探测,08-25 起在 192.168.137.2)|DSM sshd 无 SFTP(POST body 用 stdin pipe 传)|**容器→宿主 LAN IP 被 hairpin 丢包,回宿主机服务用 172.16.0.1 或容器 DNS 名**
> **Status 语义已定稿**:`pending/active/suspended/expired/deleted`,account-level 整户开关,
> **不进** permission calc。详见 `docs/ARCHITECTURE.md`、`docs/PERMISSIONS.md`、`docs/DATABASE_SCHEMA.md`。
## 项目结构
```
alist-serve-resource/
├── AGENTS.md ← 🤖 AI 会话入口(任务路由 + 铁律,开工先读)
├── SECRETS.md ← 🔑 唯一凭据文件(外发 = 删除此文件)
├── docker-compose.yml / .env.example / .gitignore
├── n8n/
│ ├── W1..W4-*.json (生成物,勿手编) · w1..w4-body.js (运行时逻辑源头)
│ ├── shared/effective-grants.js (算法单一事实源) · gen_w1..w4.js + inline_shared.js (构建)
│ ├── test_*.js · SETUP.md · W2/W3/W4-DESIGN.md
├── scripts/ create_nocodb_schema.py · add_reconcilelogs_table.py · live_dry_run_w4.js · healthcheck.sh
└── docs/ API_INTEGRATION · ARCHITECTURE · PERMISSIONS · ADMIN_GUIDE · DATABASE_SCHEMA ·
N8N_WORKFLOWS · PROJECT_STATE(本文件) · INSTALL · CONFIGURATION · SECURITY ·
BACKUP_RESTORE · UPGRADE · TROUBLESHOOTING · W4-DESIGN
```
## 待确认的设计点
1. AccessGrants 物化 —— **定案:不物化**(手工人为授权入口,n8n 永不写)
2. 密码失真 —— **定案:方案 C**(不强制回写;W4 repair 不推密码,仅 provision 新建时用)
3. 对账/到期只靠 n8n 定时扫描(AList 无 expiry 概念)—— 已确认