From e25cd94b0c599217b4e863a83ae6afe04b6a5da0 Mon Sep 17 00:00:00 2001 From: jackyu66git Date: Fri, 7 Aug 2026 17:47:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(ECR-013B):=20AccountLifecycle=20Closed?= =?UTF-8?q?=EF=BC=9B=E5=90=AF=E7=94=A8=20Loop=20=E8=BF=9E=E7=BB=AD?= =?UTF-8?q?=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UserStatus 迁移、DeviceAuth 拒绝非 active、admin-h5 CTA; Reviewer Closed。Human 授权 LOOP_AUTHORIZATION(免逐闸确认)。 Co-authored-by: Cursor --- .ai/product/feature-map.md | 2 +- .ai/product/feature-spec/README.md | 2 +- .../feature-spec/ops-account-lifecycle.md | 10 +- .ai/product/feature-spec/ops-admin.md | 3 +- apps/admin-h5/src/api/client.ts | 13 ++ apps/admin-h5/src/pages/UserDetailPage.vue | 62 ++++++- apps/api/internal/handler/admin.go | 1 + apps/api/internal/handler/admin_lifecycle.go | 78 ++++++++ apps/api/internal/handler/auth.go | 9 + .../integration/admin_lifecycle_test.go | 166 ++++++++++++++++++ apps/api/internal/middleware/device.go | 20 +++ .../repository/account_lifecycle_repo.go | 104 +++++++++++ apps/api/internal/service/admin/lifecycle.go | 76 ++++++++ apps/api/internal/service/admin/rbac.go | 2 + apps/api/internal/service/auth/service.go | 9 + .../000016_account_lifecycle.down.sql | 3 + .../000016_account_lifecycle.up.sql | 20 +++ .../BD-2026-013B-account-lifecycle.md | 5 +- docs/CHANGELOG.md | 9 +- docs/CODE_REVIEW/ECR-013B.md | 37 ++++ docs/ECR/ECR-013B-account-lifecycle.md | 12 +- .../ECR-013B-account-lifecycle.md | 4 +- .../HANDOFF/ECR-013B-architect-to-engineer.md | 9 +- docs/HANDOFF/ECR-013B-engineer-to-reviewer.md | 20 +++ .../ECR-013B-account-lifecycle.md | 4 +- docs/PROJECT_PROFILE.md | 4 +- docs/STATE/ECR-013B.md | 15 +- docs/TASKS/TASK-013B-ECR013B.yaml | 23 ++- docs/TEST_REPORT/ECR-013B.md | 45 +++++ docs/TRACEABILITY.md | 2 +- docs/WAVE0/HUMAN_REVIEW.md | 6 +- docs/WAVE0/LOOP_AUTHORIZATION.md | 33 ++++ proto/openapi.yaml | 47 +++++ 33 files changed, 799 insertions(+), 56 deletions(-) create mode 100644 apps/api/internal/handler/admin_lifecycle.go create mode 100644 apps/api/internal/integration/admin_lifecycle_test.go create mode 100644 apps/api/internal/repository/account_lifecycle_repo.go create mode 100644 apps/api/internal/service/admin/lifecycle.go create mode 100644 apps/api/migrations/000016_account_lifecycle.down.sql create mode 100644 apps/api/migrations/000016_account_lifecycle.up.sql create mode 100644 docs/CODE_REVIEW/ECR-013B.md create mode 100644 docs/HANDOFF/ECR-013B-engineer-to-reviewer.md create mode 100644 docs/TEST_REPORT/ECR-013B.md create mode 100644 docs/WAVE0/LOOP_AUTHORIZATION.md diff --git a/.ai/product/feature-map.md b/.ai/product/feature-map.md index 7e77fc4..56fc73c 100644 --- a/.ai/product/feature-map.md +++ b/.ai/product/feature-map.md @@ -235,7 +235,7 @@ UI **不出现「塔罗」**。禁止神谕吉凶、恐吓话术。 | Phase A `[Ops]` | 登录 · 用户/订单查询 · 会员授予 · 审计 · `apps/admin-h5`(ECR-006 Closed) | | Phase B `[Ops]` | 行为分析:自有埋点 + 管理端「数据」看板(**ECR-007 Closed** · Spec `ops-analytics.md`) | | Phase C `[Ops]` | 内容:首页宫格 CRUD · 测评上下架(**ECR-008 Closed** · Spec `ops-content.md`) | -| Phase D+ | **Contract-First**:Capability→BC→Domain→API(+contract_diff)→四类 AC,再 ECR 切片。**ECR-013A Closed** → **ECR-013B** AccountLifecycle(Contract Definition)。详见 `docs/WAVE0/`。 | +| Phase D+ | **Contract-First**:**ECR-013A Closed** → **ECR-013B Implemented(review)**。详见 `docs/WAVE0/`。 | | 排除 | **UGC / 社区广场**(M10.2)仍 `[No]`;真支付最后 | 不计入 P1 Complete;不进入五 Tab。 diff --git a/.ai/product/feature-spec/README.md b/.ai/product/feature-spec/README.md index 79b633e..9de4cc2 100644 --- a/.ai/product/feature-spec/README.md +++ b/.ai/product/feature-spec/README.md @@ -24,7 +24,7 @@ | [ops-analytics.md](ops-analytics.md) | 运营行为分析(埋点+数据看板) | §7 | `admin-h5` `/analytics` · H5 track | Ops-B · ECR-007 Closed | | [ops-content.md](ops-content.md) | 运营内容(宫格+测评上下架) | §7 | `admin-h5` `/content` · `GET /home/tools` | Ops-C · ECR-008 Closed | | [ops-rbac.md](ops-rbac.md) | 运营 RBAC | §7 | `admin-h5` `/me` permissions · `/admin/roles*` | Ops-D · **ECR-013A Closed** | -| [ops-account-lifecycle.md](ops-account-lifecycle.md) | 账户生命周期 / UserStatus | §7 | `admin-h5` 用户详情 status CTA · C 端拒绝 | Ops-D · **ECR-013B Draft(契约)** | +| [ops-account-lifecycle.md](ops-account-lifecycle.md) | 账户生命周期 / UserStatus | §7 | `admin-h5` 用户详情 status CTA · C 端拒绝 | Ops-D · **ECR-013B Closed** | 新功能:复制 `_TEMPLATE.md` → 填满 → 在本表登记 → 再编码。 diff --git a/.ai/product/feature-spec/ops-account-lifecycle.md b/.ai/product/feature-spec/ops-account-lifecycle.md index 944aff0..5e4c692 100644 --- a/.ai/product/feature-spec/ops-account-lifecycle.md +++ b/.ai/product/feature-spec/ops-account-lifecycle.md @@ -1,8 +1,8 @@ # Feature Spec: 账户生命周期 / UserStatus(Ops · ECR-013B) -> Status: `Active`(契约定义)· Map: `§7 运营后台` · Phase: `Ops-D` +> Status: `Active`(**Closed** · Feature Complete)· Map: `§7 运营后台` · Phase: `Ops-D` > Parent: **WAVE0-FROZEN** (`27f27a1`) · Predecessor: **ECR-013A Closed** -> ESS: `docs/ECR/ECR-013B-account-lifecycle.md`(Draft · Contract Definition · **禁止编码**) +> ESS: `docs/ECR/ECR-013B-account-lifecycle.md`(**Closed**) > Capability: `AccountLifecycle` · BC: `Identity_Profile` > 模板:`docs/WAVE0/contracts/OPS-CONTRACT-TEMPLATE.md` @@ -10,9 +10,9 @@ ## ESS 门禁 -1. Change Level = **L2** → 须 ECR + BD **Approved** 后方可改 `apps/` -2. **当前阶段:Contract Definition only**(Start Authorization 2026-08-07)— 禁止 migration / handler / DeviceAuth 改动 -3. 实现轮:TEST_REPORT 映射全部 AC-ID · contract_diff · boundary-rules 复核 +1. Change Level = **L2** → 已 Approved + Coding auth + Implemented + **Closed** +2. ~~Contract Definition only~~ — 已完成 +3. 实现证据:`docs/TEST_REPORT/ECR-013B.md` · `docs/CODE_REVIEW/ECR-013B.md` --- diff --git a/.ai/product/feature-spec/ops-admin.md b/.ai/product/feature-spec/ops-admin.md index d17a1ae..dfd577e 100644 --- a/.ai/product/feature-spec/ops-admin.md +++ b/.ai/product/feature-spec/ops-admin.md @@ -209,6 +209,7 @@ Phase A 可先 `console`/本地;不挡验收。 | **B(ECR-007 Closed)** | 自有埋点 · 管理端「数据」看板 — Spec `ops-analytics.md` | | **C(ECR-008 Closed)** | 首页宫格 CRUD · 测评上下架 — Spec `ops-content.md` | | **E(ECR-013A Closed)** | Admin RBAC — Spec `ops-rbac.md` · Parent WAVE0-FROZEN | -| **F(ECR-013B Draft)** | AccountLifecycle — Spec `ops-account-lifecycle.md` · **契约中,禁 coding** | +| **F(ECR-013B Closed)** | AccountLifecycle — Spec `ops-account-lifecycle.md` | +| **G(ECR-014)** | MembershipPlan — CommerceEntitlement 薄切片(Loop continuous) | | D | 订单筛选 · 展示价 · 退款只读(另开 ECR) | | 后置 | 封禁加深(Account_Risk)· 推送占位 | diff --git a/apps/admin-h5/src/api/client.ts b/apps/admin-h5/src/api/client.ts index 5d32a29..5bbc8c8 100644 --- a/apps/admin-h5/src/api/client.ts +++ b/apps/admin-h5/src/api/client.ts @@ -117,6 +117,19 @@ export const adminApi = { users: (q = '') => request<{ items: UserListItem[] }>('GET', `/users?q=${encodeURIComponent(q)}`), user: (id: string) => request('GET', `/users/${id}`), + setUserStatus: (id: string, status: string, reason: string) => + request('POST', `/users/${id}/status`, { status, reason }), + statusTransitions: (id: string) => + request<{ + items: Array<{ + id: string + from_status: string + to_status: string + admin_id: string + reason: string + created_at: string + }> + }>('GET', `/users/${id}/status-transitions`), grant: (id: string, plan: string) => request<{ ok: boolean }>('POST', `/users/${id}/membership/grant`, { plan }), grantAskQuota: (id: string, delta: number) => diff --git a/apps/admin-h5/src/pages/UserDetailPage.vue b/apps/admin-h5/src/pages/UserDetailPage.vue index 3b6261a..28bf653 100644 --- a/apps/admin-h5/src/pages/UserDetailPage.vue +++ b/apps/admin-h5/src/pages/UserDetailPage.vue @@ -1,9 +1,11 @@