fix: audit remediation — SSE user scoping, FK transactional safety, UI error handling

- H4: scoped SSE import progress to exact userId match; non-HTTP events excluded from all subscribers
- H2: moved PRAGMA foreign_key_check inside SQLite transaction before COMMIT; violations rollback preserving old tables
- M1: removed dead axios-style error branch from extractErrorMessage (interceptor already unwraps)
- M2: split handleSave try/catch — save errors vs reload errors shown distinctly
- M3: added provider field validation before AI config test request
- Added SSE scoping regression tests (import service + controller)
- Added FK check failure rollback test (database-migrations.spec)
- Updated controller spec expectations for userId parameter

Co-authored-by: Code Review <branch-review>
This commit is contained in:
2026-07-12 22:59:03 +08:00
parent b6fca99390
commit cc4f4dae4e
69 changed files with 6262 additions and 1980 deletions

View File

@@ -55,5 +55,33 @@ describe('DingTalkService — attendance records', () => {
).rejects.toThrow('userIds');
expect(global.fetch).toBeUndefined();
});
it('keeps DingTalk work dates in China local time', async () => {
global.fetch = jest.fn().mockResolvedValue({
json: jest.fn().mockResolvedValue({
errcode: 0,
errmsg: 'ok',
recordresult: [
{
id: 1,
userId: 'ding-1',
workDate: Date.parse('2026-07-12T00:00:00+08:00'),
userCheckTime: Date.parse('2026-07-12T21:05:00+08:00'),
sourceType: 'USER',
checkType: 'OnDuty',
timeResult: 'Normal',
},
],
}),
}) as jest.MockedFunction<typeof fetch>;
const [record] = await service.fetchAttendanceResults({
startDate: '2026-07-12',
endDate: '2026-07-12',
userIds: ['ding-1'],
});
expect(record.workDate).toBe('2026-07-12');
});
});