Files
digital-psychology/.ai/product/feature-spec/ops-account-lifecycle.md
T
jackyu66gitandCursor e25cd94b0c feat(ECR-013B): AccountLifecycle Closed;启用 Loop 连续执行
UserStatus 迁移、DeviceAuth 拒绝非 active、admin-h5 CTA;
Reviewer Closed。Human 授权 LOOP_AUTHORIZATION(免逐闸确认)。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 17:47:18 +08:00

157 lines
5.4 KiB
Markdown
Raw 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.
# Feature Spec: 账户生命周期 / UserStatusOps · ECR-013B
> 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`**Closed**
> Capability: `AccountLifecycle` · BC: `Identity_Profile`
> 模板:`docs/WAVE0/contracts/OPS-CONTRACT-TEMPLATE.md`
---
## ESS 门禁
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`
---
## L0 Capability
| 字段 | 内容 |
|------|------|
| Capability ID | `AccountLifecycle` |
| Purpose | 以可审计状态机管理 C 端用户账户启停与封禁,阻断违规会话 |
| Why now | `users.status` 字段已存在但无运营迁移与强制拒绝;013A 权限面就绪后可挂状态写权限 |
| Non-goals | soft-delete / `deleted`;UGC 社区封禁;真支付;Admin 账号启停(已有 admin.status);推送通知 |
---
## L1 Bounded Context
| 字段 | 内容 |
|------|------|
| Primary BC | `Identity_Profile` |
| owns | `User` · `UserStatus` · `AccountStateTransition` |
| does_not_own | `AdminRole` · `Membership` · `Payment` · `BanRecord`Account_Risk 后置加深) |
| allowed | `Admin_Auth_Audit.write_audit`(经 admin 调用) |
| forbidden | `Payment` · `Membership.write` · soft-delete User |
权威:`.ai/domain/boundary-rules.md` · `Account_Risk` 仅允许经明确服务触发 `UserStatus.transition`
---
## 1. 功能定义
| 字段 | 内容 |
|------|------|
| Name | Account Lifecycle / UserStatus |
| Purpose | 运营可迁移用户状态;非 active 会话在 C 端被拒绝 |
| Business Goal | 风险处置最小闭环,不引入社区/UGC |
| In | Out |
|---|---|
| 状态机 `active/disabled/banned/suspended` | soft-delete / GDPR 擦除 |
| Admin 迁移 API + AuditLog + Transition 记录 | 站内推送 / 短信 |
| DeviceAuth / Bearer 对非 active 拒绝 | AdminAccount.status013A 外) |
| 权限码 `admin.users.status.write` | 行级数据 ACL |
---
## L2 Domain
| Entity | 不变式 / 状态机 |
|--------|----------------|
| `UserStatus` | 取值冻结:`active` · `disabled` · `banned` · `suspended`;非法值拒写 |
| `User.status` | 与 `UserStatus` 同值;默认 `active`(已有列) |
| `AccountStateTransition` | 只追加;记录 from→to · admin_id · reason · created_at |
### 合法迁移
```text
active → disabled | banned | suspended
disabled → active | banned
suspended → active | banned | disabled
banned → active | disabled
```
其它边 → **400**。同状态写 → **400**(幂等拒绝,避免空审计噪音)。
### C 端效应
| Status | DeviceAuth / 已登录 Bearer |
|--------|------------------------------|
| `active` | 放行 |
| `disabled` / `banned` / `suspended` | **401**(或 403 统一码,实现轮定一)+ 不可发新 session |
---
## L3 API Contract(意图 · 实现轮同步 OpenAPI)
前缀:`/api/v1/admin` · AdminAuth · 信封 `{code,message,data}`
| Method | Path | 权限 | 语义 |
|--------|------|------|------|
| POST | `/users/:id/status` | `admin.users.status.write` | 迁移 UserStatus;写 Transition + AuditLog |
| GET | `/users/:id/status-transitions` | `admin.users.read` | 最近迁移列表(limit |
既有 `GET /users` · `GET /users/:id` 已暴露 `status` — 保持;实现轮确认枚举文档化。
`contract_diff``docs/CONTRACT_DIFF/ECR-013B.yaml`
RBAC catalog **additive**`admin.users.status.write` → 种子写入 `super_admin`migration)。
---
## L4 Acceptance Criteria
### Functional
| ID | Given | When | Then |
|----|-------|------|------|
| AC-F-01 | 用户 `active` | POST status=`banned` + reason | 200GET user.status=`banned` |
| AC-F-02 | 用户 `banned` | POST status=`active` | 200;可再次 DeviceAuth |
| AC-F-03 | 非法边(如 `active``active` | POST | **400** |
| AC-F-04 | GET status-transitions | — | 含最近 from/to/admin/reason |
### Security
| ID | Given | When | Then |
|----|-------|------|------|
| AC-S-01 | Admin 无 `admin.users.status.write` | POST status | **403** + deny audit |
| AC-S-02 | 用户 `banned` | C 端带原 Bearer 访问受保护 API | **401/403** |
| AC-S-03 | 仅 DeviceAuth 无 Admin | POST `/admin/users/:id/status` | **401** |
| AC-S-04 | 无 Admin session | GET transitions | **401** |
### Performance
| ID | Given | When | Then |
|----|-------|------|------|
| AC-P-01 | transitions ≤1000 行/用户 | GET transitions limit=50 | 本机 P95 **&lt; 500ms** |
### Observability
| ID | Given | When | Then |
|----|-------|------|------|
| AC-O-01 | 迁移成功 | — | AuditLog action=`users.status.transition` |
| AC-O-02 | 迁移成功 | — | `account_state_transitions` 有对应行 |
---
## Forbidden(本切片)
- soft-delete / `deleted` 状态
- 真支付 · UGC · Prompt · 兑换码 · Crisis 深化
- 改 Admin RBAC 模型(仅 **additive** 一枚 permission
- 自动开下一 ECR
---
## Implementation Notes(实现轮才执行)
| 项 | 内容 |
|----|------|
| Migration | YEStransitions 表;permission 种子;必要时 CHECK/注释枚举) |
| Packages | service account/lifecycle · DeviceAuth/session 拒绝 · admin handler · admin-h5 用户详情最小 CTA |
| Depends | ECR-013A Closedpermission middleware |