You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/docs/superpowers/plans/2026-08-03-pevc-local-accou...

182 lines
7.2 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# PEVC Local Account Initialization Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 按 PEVC 的模式内置学生 `tzs001`,本地只保存其 BCrypt 密码哈希SSO 只投影身份和角色,不再读取主平台密码。
**Architecture:** Flyway 迁移一次性插入用户 ID `487`、学生快照和 `STUDENT` 角色关联,密码列仅存 BCrypt 哈希。平台 SSO/CAS 继续验证并投影身份;新投影用户使用随机 BCrypt 密码,和 PEVC 的 SSO 自动建号保持一致。移除当前分支中为镜像主平台密码新增的凭据查询与初始化器。
**Tech Stack:** Java 17, Spring Boot, Spring Security `PasswordEncoder`, Flyway, MyBatis-Plus, JUnit 5.
## Global Constraints
- 不修改 `E:\javawork\tianze-pro` 主平台工程。
- 不读取、记录、返回或提交主平台密码明文。
- 仅保留 `TEACHER`、`STUDENT` 两个角色,用户/角色无 CRUD 接口。
- `tzs001` 固定使用平台用户 ID `487``STUDENT` 角色。
---
### Task 1: 移除密码镜像防腐接口
**Files:**
- Delete: `src/main/java/com/yau/digitalrmb/platformintegration/application/PlatformCredentialRepository.java`
- Delete: `src/main/java/com/yau/digitalrmb/platformintegration/domain/PlatformCredential.java`
- Delete: `src/main/java/com/yau/digitalrmb/identity/application/PlatformCredentialInitializer.java`
- Modify: `src/main/java/com/yau/digitalrmb/platformintegration/infrastructure/JdbcPlatformIdentityRepository.java`
- Modify: `src/main/java/com/yau/digitalrmb/identity/application/PlatformIdentityProjectionService.java`
- Modify: `src/main/java/com/yau/digitalrmb/platformintegration/interfaces/PlatformSsoController.java`
- Modify: `src/main/java/com/yau/digitalrmb/platformintegration/interfaces/CasAuthenticationController.java`
- Test: `src/test/java/com/yau/digitalrmb/identity/PlatformIdentityProjectionServiceTest.java`
**Interfaces:**
- Consumes: `PlatformIdentityProjectionService.project(PlatformActor)`.
- Produces: 所有 SSO/CAS 流程仅投影 `PlatformActor`,不包含密码对象或主平台密码查询。
- [ ] **Step 1: 写出失败测试,证明新投影用户拥有 BCrypt 格式的随机密码**
```java
projectionService.project(actor);
UserEntity user = userMapper.selectById(actor.platformUserId());
assertThat(user.getPasswordHash()).startsWith("$2");
assertThat(passwordEncoder.matches("unknown", user.getPasswordHash())).isFalse();
```
- [ ] **Step 2: 运行测试确认失败**
Run: `mvn -Dtest=PlatformIdentityProjectionServiceTest test -DforkCount=0 -B`
Expected: 旧实现写入 `{noop}EXTERNAL_SSO_ONLY`,断言失败。
- [ ] **Step 3: 最小化实现**
```java
private void projectUser(PlatformActor actor) {
UserEntity user = userMapper.selectById(actor.platformUserId());
if (user == null) {
user = new UserEntity();
user.setId(actor.platformUserId());
user.setUsername(actor.account());
user.setPasswordHash(passwordEncoder.encode(UUID.randomUUID().toString()));
user.setEnabled(true);
userMapper.insert(user);
return;
}
user.setUsername(actor.account());
user.setEnabled(true);
userMapper.updateById(user);
}
```
删除凭据类型、仓储、初始化器和所有 `findCredential` 调用;`JdbcPlatformIdentityRepository` 仅保留身份查询。
- [ ] **Step 4: 运行针对性测试**
Run: `mvn -Dtest=PlatformIdentityProjectionServiceTest,PlatformSsoControllerTest test -DforkCount=0 -B`
Expected: PASS.
- [ ] **Step 5: 提交**
```powershell
git add src/main/java src/test/java
git commit -m "refactor: align sso with pevc local accounts"
```
### Task 2: 以 Flyway 内置 tzs001 学生账号
**Files:**
- Create: `src/main/resources/db/migration/V3__seed_tzs001_local_student.sql`
- Test: `src/test/java/com/yau/digitalrmb/security/AuthControllerTest.java`
**Interfaces:**
- Consumes: `sys_user(id, username, password_hash)`, `platform_user_snapshot`, `sys_user_role` 和现有角色 ID `1002`
- Produces: 迁移后本地 `POST /api/v1/auth/login` 能用 `tzs001` 和指定初始密码签发 JWT`GET /api/v1/auth/me` 返回 `STUDENT`
- [ ] **Step 1: 写出失败集成测试**
```java
mvc.perform(post("/api/v1/auth/login")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"username\":\"tzs001\",\"password\":\"123qwe\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.accessToken").isNotEmpty());
```
移除测试 `@BeforeEach` 中的凭据投影,使测试只依赖迁移。
- [ ] **Step 2: 运行测试确认失败**
Run: `mvn -Dtest=AuthControllerTest test -DforkCount=0 -B`
Expected: 登录返回 401因为 V3 迁移尚不存在。
- [ ] **Step 3: 添加仅含 BCrypt 哈希的迁移**
```sql
INSERT INTO sys_user (id, username, password_hash, enabled, created_at, updated_at, created_by, updated_by, deleted)
VALUES (487, 'tzs001', '$2a$10$ufcw5KFHtOmLzxAsV4C.MuIDOErMlw0iw5J5hc8OMzaTx0u9QYxG6', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'SYSTEM', 'SYSTEM', FALSE);
INSERT INTO platform_user_snapshot (platform_user_id, account, display_name, role_key, source_updated_at, synced_at)
VALUES (487, 'tzs001', 'tzs001', 'STUDENT', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO sys_user_role (user_id, role_id) VALUES (487, 1002);
```
最终 SQL 和日志均不得包含明文密码。
- [ ] **Step 4: 运行集成测试**
Run: `mvn -Dtest=AuthControllerTest test -DforkCount=0 -B`
Expected: PASS`/me` 角色为 `STUDENT`
- [ ] **Step 5: 提交**
```powershell
git add src/main/resources/db/migration/V3__seed_tzs001_local_student.sql src/test/java/com/yau/digitalrmb/security/AuthControllerTest.java
git commit -m "feat: seed tzs001 local student account"
```
### Task 3: 清理配置、文档与回归验证
**Files:**
- Modify: `src/main/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationProperties.java`
- Modify: `README.md`
- Modify: `docs/superpowers/specs/2026-08-03-platform-sso-readonly-design.md`
- Delete: `src/test/java/com/yau/digitalrmb/identity/PlatformCredentialInitializerTest.java`
- Modify: `src/test/java/com/yau/digitalrmb/platformintegration/infrastructure/JdbcPlatformIdentityRepositoryTest.java`
**Interfaces:**
- Consumes: PEVC 对 SSO 与迁移账号的职责分离。
- Produces: 无 `local-login`、`PlatformCredential` 或主平台密码查询的可部署后端。
- [ ] **Step 1: 写出仓储回归测试**
```java
assertThat(repository.findByPlatformUserId(101L)).contains(actor);
```
删除依赖 `core_user.PASSWORD` 的断言。
- [ ] **Step 2: 移除过时配置与文档描述**
删除 `PlatformIntegrationProperties.LocalLogin`、密码镜像叙述及其测试文档改为“SSO 身份投影 + Flyway 内置本地账号”。
- [ ] **Step 3: 运行全量验证**
Run: `mvn test -DforkCount=0 -B`
Expected: 全部测试 PASS0 failures0 errors。
- [ ] **Step 4: 构建可执行包**
Run: `mvn package -DskipTests -B`
Expected: `target/digital-rmb-backend-0.1.0-SNAPSHOT.jar` 生成成功。
- [ ] **Step 5: 提交**
```powershell
git add README.md docs/superpowers/specs src/main/java src/test/java
git commit -m "docs: document pevc-style local login"
```