apps/server/docs/ai-context/verifications/admin-user-balance-ban.md
6f63ce96e(工作区改动未提交),本地 vitest + PGlite 内存 Postgresadmin 插件的 role(删 ADMIN_EMAILS);ban/unban 收敛到 better-auth 原生 user.banned;改余额保留自建。设计见 ../account-ban.md命令:
pnpm -F @proj-airi/server typecheck # tsc --noEmit,无输出(通过)
pnpm exec vitest run apps/server # 全量 Test Files 43 passed / Tests 398 passed(含 tests/ 集成测试)
pnpm db:generate # → drizzle/0013_naive_groot.sql
pnpm -F @proj-airi/server-schema build # 重新打包迁移
role-based adminGuard(HTTP 边界)
middlewares/tests/admin-guard.test.ts 5 个用例通过admin flux-grants 走 role 鉴权(真实 app + PGlite 集成)
tests/verifications/admin-flux-grants.integration.test.ts 通过,经 buildApp 全量装配 + 真实 PGlite(user 表带新 role 列),adminGuard 读 user.role 判定封禁立即生效(热路径,OIDC JWT)
resolveRequestAuth 对 user.banned 命中的 principal 返回 null(即使 session 能解析);banExpires 已过期当未封禁libs/tests/request-auth.test.ts「rejects a banned principal even when the session resolves」「treats an expired ban as not banned」通过userinfo 封禁 guard(HTTP 边界)
/api/auth/oauth2/userinfo → 403 不到 handler;未封禁透传;ban 过期透传routes/auth/oidc-userinfo-ban.test.ts 3 个用例通过,挂真实 createAuthRoutes 装配,banned 由 mock 的 getSession user 驱动改余额为 0 / 任意值(含缓存失效)
user_flux.flux 覆盖,写 admin_set 账本(direction + before/after + issuedBy),提交后 redis.del 失效缓存services/domain/billing/tests/billing-service.test.ts setFlux 三个用例通过(设值 / 归零 / 初始化行 + redis.del 断言)余额 route 鉴权 + 校验(HTTP 边界)
routes/admin/users/route.test.ts 6 个用例通过迁移
drizzle/0013_naive_groot.sql:ALTER user ADD role/banned/ban_reason/ban_expires + ALTER session ADD impersonated_by,无 account_ban封禁撤销 OAuth 凭据(codex review 发现)
updateUser 写 banned=true)触发 databaseHooks.user.update.after,删该用户 oauth refresh/access token,堵住「refresh grant 换新 JWT」// NOTICE:,typecheck/lint 通过。hook 真正触发依赖 better-auth updateUser 全流程,属下方 pending(同 admin 端点真实登录流)。新 JWT 即便被 mint 也已被 isUserBannedNow 在第 3、4 条覆盖的资源路径挡住admin 插件自身的 /api/auth/admin/ban-user|unban-user 端点 + session.create.before 登录拦截未跑真实 better-auth 登录流(需起真服务 + Postgres + OAuth)。靠源码确认语义;我们自己的热路径闸(resolveRequestAuth / userinfo guard)已被第 3、4 条真实执行覆盖UPDATE "user" SET role='admin' WHERE email='...';多实例 Railway + 真实 Redis 下的封禁延迟未测ADMIN_EMAILS:首次部署/新环境要手动设 role../account-ban.md)@better-auth/infra dash() 是闭源 SaaS + 数据外发 + 不可扩展,业务管理将来自建 UI