- Root cause: EXECUTIONS_DATA_SAVE_ON_SUCCESS=none -> successful executions
never persisted; only errors land in execution_entity
- W1-W4 activation verified healthy post-recreate (activeVersionId aligned)
- NocoDB test data wiped (Customers/CP=0; catalog 176/171 intact)
- AList orphan accounts cleaned: users TEST-Alice/mama/hoe/test and roles
customer-*+newrole removed; only guest+hoelee remain
- Next step reprioritized: end-to-end live test (W1->W2->W3)
- Added current workflow IDs + drifting DSM IP to credential quick-ref
- 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)
- Non-active statuses (pending/suspended/expired/deleted) now uniformly:
disable AList user + clear role scopes (soft, keeps user/role/CP/history);
no-op when the customer has no AList user yet (pure NocoDB label).
- Resume transitions (X -> active) recompute effective grants from current
CustomerProducts + expiry, never restore stale scopes.
- businessChanged() now also treats after-insert (new row, no previous) as a
business change so fresh customers are processed on first webhook.
- Lifecycle test covers the full matrix: 10 scenarios, all green.
- AccessGrants still not materialized (deferred to W4 per decision).
- Customers.status stays account-level, outside permission calc.
- Replace brittle sync_status==='synced' loop guard with NocoDB v2
old/new row comparison (previous_rows vs rows).
- businessChanged() = business field move OR sync_required set; echo
(bookkeeping-only delta) -> skip_writeback_echo, zero AList mutation.
- writeBack() value-change guard: GET live record, PATCH only fields
whose value actually changes (no-change -> no PATCH -> no webhook).
- sync_required Checkbox honored as force-reprocess flag, cleared on write-back.
- Extract-id node passes previousRow/newRow through Load Env to lifecycle.
- W1 lifecycle test now covers echo suppression (26 assertions).
- Customers.status still NOT consumed by permission calc (TBD semantics).
- W2/W3 effective-grants semantics unchanged.
- Extract calculateEffectiveGrants into n8n/shared/effective-grants.js
(single source of truth), inlined at build time into W1/W2/W3 via
gen_w*.js + inline_shared.js — removes the duplicated algorithm.
- W1 now provisions with a status branch:
suspended/deleted -> disable AList user + clear role scopes (soft delete)
active -> create/update user+role, RECOMPUTE desired scopes (never restore
stale), re-enable
- Loop guard corrected: check AList user LIVE disabled state via
GET /api/admin/user/get (sync_status alone breaks suspend->resume).
- W2/W3 rebuilt on shared lib (identical behaviour).
- Tests: test_effective_grants.js (15), test_w3_refactored.js (13),
test_w1_lifecycle.js (23) — all green.
- Drop superseded w2-compute.js / w3-compute.js / test_w3.js.