/** * GroupResolver port(契约 C2)。 * * 权限计算只依赖这一个查询:"用户 → 所属 Group(含全部祖先)"。 * ADR-0028 起,默认实现是 in-hub 的 MemberGroup 闭包读取器 * (`createMemberGroupResolver`,见 memberGroupResolver.ts); * `HUB_GROUP_SERVICE_URL` 配置后切外部 HTTP 实现(groupResolverHttp.ts)。 * 调用方只依赖此 port,不换调用点。 */ import type { PrismaClient } from "@prisma/client"; export interface GroupResolver { resolveMemberGroupIds(userId: string): Promise; } /** * @deprecated ADR-0028:成员组已内置为 in-hub MemberGroup,默认 resolver 改为 * `createMemberGroupResolver`。此扁平 Team 过渡实现不再接线,保留仅为历史参照 * (以及潜在的迁移对照),新代码不要使用。 * * 旧过渡实现:读 hub 既有 Team(org 内、扁平无嵌套 → "祖先即自身")。 */ export function createTeamGroupResolver( prisma: PrismaClient, organizationId: string, ): GroupResolver { return { async resolveMemberGroupIds(userId) { const memberships = await prisma.teamMembership.findMany({ where: { userId, revokedAt: null, team: { organizationId, archivedAt: null }, }, select: { teamId: true }, }); return memberships.map((m) => m.teamId); }, }; } /** 单测 mock:静态 用户→组 映射。 */ export function createStaticGroupResolver( map: Readonly>, ): GroupResolver { return { async resolveMemberGroupIds(userId) { return map[userId] ?? []; }, }; }