- New ARCHITECTURE.md (3-layer model + data flow + lifecycle matrix) - New PERMISSIONS.md (grant calculation rules + enforcement) - New ADMIN_GUIDE.md (華文极简:Customer/CustomerProduct 授权 + Product/Resource 管理) - Rewrite N8N_WORKFLOWS.md from WF1-6 (obsolete) to actual W1/W2/W3 - Update DATABASE_SCHEMA.md: fix status enum (drop 'disabled'), add 5-status semantics - Update README.md doc index
73 lines
3.7 KiB
Markdown
73 lines
3.7 KiB
Markdown
# 架构说明(Architecture)
|
||
|
||
> 本文解释系统的分层职责与数据流。更新日期 2026-08-23。
|
||
|
||
## 三层职责(核心心智模型)
|
||
|
||
| 层 | 载体 | 职责 | 谁改它 |
|
||
|---|---|---|---|
|
||
| **Account lifecycle** | `Customers.status` | 账户整体状态开关(active / pending / suspended / expired / deleted)| 管理员手工 |
|
||
| **Product entitlement** | `CustomerProducts` + `Products` + `Resources` | 「这个客户买了哪些产品 → 能访问哪些路径」+ 每个产品的到期时间 | 管理员手工 |
|
||
| **Effective permission** | AList Role `permission_scopes` | 最终生效的路径授权(由 n8n 从上面两层计算出来,写到 AList)| **仅 n8n**,管理员不直接碰 |
|
||
|
||
```
|
||
Customers.status (account-level:整户开关)
|
||
+
|
||
CustomerProducts (product entitlement:买了什么、何时到期)
|
||
+
|
||
Product → Resources (产品包含哪些路径)
|
||
+
|
||
CustomerProduct.expires_at
|
||
↓
|
||
calculateEffectiveGrants (n8n 共享算法,单一事实源)
|
||
↓
|
||
AList Role.permission_scopes (effective/materialized permission)
|
||
```
|
||
|
||
## 关键原则
|
||
|
||
1. **`Customers.status` 不进入权限计算**。它只决定「整户开关」:
|
||
- `active` → 允许计算并应用 grants
|
||
- `pending` / `suspended` / `expired` / `deleted` → AList user disabled + scopes 清空(账户级封禁)
|
||
- 权限的「细粒度」永远来自 CustomerProducts 的到期时间,不由 status 替代。
|
||
|
||
2. **AccessGrants 是预留的物化表,当前不经 n8n 写入**。将来(W4)可用于 reconciliation 日志/物化审计,但现在不作为 source-of-truth,也不参与计算。
|
||
|
||
3. **n8n 是同步器,不是 SOT**。Source of Truth = NocoDB;AList 只做 enforcement。
|
||
|
||
## 数据流
|
||
|
||
```
|
||
管理员在 NocoDB 改 Customers.status 或 CustomerProducts
|
||
│ (NocoDB webhook:after insert / after update)
|
||
▼
|
||
n8n W1 (Customer webhook) ── 处理整户 status lifecycle
|
||
n8n W2 (CustomerProduct webhook) ── 重算该客有效 grants 并应用
|
||
n8n W3 (每 5 分钟 schedule) ── 全量对账:重算所有客户,修 drift
|
||
│
|
||
▼
|
||
AList Admin API(role/update 写 permission_scopes;user/update 写 disabled)
|
||
```
|
||
|
||
- **W1** 单一 Code 节点:provision + status lifecycle(5 状态)+ 幂等 write-back。
|
||
- **W2** 单一 Code 节点:CustomerProduct 变更 → 重算该客 grants → diff → 应用。
|
||
- **W3** 单一 Code 节点:全量 sweep,逐客调共享算法,diff 后应用;支持 dry-run / auto-disable 开关。
|
||
|
||
三个 workflow 共用同一个 `calculateEffectiveGrants`(`n8n/shared/effective-grants.js`,构建时内联),保证三处算法零复制、零漂移。
|
||
|
||
## Status lifecycle(W1)
|
||
|
||
| status | AList user | scopes | 说明 |
|
||
|---|---|---|---|
|
||
| `pending`(无 user)| —(不建)| — | 纯标签,customer 未正式开通 |
|
||
| `pending`/`suspended`/`expired`/`deleted`(有 user)| disabled | 清空 | 账户级封禁,soft,保留历史 |
|
||
| `active`(无 user)| 新建 + enabled | 计算应用 | 首次开通 |
|
||
| `active`(有 user)| re-enable | 重算 + 应用 | 恢复/续期,永不恢复旧值 |
|
||
| 任意 `X → active` | enable | 重算(仅当前有效)| resume,忽略已过期产品 |
|
||
|
||
## Loop 防护
|
||
|
||
- n8n 只写回 bookkeeping 字段(`alist_user_id`/`alist_role_id`/`sync_status`/`sync_required`/`last_sync`/`last_sync_error`)。
|
||
- W1 用 **old/new field comparison**(NocoDB webhook 的 `previous_rows` vs `rows`)区分「管理员业务变更」vs「自己的 write-back echo」:echo 直接短路,零 PATCH。
|
||
- `writeBack()` 有值比对守卫:字段值没变就不发 PATCH,从物理上掐断 echo loop。
|