feat: 레거시 재이관과 계정 복구 기반을 추가

중앙 이전 기록 스키마와 버전 정규화기를 도입하고, 재실행 시 현행 계정 상태를 보존한다. 카카오 인증 뒤 이관 비밀번호를 1회 설정하는 흐름과 비카카오 계정용 안전한 CLI 복구 경로를 추가한다.
This commit is contained in:
2026-08-17 15:55:32 +00:00
parent 50e7d894e4
commit fc7de05017
33 changed files with 1720 additions and 150 deletions
@@ -34,10 +34,12 @@ describe('password credential compatibility', () => {
});
user.passwordSalt = 'core-salt';
user.passwordHash = createHash('sha256').update('core-salt:current-password').digest('hex');
user.passwordResetRequired = true;
expect(await users.verifyPassword(user, 'current-password')).toBe(true);
expect(user.passwordHash.startsWith('$argon2id$')).toBe(true);
expect(user.passwordSalt).toBe('');
expect(user.passwordResetRequired).toBe(false);
});
it('upgrades an imported ref double-SHA-512 credential after a successful login', async () => {
@@ -52,10 +54,12 @@ describe('password credential compatibility', () => {
const browserHash = createHash('sha512').update(`${globalSalt}current-password${globalSalt}`).digest('hex');
user.passwordSalt = userSalt;
user.passwordHash = createHash('sha512').update(`${userSalt}${browserHash}${userSalt}`).digest('hex');
user.passwordResetRequired = true;
expect(await users.verifyPassword(user, 'current-password')).toBe(true);
expect(user.passwordHash.startsWith('$argon2id$')).toBe(true);
expect(user.passwordSalt).toBe('');
expect(user.passwordResetRequired).toBe(false);
});
it('does not accept an imported ref credential without the matching global salt', async () => {