feat(api): admin account governance endpoints

P4a Task 6: GET /admin/users 双模式收口(无 accountPrefix 进入管理列表
模式:全量用户、query/status 过滤、createdAt+ID 倒序键集游标、仅 admin;
前缀模式 P1b 语义保留)+ PATCH / reset-password / activate / deactivate
治理端点(sourceStatus 只读拒绝、自我保护、会话撤销、审计、生成初始
密码)。附带修复 full-chain e2e 的 job-done 断言竞态(轮询条件补齐
photo_jobs 终态)。api e2e 214 → 227 全绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-20 19:31:00 +08:00
parent 4937eeecff
commit f4a1ba7a14
9 changed files with 1326 additions and 60 deletions
+23 -5
View File
@@ -293,14 +293,32 @@ describe('full-chain (e2e)', () => {
connection: workerConnection,
});
try {
// 轮询条件须覆盖**被断言的全部终态**:processor 里 photo ready(发布
// 事务提交)与 photo_jobs done(其后的独立 updateMany)是两次落库,
// 只轮询 photo 状态会在两写之间闯入断言窗口(P4a Task 6 全套件时序
// 下命中:job 仍 active 而 photo 已 ready)——一并轮询 job 终态。
await waitFor(
async () =>
(
await prisma.photos.findMany({
async () => {
const [photos, jobs] = await Promise.all([
prisma.photos.findMany({
where: { id: { in: [uploadA.photoId, uploadB.photoId] } },
select: { processingState: true },
})
).every((p) => p.processingState === 'ready'),
}),
prisma.photo_jobs.findMany({
where: {
photoId: { in: [uploadA.photoId, uploadB.photoId] },
type: 'process',
},
select: { state: true },
}),
]);
return (
photos.length === 2 &&
photos.every((p) => p.processingState === 'ready') &&
jobs.length === 2 &&
jobs.every((j) => j.state === 'done')
);
},
);
for (const { photoId } of [uploadA, uploadB]) {