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...

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 主平台工程。
  • 不读取、记录、返回或提交主平台密码明文。
  • 仅保留 TEACHERSTUDENT 两个角色,用户/角色无 CRUD 接口。
  • tzs001 固定使用平台用户 ID 487STUDENT 角色。

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 和现有角色 ID 1002

  • Produces: 迁移后本地 POST /api/v1/auth/login 能用 tzs001 和指定初始密码签发 JWTGET /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-loginPlatformCredential 或主平台密码查询的可部署后端。

  • 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: 全部测试 PASS0 failures0 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"