7.2 KiB
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固定使用平台用户 ID487和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 格式的随机密码
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: 最小化实现
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: 提交
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和现有角色 ID1002。 -
Produces: 迁移后本地
POST /api/v1/auth/login能用tzs001和指定初始密码签发 JWT;GET /api/v1/auth/me返回STUDENT。 -
Step 1: 写出失败集成测试
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 哈希的迁移
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: 提交
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: 写出仓储回归测试
assertThat(repository.findByPlatformUserId(101L)).contains(actor);
删除依赖 core_user.PASSWORD 的断言。
- Step 2: 移除过时配置与文档描述
删除 PlatformIntegrationProperties.LocalLogin、密码镜像叙述及其测试;文档改为“SSO 身份投影 + Flyway 内置本地账号”。
- Step 3: 运行全量验证
Run: mvn test -DforkCount=0 -B
Expected: 全部测试 PASS,0 failures,0 errors。
- Step 4: 构建可执行包
Run: mvn package -DskipTests -B
Expected: target/digital-rmb-backend-0.1.0-SNAPSHOT.jar 生成成功。
- Step 5: 提交
git add README.md docs/superpowers/specs src/main/java src/test/java
git commit -m "docs: document pevc-style local login"