cisd/docs/plans/2026-03-30-auth-refactor-plan.md
2026-03-30 14:41:38 +08:00

17 KiB

Auth Refactor Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Refactor modules/auth to keep only the new standardized auth API while preserving the legacy password-login and UKey-login business rules for the four main roles.

Architecture: Keep one canonical auth module built around four roles plus AuthLevel, split standardized controllers for session and admin actions, and move all old flow compatibility into the service layer instead of keeping compatibility endpoints. Preserve legacy verification order for UKey login and password-login safety checks while normalizing DTO names, entity fields, and mapper contracts.

Tech Stack: Spring Boot, MyBatis, Flyway, Jakarta Validation, JUnit 5, Maven


Task 1: Lock the domain model to four roles plus auth level

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/enums/RoleCode.java
  • Create: src/main/java/com/cisd/tms/modules/auth/enums/AuthMethod.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/enums/AuthLevel.java
  • Create: src/main/java/com/cisd/tms/modules/auth/service/AuthPolicyService.java
  • Test: src/test/java/com/cisd/tms/modules/auth/service/AuthDomainModelTest.java

Step 1: Write the failing test

Add assertions that:

  • RoleCode only exposes SUPER_ADMIN, KEY_ADMIN, AUDIT_ADMIN, OPS_ADMIN
  • each role has the correct required UKey count
  • PASSWORD maps to LIMITED
  • UKEY maps to FULL

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthDomainModelTest test Expected: FAIL because role/auth-method policy is not fully modeled yet.

Step 3: Write minimal implementation

Implement:

  • AuthMethod enum
  • updated RoleCode
  • minimal AuthPolicyService helpers such as:
    • requiredUkeyCount(roleCode)
    • authLevelFor(method)

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthDomainModelTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/enums/RoleCode.java src/main/java/com/cisd/tms/modules/auth/enums/AuthMethod.java src/main/java/com/cisd/tms/modules/auth/enums/AuthLevel.java src/main/java/com/cisd/tms/modules/auth/service/AuthPolicyService.java src/test/java/com/cisd/tms/modules/auth/service/AuthDomainModelTest.java
git commit -m "refactor: normalize auth role domain model"

Task 2: Normalize request and response DTOs to the new API contract

Files:

  • Create: src/main/java/com/cisd/tms/modules/auth/dto/PasswordLoginRequest.java
  • Create: src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRequest.java
  • Create: src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginProof.java
  • Create: src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRandomRequest.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRandomResponse.java
  • Create: src/main/java/com/cisd/tms/modules/auth/dto/CaptchaResponse.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/dto/UkeyBindRequest.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/dto/CurrentUserResponse.java
  • Delete: src/main/java/com/cisd/tms/modules/auth/dto/CompatPasswordLoginRequest.java
  • Delete: src/main/java/com/cisd/tms/modules/auth/dto/CompatUkeyLoginRequest.java
  • Test: src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java

Step 1: Write the failing test

Add controller-request binding tests covering:

  • POST /api/v1/auth/password-login
  • POST /api/v1/auth/ukey-login/randoms
  • POST /api/v1/auth/ukey-login
  • request validation failures for missing roleCode, missing captcha fields, and missing UKey proof fields

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthControllerTest test Expected: FAIL because controller methods and DTOs still use the old contract.

Step 3: Write minimal implementation

Introduce the standardized DTOs with field names:

  • roleCode
  • captchaCode
  • captchaId
  • ukeyProofs
  • proof fields pubKey, uid, rid, serverRandom, issueSignature, loginPayload, loginSignature

Update UkeyBindRequest to include slotNo, ukeySerial, pubKey, uid, rid, issuerSignature.

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthControllerTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/dto/PasswordLoginRequest.java src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRequest.java src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginProof.java src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRandomRequest.java src/main/java/com/cisd/tms/modules/auth/dto/UkeyLoginRandomResponse.java src/main/java/com/cisd/tms/modules/auth/dto/CaptchaResponse.java src/main/java/com/cisd/tms/modules/auth/dto/UkeyBindRequest.java src/main/java/com/cisd/tms/modules/auth/dto/CurrentUserResponse.java src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java
git commit -m "refactor: standardize auth api dto contract"

Task 3: Extend persistence model for legacy UKey semantics

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/entity/RoleUkeyBindingEntity.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/entity/AuthSessionEntity.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/mapper/RoleUkeyBindingMapper.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/mapper/AuthSessionMapper.java
  • Modify: src/main/resources/mapper/auth/RoleUkeyBindingMapper.xml
  • Modify: src/main/resources/mapper/auth/AuthSessionMapper.xml
  • Create: src/main/resources/db/migration/V12__refactor_auth_login_model.sql
  • Test: src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java

Step 1: Write the failing test

Add service-level tests asserting:

  • UKey binding records preserve uid and rid
  • sessions persist authMethod and authLevel

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthServiceTest test Expected: FAIL because entities and mappers do not yet expose the new fields.

Step 3: Write minimal implementation

Add:

  • uid, rid to RoleUkeyBindingEntity and mapper XML
  • authMethod to AuthSessionEntity and mapper XML
  • Flyway migration to add the new columns and seed/normalize existing auth rows if needed

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthServiceTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/entity/RoleUkeyBindingEntity.java src/main/java/com/cisd/tms/modules/auth/entity/AuthSessionEntity.java src/main/java/com/cisd/tms/modules/auth/mapper/RoleUkeyBindingMapper.java src/main/java/com/cisd/tms/modules/auth/mapper/AuthSessionMapper.java src/main/resources/mapper/auth/RoleUkeyBindingMapper.xml src/main/resources/mapper/auth/AuthSessionMapper.xml src/main/resources/db/migration/V12__refactor_auth_login_model.sql src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java
git commit -m "refactor: persist normalized auth login model"

Task 4: Refactor AuthService into explicit password-login and UKey-login flows

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/service/AuthService.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/service/UkeyLoginRandomService.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/service/InMemoryUkeyLoginRandomService.java
  • Create: src/main/java/com/cisd/tms/modules/auth/service/CaptchaService.java
  • Create: src/main/java/com/cisd/tms/modules/auth/service/InMemoryCaptchaService.java
  • Modify: src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java

Step 1: Write the failing test

Add tests for:

  • password login returns LIMITED
  • UKey login returns FULL
  • wrong captcha fails password login
  • wrong UKey count fails UKey login
  • wrong auth level is stored in session if service logic is broken

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthServiceTest test Expected: FAIL because AuthService still uses the generic old login shape.

Step 3: Write minimal implementation

Refactor service methods to explicit operations:

  • passwordLogin(PasswordLoginRequest request)
  • issueUkeyLoginRandoms(UkeyLoginRandomRequest request)
  • ukeyLogin(UkeyLoginRequest request)
  • issueCaptcha()

Preserve old business order:

  • password flow validates master key, captcha, password, failure count, and status
  • UKey flow validates count, role/rid combination, issuer signature, auth info, randoms, login signature, whitelist, master key, and role password

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthServiceTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/service/AuthService.java src/main/java/com/cisd/tms/modules/auth/service/UkeyLoginRandomService.java src/main/java/com/cisd/tms/modules/auth/service/InMemoryUkeyLoginRandomService.java src/main/java/com/cisd/tms/modules/auth/service/CaptchaService.java src/main/java/com/cisd/tms/modules/auth/service/InMemoryCaptchaService.java src/test/java/com/cisd/tms/modules/auth/service/AuthServiceTest.java
git commit -m "refactor: split password and ukey auth flows"

Task 5: Refactor AuthAdminService around standardized role and UKey admin APIs

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java
  • Modify: src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java

Step 1: Write the failing test

Add tests covering:

  • KEY_ADMIN + FULL can enable another role
  • KEY_ADMIN + FULL can reset password
  • KEY_ADMIN + FULL can issue UKey binding sign
  • KEY_ADMIN + FULL can bind UKey with uid/rid/issuerSignature
  • KEY_ADMIN + LIMITED is rejected

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthAdminServiceTest test Expected: FAIL because service still reflects the old compat split.

Step 3: Write minimal implementation

Refactor admin methods so they accept:

  • roleCode
  • slotNo
  • ukeySerial
  • pubKey
  • uid
  • rid
  • issuerSignature

Ensure slot validation follows role UKey counts and binding updates are overwrite-by-role-and-slot.

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthAdminServiceTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/service/AuthAdminService.java src/main/java/com/cisd/tms/modules/auth/repository/RoleUkeyBindingRepository.java src/main/java/com/cisd/tms/modules/auth/repository/impl/RoleUkeyBindingRepositoryImpl.java src/test/java/com/cisd/tms/modules/auth/service/AuthAdminServiceTest.java
git commit -m "refactor: standardize auth admin role and ukey actions"

Task 6: Collapse controller layer to one standardized API surface

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/controller/AuthController.java
  • Create: src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java
  • Delete: src/main/java/com/cisd/tms/modules/auth/controller/CompatAuthController.java
  • Delete: src/test/java/com/cisd/tms/modules/auth/controller/CompatAuthControllerTest.java
  • Modify: src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java

Step 1: Write the failing test

Add controller tests for:

  • POST /api/v1/auth/password-login
  • POST /api/v1/auth/ukey-login/randoms
  • POST /api/v1/auth/ukey-login
  • POST /api/v1/auth/captcha
  • POST /api/v1/auth/roles/{roleCode}/enable
  • POST /api/v1/auth/roles/{roleCode}/reset-password
  • POST /api/v1/auth/roles/{roleCode}/ukeys/issue-sign
  • POST /api/v1/auth/roles/{roleCode}/ukeys/bind

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthControllerTest test Expected: FAIL because the endpoints are still split across standard and compat controllers.

Step 3: Write minimal implementation

Keep only:

  • AuthController for session-facing endpoints
  • AuthAdminController for role/UKey admin endpoints

Delete CompatAuthController and route all supported behavior through the new API paths.

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthControllerTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/controller/AuthController.java src/main/java/com/cisd/tms/modules/auth/controller/AuthAdminController.java src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java
git rm src/main/java/com/cisd/tms/modules/auth/controller/CompatAuthController.java src/test/java/com/cisd/tms/modules/auth/controller/CompatAuthControllerTest.java
git commit -m "refactor: keep one standardized auth controller surface"

Task 7: Update internal authorization to use role plus auth level

Files:

  • Modify: src/main/java/com/cisd/tms/modules/auth/security/InternalAuthorizationInterceptor.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/security/RequireRole.java
  • Modify: src/main/java/com/cisd/tms/modules/auth/security/RequireAuthLevel.java
  • Modify: src/test/java/com/cisd/tms/modules/auth/security/InternalAuthorizationInterceptorTest.java

Step 1: Write the failing test

Add tests asserting:

  • a LIMITED session is denied for FULL endpoints
  • role-only mismatch is denied
  • KEY_ADMIN + FULL is accepted for admin endpoints

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=InternalAuthorizationInterceptorTest test Expected: FAIL because endpoint requirements and session mapping still reflect the pre-refactor shape.

Step 3: Write minimal implementation

Make interceptor decisions solely from:

  • session roleCode
  • session authLevel

Remove any remaining dependency on compat endpoint semantics.

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=InternalAuthorizationInterceptorTest test Expected: PASS

Step 5: Commit

git add src/main/java/com/cisd/tms/modules/auth/security/InternalAuthorizationInterceptor.java src/main/java/com/cisd/tms/modules/auth/security/RequireRole.java src/main/java/com/cisd/tms/modules/auth/security/RequireAuthLevel.java src/test/java/com/cisd/tms/modules/auth/security/InternalAuthorizationInterceptorTest.java
git commit -m "refactor: enforce auth by role and auth level"

Task 8: Remove obsolete compat code and refresh docs

Files:

  • Delete: src/main/java/com/cisd/tms/modules/auth/service/CompatAuthService.java
  • Delete: src/main/java/com/cisd/tms/modules/auth/dto/CompatPasswordLoginRequest.java
  • Delete: src/main/java/com/cisd/tms/modules/auth/dto/CompatUkeyLoginRequest.java
  • Delete: src/test/java/com/cisd/tms/modules/auth/service/CompatAuthServiceTest.java
  • Modify: docs/plans/2026-03-23-auth-role-ukey-design.md
  • Modify: docs/openapi/cisd-init.openapi.yaml
  • Modify: docs/openapi/cisd-init.openapi.json
  • Test: src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java

Step 1: Write the failing test

Add an assertion in controller-level tests or OpenAPI export verification that only the standardized endpoints remain documented.

Step 2: Run test to verify it fails

Run: mvn -q -Dtest=AuthControllerTest test Expected: FAIL because compat artifacts or docs are still present.

Step 3: Write minimal implementation

Remove obsolete compat classes and update documentation to describe:

  • four roles only
  • LIMITED/FULL
  • password-login and ukey-login standardized endpoints

Step 4: Run test to verify it passes

Run: mvn -q -Dtest=AuthControllerTest test Expected: PASS

Step 5: Commit

git rm src/main/java/com/cisd/tms/modules/auth/service/CompatAuthService.java src/main/java/com/cisd/tms/modules/auth/dto/CompatPasswordLoginRequest.java src/main/java/com/cisd/tms/modules/auth/dto/CompatUkeyLoginRequest.java src/test/java/com/cisd/tms/modules/auth/service/CompatAuthServiceTest.java
git add docs/plans/2026-03-23-auth-role-ukey-design.md docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json src/test/java/com/cisd/tms/modules/auth/controller/AuthControllerTest.java
git commit -m "refactor: remove auth compat surface and refresh docs"

Task 9: Final verification

Files:

  • Verify only

Step 1: Run focused auth test suite

Run: mvn -q -Dtest=AuthControllerTest,AuthServiceTest,AuthAdminServiceTest,AuthDomainModelTest,InternalAuthorizationInterceptorTest test Expected: PASS

Step 2: Run full auth package compile verification

Run: mvn -q -DskipTests compile Expected: PASS

Step 3: Review final behavior against design

Confirm:

  • only four roles remain
  • password-login issues LIMITED
  • ukey-login issues FULL
  • no compat controller remains
  • UKey binding preserves slotNo/uid/rid/issuerSignature

Step 4: Commit verification touch-ups if needed

git add .
git commit -m "test: finalize auth refactor verification"