Files
danyang-match/docs/superpowers/plans/2026-10-23-v12-account-lifecycle-matchmaker-dashboard.md
T
WorkBuddy 377429995c
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Waiting to run
CI/CD Pipeline / Backend Build & Test (push) Waiting to run
CI/CD Pipeline / Admin Web Build (push) Waiting to run
CI/CD Pipeline / Mini Program Compile Check (push) Waiting to run
CI/CD Pipeline / Migration Validation (push) Blocked by required conditions
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Waiting to run
CI/CD Pipeline / E2E (live stack) (push) Blocked by required conditions
release: freeze V1.2 demo acceptance 2026-10-25
2026-10-25 14:29:29 +08:00

364 lines
30 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.
# V1.2 账号生命周期、红娘分配与工作台实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在保留 V1.1 核心业务和现有红娘分配权限的前提下,补齐 V1.2 的用户注册/建档/审核/账号发放/首次授权闭环,确保认证后的资料变更重新审核后才重新展示和匹配,并让普通红娘、红娘组长和管理员使用一致且不可越权的六项工作台统计。
**Architecture:** 继续使用 Spring Boot 模块化单体、PostgreSQL Source of Truth、Redis 只保存验证码/登录失败状态。用户账号生命周期、授权门禁、导入批次和红娘工作台范围分别建模;业务服务通过现有 `CapabilityService`、`ServiceAssignmentPolicy` 和 `DataScopeGuard` 接入,不重建权限体系。工作台采用一个服务端聚合接口,依据当前登录主体推导 scope,卡片和详情列表复用同一组查询条件。
**Tech Stack:** Java 21 / Spring Boot 3 / MyBatis-Plus / PostgreSQL / Redis / Flyway / Vue 3 / TypeScript / 微信原生小程序 / Maven / pnpm / Python pytest。
**Spec:** `C:\Users\13070\.codex\attachments\155243ba-d394-45a0-b100-8c44baf9094d\已粘贴的文本.txt`;审计基线:`docs/audits/V1.2-现状审计与差距矩阵-2026-10-23.md`(若该审计文件尚未写入,则以本计划中的审计结论为准)。
## Global Constraints
- 用户永久免费;不新增 VIP、会员、金币或收费路径。
- PostgreSQL 是 Source of Truth;Redis 不保存业务状态,不覆盖数据库状态。
- 所有权限范围由后端从认证主体、角色、组织和有效分配关系推导;不信任请求体中的 `userId`、`matchmakerId`、`teamId` 或角色字段。
- 审核状态、账号状态、手机号核验、授权、服务资格、凭据发放必须独立存储,禁止合并为一个完成字段。
- 用户完成实名认证后,任何个人资料变更都生成新版本并进入 `pending_review`;新版本审核通过前,不得在推荐、搜索、活动匹配、红娘推荐或其他用户可见资料中使用。
- 资料重新审核期间,后端按“未通过审核”处理;不能只在前端隐藏,也不能继续使用未审核的新资料计算匹配。
- 未确认的登录标识、密码发放渠道、授权正式文案、重复资料处理、自动分配算法和看板统计口径在 Gate 0 前不得进入业务代码。
- 不重写 V001-V061;V1.2 新迁移从 V062 开始,所有迁移向前兼容已有数据。
- 不增加第三方依赖;批量导入首版使用 UTF-8/UTF-8 BOM CSV,`.xlsx` 作为明确不支持格式返回可读错误。
- Mock 短信/微信只能在显式测试或演示 profile 启用;生产配置不得把 Mock 验证当作真实核验。
- 每个任务先写失败测试,再写最小实现;任务完成后输出阶段 Completion Report,不自动进入下一任务。
- 任何外部短信、微信、生产数据库和真实用户 UAT 都不是本地测试的替代证据。
## Gate 0:产品和数据决策冻结
**Files:**
- Modify: `docs/governance/open-questions.md`
- Modify: `docs/governance/decision-register.md`
- Modify: `docs/governance/config-register.md`
- Create: `docs/v12/V1.2-状态机与接口契约.md`
- Create: `docs/v12/V1.2-字段与统计口径表.md`
**必须确认的决策:**
1. 用户登录标识:手机号 + 密码,或平台发放的独立用户名 + 密码。
2. 初始密码的实际发放渠道;失败时由谁、通过什么双人复核流程人工发放。
3. 两份授权书的正式文本、版本号、拒绝后的服务状态和重新授权规则。
4. 历史微信用户的补授权、手机号核验和账号关联策略。
5. 重复手机号/重复资料的拒绝、合并或人工队列规则。
6. 自动分配算法、跨组规则、无可用红娘时的待分配队列行为。
7. 六项看板的状态、时间范围、去重规则和“有效匹配”正式口径。
8. 红娘组长是否可建档、导入、直接分配及调整组内红娘关系。
**验收:** 所有决策进入 `decision-register.md`;仍未确认的内容进入 `open-questions.md`,并在代码计划中标记为配置或阻断,不写成默认业务规则。
---
### Task 1: 建立 V1.2 状态模型和迁移
**Files:**
- Create: `backend/src/main/resources/db/migration/V062__add_v12_user_account_lifecycle.sql`
- Create: `backend/src/main/resources/db/migration/V063__add_v12_import_batches.sql`
- Create: `backend/src/main/resources/db/migration/V064__add_v12_consent_and_service_state.sql`
- Modify: `backend/src/test/resources/schema-h2.sql`
- Create: `backend/src/test/java/com/danyang/match/platform/deployment/V12MigrationContractTest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/entity/UserCredential.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/entity/UserAccountLifecycle.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/entity/UserConsentState.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/entity/UserImportBatch.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/entity/UserImportRow.java`
**Interfaces:**
- Produces independent fields for `profile_review_status`, `profile_revision`, `published_profile_revision`, `account_creation_status`, `credential_delivery_status`, `phone_verification_status`, `service_consent_status`, and `service_eligibility_status`.
- Produces password hash, `must_change_password`, password version, credential issued/used timestamps, and delivery channel/status; never stores plaintext passwords.
- Produces import batch and row status/error fields with a unique idempotency key per batch.
- Preserves existing `users`, `operators`, `review_tasks`, `consent_records` rows and existing V1.1 status values.
- [x] **Step 1: Write migration contract tests** for new tables/columns, allowed status values, indexes, uniqueness, and absence of plaintext credential columns.
- [x] **Step 2: Run the contract tests**; initial run failed because V062-V064 did not exist, then passed after implementation.
- [x] **Step 3: Add V062-V064 migrations** with backfill-safe columns, batch row uniqueness, and indexes for status/scope queries.
- [x] **Step 3a: Add profile revision storage**: retain the last approved/published revision and backfill approved users; atomic profile-write transition is implemented in Task 4 at the service boundary.
- [x] **Step 4: Mirror required tables and constraints in `schema-h2.sql`** and keep PostgreSQL-specific DDL covered by migration contract tests.
- [x] **Step 5: Add lifecycle entities** without changing existing V1.1 entity semantics; profile write behavior remains a Task 4 concern.
- [x] **Step 6: Run migration and entity tests**; no modification to V001-V061.
- [x] **Step 7: Write `docs/v12/V1.2-状态机与接口契约.md`** with allowed transitions, terminal states, idempotency behavior, and actor/audit rules.
**验收:** Empty PostgreSQL can migrate V001-V064; existing demo data remains readable; duplicate active credential/phone/batch rows are rejected by database constraints.
### Task 2: 实现用户自主注册、手机号核验和历史账号关联
**Files:**
- Create: `backend/src/main/java/com/danyang/match/platform/user/dto/UserRegistrationRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/dto/PhoneVerificationRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/service/UserRegistrationService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/service/PhoneVerificationService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/controller/AuthController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/service/AuthService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/auth/provider/SmsVerificationProvider.java`
- Create: `backend/src/main/java/com/danyang/match/platform/auth/provider/MockSmsVerificationProvider.java`
- Create: `backend/src/main/java/com/danyang/match/platform/auth/provider/ConfiguredSmsVerificationProvider.java`
- Create: `backend/src/test/java/com/danyang/match/platform/user/UserRegistrationServiceTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/auth/PhoneVerificationGuardTest.java`
- Modify: `miniapp/services/authService.js`
- Modify: `miniapp/pages/login/login.ts`
- Create: `miniapp/pages/register/register.ts`
- Create: `miniapp/pages/register/register.wxml`
- Create: `miniapp/pages/register/register.wxss`
- Create: `miniapp/pages/register/register.json`
**Interfaces:**
- `POST /api/v1/auth/register` consumes name, organization, organizationPhone, phone, and verification transaction; returns a pending user reference, never an active service token.
- `POST /api/v1/auth/phone/send-code` and `POST /api/v1/auth/phone/verify` use a provider abstraction and one-time Redis transaction; production provider must fail closed when unconfigured.
- `POST /api/v1/auth/wechat/login` remains compatible, but new and historical users receive explicit lifecycle state in the response.
- Duplicate phone returns a stable conflict code and does not overwrite existing records.
- [x] **Step 1: Add failing tests** for phone validation, code expiry/replay, rate limits, duplicate phone, and provider refusal outside test/demo profiles.
- [x] **Step 2: Run targeted tests** and confirm failure before implementation.
- [x] **Step 3: Implement provider and Redis transaction** with hashed code storage, expiry, attempt limit, cooldown, and audit-safe logs; never log the code or full phone.
- [x] **Step 4: Implement registration transaction** that writes the registration application and marks phone verification separately.
- [x] **Step 5: Preserve WeChat login compatibility**; ambiguous historical account association remains blocked until its explicit association flow is implemented in a later task.
- [x] **Step 6: Add miniapp registration and error/loading states** using existing API and UI conventions.
- [x] **Step 7: Run backend tests and miniapp type-check**.
**验收:** Unverified users cannot enter the service flow; duplicate phone cannot overwrite existing data; the same verification transaction cannot be replayed; real-provider configuration is required for production.
### Task 3: 实现后台建档、CSV 导入和审核后账号发放
**Files:**
- Create: `backend/src/main/java/com/danyang/match/platform/user/dto/OperatorCreateUserRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/dto/UserImportPreviewRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/dto/UserImportPreviewResponse.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/service/UserOnboardingService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/service/UserImportService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/user/service/UserCredentialService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/user/controller/UserController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/review/service/ReviewService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/review/controller/ReviewController.java`
- Create: `backend/src/test/java/com/danyang/match/platform/user/UserImportServiceTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/user/UserAccountLifecycleTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/review/ReviewAccountIssuanceTest.java`
- Create: `admin-web/src/modules/user/UserCreateView.vue`
- Create: `admin-web/src/modules/user/UserImportView.vue`
- Modify: `admin-web/src/modules/user/UserManagementView.vue`
- Modify: `admin-web/src/router/index.ts`
**Interfaces:**
- `POST /api/v1/operator/users` creates a draft profile only; it does not bypass phone verification, authorization, or review.
- `POST /api/v1/operator/users/import/preview` accepts CSV bytes and returns row-level normalized values/errors without writes.
- `POST /api/v1/operator/users/import/commit` consumes a preview batch id plus `Idempotency-Key`, writes valid rows only, and records every row result.
- `POST /api/v1/operator/users/{id}/issue-account` is idempotent and allowed only after approved profile + verified phone + required consent policy.
- Account issuance returns a masked delivery result and one-time credential reference; plaintext initial password is never persisted or written to logs.
- [x] **Step 1: Write failing tests** for permission, CSV encoding/header validation, row errors, duplicate rows within a file, duplicate database phone, preview no-write, commit idempotency, and retry behavior.
- [x] **Step 2: Run targeted tests** and confirm failure.
- [x] **Step 3: Implement manual create and CSV preview** with explicit required columns: name, organization, organizationPhone, phone; unsupported formats are rejected by the CSV-only endpoint.
- [x] **Step 4: Implement commit transaction** with row-level success/failure persistence, Redis idempotency, and no partial overwrite of an existing user.
- [x] **Step 5: Connect review approval to account issuance eligibility and profile publication**; approval publishes the reviewed revision while rejection/need-edit preserves the previous published revision.
- [x] **Step 6: Implement secure random initial password generation and hash storage** with `must_change_password=true`; only a credential reference is returned.
- [x] **Step 7: Add admin UI manual-create and CSV preview/commit workflow** with permission-based visibility.
- [x] **Step 8: Run backend tests and admin type-check**.
**验收:** Preview performs no database write; commit can be safely retried; failed rows are explainable; approval, phone verification, consent, account status and profile publication remain separate; no plaintext credential is stored; a changed authenticated profile is excluded from matching until its new revision is approved.
### Task 4: 实现用户/红娘登录、首次改密和授权门禁
**Files:**
- Create: `backend/src/main/java/com/danyang/match/platform/auth/dto/PasswordLoginRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/auth/dto/InitialPasswordChangeRequest.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/service/UserCredentialService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/service/ServiceConsentService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/service/AuthService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/controller/AuthController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/service/OperatorAuthService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/auth/controller/OperatorAuthController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/profile/controller/ProfileController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/profile/service/UserProfileService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/profile/mapper/UserProfileMapper.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/capability/service/CapabilityService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/account/controller/ServiceConsentController.java`
- Create: `backend/src/test/java/com/danyang/match/platform/auth/InitialPasswordGuardTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/account/ServiceConsentGateTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/account/ConsentVersionAuditTest.java`
- Create: `miniapp/pages/initial-password/initial-password.ts`
- Create: `miniapp/pages/initial-password/initial-password.wxml`
- Create: `miniapp/pages/initial-password/initial-password.wxss`
- Create: `miniapp/pages/service-consent/service-consent.ts`
- Create: `miniapp/pages/service-consent/service-consent.wxml`
- Create: `miniapp/pages/service-consent/service-consent.wxss`
- Modify: `miniapp/stores/authStore.js`
- Modify: `miniapp/app.js`
**Interfaces:**
- `POST /api/v1/auth/password/login` authenticates the confirmed login identifier and returns `mustChangePassword`, `consentRequired`, and `serviceActive` state.
- `POST /api/v1/auth/password/change-initial` is the only non-essential endpoint allowed while `must_change_password=true`; success rotates credential version and invalidates old sessions.
- `GET /api/v1/account/service-consent` returns the two required document versions and current user decisions.
- `POST /api/v1/account/service-consent` requires explicit positive confirmation for each required document and records version, actor, timestamp, IP, user agent, and audit event.
- All match, chat, matchmaker, counseling, appointment and activity service entry points call a shared `ServiceConsentService.requireActive(userId)` or equivalent policy check.
- [ ] **Step 1: Write failing tests** for initial-login restriction, wrong password rate limiting, password complexity, old credential invalidation, unchecked consent rejection, version mismatch, withdrawal, and reactivation.
- [ ] **Step 2: Run targeted tests** and confirm failure.
- [ ] **Step 3: Implement password login and initial-change flow** with the existing JWT/Redis conventions; never expose password hashes or plaintext credentials.
- [ ] **Step 4: Implement consent state and audit** using the formal versions from Gate 0; do not treat silence or a pre-checked UI box as consent.
- [ ] **Step 5: Add profile revision gate** to profile update endpoints: after authentication, every personal-profile write creates a new revision and moves the profile to `pending_review`; fields that are not personal-profile data must be explicitly classified rather than silently bypassing review.
- [ ] **Step 6: Add shared backend gate** to each service boundary. The gate must require the latest profile revision to equal the published approved revision, not just trust the front-end capability response.
- [ ] **Step 7: Add miniapp first-login and profile-update routing** for change-password, consent, profile confirmation, pending-review, rejection and resubmission states.
- [ ] **Step 8: Run negative permission, profile-revision and service-block tests** plus miniapp type-check.
**验收:** Refusal sets the confirmed inactive/suspended service state; protected service APIs reject the user server-side; changing the initial password and accepting both documents are separately auditable; an authenticated profile edit immediately leaves the new revision unpublished and excluded from matching until review approval.
### Task 5: 接入红娘自动分配前置条件和账号管理闭环
**Files:**
- Create: `backend/src/main/java/com/danyang/match/platform/matchmaker/service/MatchmakerEligibilityPolicy.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/service/MatchmakerAssignmentService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/service/ServiceAssignmentPolicy.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/operator/service/OperatorManagementService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/operator/controller/OperatorController.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerAssignmentEligibilityTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/ProfileRevisionAssignmentGuardTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/operator/OperatorCredentialLifecycleTest.java`
- Modify: `backend/src/main/resources/db/migration/V065__add_v12_assignment_eligibility_audit.sql`
**Interfaces:**
- `MatchmakerEligibilityPolicy.assertEligible(userId)` checks, in order: approved profile, verified phone, required consent, normal account status, confirmed service eligibility.
- Existing `MatchmakerAssignmentService.create/transfer` remains the write boundary and calls the policy before creating an active assignment.
- Operator creation requires an explicit approved role (`matchmaker` or `matchmaker_leader`), organization scope, secure credential issuance state, and audit record.
- Disabling a matchmaker cannot silently drop active assignments; it follows the Gate 0 decision for transfer queue/leader handling.
- [ ] **Step 1: Write failing tests** for each missing eligibility condition, concurrent assignment, cross-organization leader denial, disabled target, and re-enable behavior.
- [ ] **Step 2: Run targeted tests** and confirm failure.
- [ ] **Step 3: Implement `MatchmakerEligibilityPolicy`** by reusing `CapabilityService`, consent policy and the published-profile-revision check; do not duplicate status rules in controllers.
- [ ] **Step 4: Connect policy to create/transfer** within the existing transaction and preserve database unique-index race protection.
- [ ] **Step 5: Harden operator creation** with request validation, role binding, audit, password policy and initial-change flag.
- [ ] **Step 6: Implement disabled-operator assignment handling** exactly as decided at Gate 0, with an audit event and no data loss.
- [ ] **Step 7: Run the existing matchmaker suite plus new eligibility tests**.
**验收:** No ineligible user can receive an active automatic/manual assignment; ordinary matchmakers cannot claim or browse unassigned users; group leaders remain organization-scoped; disabling a matchmaker leaves an auditable, recoverable assignment state.
### Task 6: 重建六项范围看板和详情一致性
**Files:**
- Create: `backend/src/main/java/com/danyang/match/platform/matchmaker/dashboard/MatchmakerDashboardScope.java`
- Create: `backend/src/main/java/com/danyang/match/platform/matchmaker/dashboard/MatchmakerDashboardMapper.java`
- Create: `backend/src/main/java/com/danyang/match/platform/matchmaker/dashboard/MatchmakerWorkbenchService.java`
- Create: `backend/src/main/java/com/danyang/match/platform/matchmaker/dashboard/MatchmakerWorkbenchController.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/analytics/AnalyticsService.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerWorkbenchScopeTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerDashboardConsistencyTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerDashboardAuthorizationTest.java`
- Modify: `admin-web/src/services/dashboard.ts`
- Modify: `admin-web/src/types/dashboard.ts`
- Modify: `admin-web/src/views/DashboardView.vue`
- Modify: `admin-web/src/router/index.ts`
**Interfaces:**
- `GET /api/v1/operator/matchmaker/workbench/dashboard` returns `{ scope, metrics, availability, generatedAt }` for the six cards and shared query metadata.
- `MatchmakerDashboardScope` is derived server-side: ordinary matchmaker = active assignments owned by principal; group leader = same organization; administrator = platform scope.
- The six metric keys remain `pending_reviews`, `matchmaker_todos`, `counseling_todos`, `station_appointments`, `effective_matches`, and `activity_registrations` to preserve the existing UI contract.
- Detail list endpoints receive only pagination/time filters; they cannot receive an alternate operator/team scope. They call the same scope builder and status predicates as the aggregate query.
- User/profile-backed metrics and drill-down records exclude rows where `profile_revision != published_profile_revision`; an unreviewed profile revision must not leak through the dashboard or matching data.
- [ ] **Step 1: Freeze metric definitions** in `docs/v12/V1.2-字段与统计口径表.md`, including included/excluded statuses, timezone `Asia/Shanghai`, time window, and deduplication.
- [ ] **Step 2: Write failing authorization/consistency tests** for ordinary matchmaker, same-team leader, other-team leader, administrator, empty data, permission denied, and aggregate/detail equality.
- [ ] **Step 3: Run targeted tests** and confirm failure.
- [ ] **Step 4: Implement scope builder and SQL filters** at query level; do not fetch global rows and filter in Vue. Add the published-profile-revision predicate to every user/profile-backed metric and detail query.
- [ ] **Step 5: Implement one aggregate endpoint** while preserving older analytics endpoints for existing analytics pages.
- [ ] **Step 6: Update `dashboard.ts`** to use the aggregate response for six cards; keep loading, empty, forbidden, partial-failure states distinct.
- [ ] **Step 7: Add detail navigation tests** showing a card click cannot broaden the scope.
- [ ] **Step 8: Run backend scope tests, admin type-check, build, and UI contract tests**.
**验收:** Six cards show `0` for real empty data, a distinct no-permission state for forbidden data, and a distinct failure state for query failure; ordinary matchmaker, leader, and administrator counts match their permitted detail lists; changing request parameters cannot change scope.
### Task 7: 活栈 E2E、文档收口和发布门禁
**Files:**
- Create: `tests/e2e/v12_account_lifecycle_test.py`
- Create: `tests/e2e/v12_import_and_review_test.py`
- Create: `tests/e2e/v12_matchmaker_dashboard_test.py`
- Modify: `tests/e2e/conftest.py`
- Modify: `backend/src/test/resources/application-test.yml`
- Modify: `docs/STATUS.md`
- Create: `docs/Phase-V12-Completion-Report.md`
- Modify: `docs/api/API_INVENTORY.md`
- Modify: `docs/database/MIGRATION_GUIDE.md`
- Modify: `README.md`
- Modify: `.github/workflows/ci.yml`
**Interfaces:**
- E2E uses a clean PostgreSQL/Redis stack and explicit test providers; it never treats H2-only results as release evidence.
- CI runs migration validation, backend tests, admin type-check/build, miniapp type-check, and V1.2 E2E; any failed gate blocks completion.
- Completion report records current commit, migration version, test counts, skipped tests/reasons, runtime configuration, and unresolved production evidence.
- [ ] **Step 1: Add E2E fixtures** for a user, duplicate phone, pending/approved review, ordinary matchmaker, same-team leader, other-team leader, and administrator.
- [ ] **Step 2: Add the account lifecycle path**: register or import → preview → commit → review → account issue → password login → forced change → two consents → service capability.
- [ ] **Step 2a: Add the profile revision path**: approved user edits personal profile → new revision becomes pending → old approved revision remains the only published revision → review approval publishes the new revision → matching and display resume.
- [ ] **Step 3: Add negative paths**: duplicate phone, expired code, repeated commit, refused consent, pending/rejected profile excluded from search/recommendation/matchmaker recommendation, cross-team dashboard query, and disabled matchmaker.
- [ ] **Step 4: Add dashboard consistency checks** for all six cards and corresponding detail lists under all three role scopes, including exclusion of unpublished profile revisions.
- [ ] **Step 5: Run the full local gate**:
```powershell
mvn -B -f backend/pom.xml test
pnpm --dir admin-web type-check
pnpm --dir admin-web build
npm --prefix miniapp run type-check
python -m pytest tests/e2e -q
```
- [ ] **Step 6: Fix environment blockers separately** if `spawn EPERM`, locked `target/classes`, missing Redis, or missing production-provider credentials occur; do not weaken tests.
- [ ] **Step 7: Write Completion Report** with `PASS/PARTIAL/FAIL/NOT_IMPLEMENTED/NOT_VERIFIED` evidence and stop for user acceptance.
**验收:** Clean-stack E2E proves the complete V1.2 path and role isolation; CI is green; no historical test count is reused as current evidence; production remains `NO-GO` until real SMS/WeChat, TLS, backup/restore, monitoring, rollback and user UAT are separately proven.
## Dependency Order and Release Gates
```text
Gate 0 product decisions
|
v
Task 1 state model and migrations
|
+--> Task 2 registration and phone verification
| |
| v
+--> Task 3 admin create/import/review/issuance
|
v
Task 4 first login/password/consent gate
|
+--> Task 5 assignment eligibility
|
+--> Task 6 scoped dashboard
|
v
Task 7 E2E and release gate
```
**Phase completion rules:**
- Gate 0: all mandatory product decisions recorded.
- Task 1: V062-V064 migrate on a clean database and existing data remains readable.
- Task 2: phone verification cannot be bypassed or replayed.
- Task 3: import is previewable, idempotent, auditable and cannot bypass review/consent.
- Task 4: initial password, consent and unpublished profile revisions are backend-enforced.
- Task 5: assignment eligibility and role scope are negative-tested.
- Task 6: cards and details share scope and metric definitions.
- Task 7: full current test evidence is recorded and user acceptance is requested.
## Explicitly Deferred
- Direct `.xlsx` parsing; first release accepts UTF-8 CSV and returns a clear unsupported-format error for `.xlsx`.
- A new automatic assignment algorithm before the product decision; the existing explicit assignment path remains available.
- Any payment, VIP, AI代聊, community feed, microservice, Kubernetes, or unrelated V1.2 expansion.
- Production SMS/WeChat provider integration, real credentials, production TLS, backup/restore rehearsal and real-user UAT until their environment and owners are available.
## Plan Self-Check
- Registration fields, phone verification, duplicate handling: Task 2.
- Manual create, CSV preview/commit, row errors, review linkage: Task 3.
- Independent account/credential/consent/service states: Task 1 and Task 4.
- Initial password rules, hash-only storage, forced change: Task 3 and Task 4.
- Authenticated profile update creates a new revision and blocks display/matching until approval: Task 1, Task 3, Task 4, Task 5, Task 6 and Task 7.
- Administrator-only matchmaker account opening and group scope: Task 5.
- Automatic assignment prerequisites and no-available-matchmaker behavior: Gate 0 and Task 5.
- Six dashboard cards, role scopes, empty/error/forbidden states, card/detail consistency: Task 6.
- Tests, migrations, frontend builds, clean-stack E2E, documentation and completion report: Task 7.
## Execution Handoff
Plan complete and saved to `docs/superpowers/plans/2026-10-23-v12-account-lifecycle-matchmaker-dashboard.md`. Execute it task-by-task with review checkpoints; implementation must begin at Gate 0 and stop after each phase Completion Report.