From 29ff66de88ae3ad181d50ee0a45588fb7d43da9f Mon Sep 17 00:00:00 2001 From: hoelee Date: Sun, 23 Aug 2026 07:50:25 +0800 Subject: [PATCH] =?UTF-8?q?docs(PROJECT=5FSTATE):=20sync=20handoff=20to=20?= =?UTF-8?q?final=20state=20(status=205-value=20=E5=AE=9A=E7=A8=BF,=20W4=20?= =?UTF-8?q?next)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix stale '待决策 status 语义' section (now 定稿 as 5 account-level statuses) - Rewrite 下一步 to reflect: features done + tested, remaining = reimport W1 to n8n for real acceptance, then W4 reconciliation, then AccessGrants design - Correct test count (W1 = 10 scenarios, not 26 assertions) - Add ARCHITECTURE/PERMISSIONS/ADMIN_GUIDE to project structure - Fix lifecycle value suspend_or_delete -> deactivate - Drop obsolete Load Env template (now in gen_w1.js) --- docs/PROJECT_STATE.md | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/docs/PROJECT_STATE.md b/docs/PROJECT_STATE.md index 82ff724..a4f78f1 100644 --- a/docs/PROJECT_STATE.md +++ b/docs/PROJECT_STATE.md @@ -76,16 +76,22 @@ Base: **`AlistAccess`**(`p3lzkresswyowqg`),与旧 `accessDB` 完全隔离 - expiry 边界 `<= today`;status 过滤非 active - **构建时内联**:`n8n/inline_shared.js` 的 `sharedSource()` 剥离 `module.exports`(`/* SHARED_EXPORT_BEGIN */` 之后),三个 `gen_w*.js` 把 body(`__SHARED_INLINE__` 占位)+ 共享源拼成 JSON - **W1/W2/W3 零复制算法**:三处都调同一个 `calculateEffectiveGrants` -- **测试**:`test_effective_grants.js`(共享算法 15 断言)、`test_w3_refactored.js`(W3 重构回归 13 断言)、`test_w1_lifecycle.js`(W1 lifecycle 幂等 26 断言)——全过 +- **测试**(全过):`test_effective_grants.js`(共享算法)、`test_w3_refactored.js`(W3 回归)、`test_w1_lifecycle.js`(W1 lifecycle,10 场景全覆盖:pending/active/suspended/expired/deleted 全转换 + echo 短路 + sync_required 强制重算) ## 🔴 下一步(按序) -1. **重新 import 三个 workflow**(W1/W2/W3 都改了:W1 status lifecycle + **loop guard 重写为 old/new 对比**)到 n8n,覆盖旧版本 -2. **实测 loop 修复**:NocoDB 改 customer.status 一次 → 应只产生**一次**真正 W1 execution(`active_provision` 或 `suspend_or_delete`),其后 echo 全是 `skip_writeback_echo`,不再无限 loop -3. **实测 W1 status lifecycle**:status=suspended → AList user disabled + scopes 清空;改回 active → re-enable + scopes 重算(不是恢复旧值);deleted → soft delete 不删 user -4. **⚠️ 待决策**:`Customers.status` 的 4 个值(active/expired/suspended/pending)最终权限语义——当前**不进** permission calc(W2/W3 只看 CP/expires_at),只被 W1 用 suspended/deleted/active 分支消费 -5. **(Step 4) W4 Full Reconciliation**:NocoDB desired vs AList actual 全量 drift 修复 -6. (Step 5 之后) 暂不做 hard delete(W6) -7. 本地 git 留档 + 验证稳定后推 Gitea(git.hoelee.com;凭据已脱敏 + 历史已重写) + +> 功能已全部实现并通过本地测试(用户已确认「已测试功能正常」)。剩余事项如下: + +1. **reimport W1 到 n8n 并做真实验收**(W2/W3 也重新生成过,可一并覆盖): + - 改 `Customers.status` 一次 → 只产生**一次**真正 W1 execution(`active_provision` 或 `deactivate`),其后 echo 全是 `skip_writeback_echo` + - 验证 W1 execution 的 `desiredPaths` 非空、AList role `permission_scopes` 落对 +2. **(Step 4) W4 Full Reconciliation**:NocoDB desired vs AList actual 全量 drift 修复 + reconciliation 日志(W3 已具备基础,W4 补每日全量 + 日志) +3. **(待设计) AccessGrants 物化**:当前 W2/W3 不写 AccessGrants 表,不作为 source-of-truth。W4 时统一设计 reconciliation/materialization 策略 +4. 密码回写问题(客户自改 AList 密码 → NocoDB plaintext 失真):当前不强制回写(用户已选方案 C),必要时再议 +5. 本地 git 已留档并推 Gitea(`git.hoelee.com/hoelee/alist-serve-resource`,凭据已脱敏) + +> ⚠️ **Status 语义已定稿(不再待决策)**:5 个值 `pending/active/suspended/expired/deleted`, +> account-level 整户开关,**不进** permission calc。详见 `docs/ARCHITECTURE.md`、`docs/PERMISSIONS.md`、`docs/DATABASE_SCHEMA.md`。 ## 🐛 已沉淀的坑(勿再踩) - **AList**: @@ -107,21 +113,7 @@ Base: **`AlistAccess`**(`p3lzkresswyowqg`),与旧 `accessDB` 完全隔离 - Code 节点内 `$env` ✅(**用户实测可用**,如 `$env.NOCODB_URL`) - HTTP 节点表达式字段里 `$env` / `process.env` ❌ 都不行 - 模式:step 2 放 "Load Env" Code 节点输出全部 env **并透传 payload 字段**,下游 HTTP 用 `$('Load Env').item.json.VAR` - - step 2 已验证模板: - ```js - const prev = $input.item.json; - return { json: { - customerId: prev.customerId, - eventType: prev.eventType, - NOCODB_URL: $env.NOCODB_URL, - NOCODB_TOKEN: $env.NOCODB_TOKEN, - T_CUSTOMERS: $env.NOCODB_TABLE_CUSTOMERS, - ALIST_URL: $env.ALIST_URL, - ALIST_ADMIN_USERNAME: $env.ALIST_ADMIN_USERNAME, - ALIST_ADMIN_PASSWORD: $env.ALIST_ADMIN_PASSWORD, - ALIST_ADMIN_OTP: $env.ALIST_ADMIN_OTP || '', - } }; - ``` + - `gen_w*.js` 里的 Load Env 节点已含所有表 env + `previousRow`/`newRow` 透传(W1);直接看 `n8n/gen_w1.js` 最新版为准 - **Webhook write-back loop(2026-08-23 已修)**: - 症状:n8n 写回 NocoDB(sync_status 等)→ 触发 webhook → 又写回 → 无限循环;且 `sync_status==='synced'` 做 guard 不可靠(suspend 分支也写 synced) @@ -141,10 +133,10 @@ alist-serve-resource/ │ test_effective_grants.js · test_w1_lifecycle.js · test_w3_refactored.js │ SETUP.md · W2-DESIGN.md · W3-DESIGN.md ├── scripts/ create_nocodb_schema.py · healthcheck.sh -└── docs/ API_INTEGRATION.md · DATABASE_SCHEMA.md · INSTALL.md · CONFIGURATION.md · SECURITY.md · BACKUP_RESTORE.md · UPGRADE.md · TROUBLESHOOTING.md · PROJECT_STATE.md +└── docs/ API_INTEGRATION.md · ARCHITECTURE.md · PERMISSIONS.md · ADMIN_GUIDE.md · DATABASE_SCHEMA.md · N8N_WORKFLOWS.md · INSTALL.md · CONFIGURATION.md · SECURITY.md · BACKUP_RESTORE.md · UPGRADE.md · TROUBLESHOOTING.md · PROJECT_STATE.md ``` ## 待确认的设计点 -1. W2 当前不写 AccessGrants 表 —— 是否在验证后补物化写入?(避免 AccessGrant→n8n loop 的前提下,由 W2 单向写) +1. **AccessGrants 物化**(已定:本次不物化,不作为 source-of-truth)—— W4 时统一设计 reconciliation/materialization 策略,需避免 AccessGrant→n8n loop 2. 密码:客户可自改 AList 密码 → NocoDB plaintext 会失真;当前不强制回写(用户已选方案 C) 3. 对账/到期只靠 n8n 定时扫描(AList 无 expiry 概念)—— 已确认 \ No newline at end of file