@simple-auth-kit/cli 1.4.3 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/lib/copy.ts +1 -1
  2. package/package.json +1 -1
  3. package/registry/combos/express-drizzle/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
  4. package/registry/combos/express-drizzle/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +23 -7
  5. package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/middleware}/response-envelope.middleware.ts +15 -3
  6. package/registry/combos/express-drizzle/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +32 -9
  7. package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
  8. package/registry/combos/express-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
  9. package/registry/combos/express-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +20 -6
  10. package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
  11. package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +395 -0
  12. package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +52 -19
  13. package/registry/combos/express-drizzle/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
  14. package/registry/combos/express-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +28 -10
  15. package/registry/combos/express-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +239 -48
  16. package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +497 -0
  17. package/registry/combos/express-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +480 -109
  18. package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +69 -23
  19. package/registry/combos/express-drizzle/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
  20. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +147 -28
  21. package/registry/combos/express-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +30 -11
  22. package/registry/combos/express-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +319 -70
  23. package/registry/combos/express-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +127 -30
  24. package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +534 -0
  25. package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +194 -0
  26. package/registry/combos/express-drizzle/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +544 -122
  27. package/registry/combos/express-prisma/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
  28. package/registry/combos/express-prisma/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +19 -6
  29. package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/middleware}/response-envelope.middleware.ts +15 -3
  30. package/registry/combos/express-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +27 -9
  31. package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
  32. package/registry/combos/express-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
  33. package/registry/combos/express-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
  34. package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
  35. package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +398 -0
  36. package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +56 -21
  37. package/registry/combos/express-prisma/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
  38. package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +66 -18
  39. package/registry/combos/express-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  40. package/registry/combos/express-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +199 -48
  41. package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +508 -0
  42. package/registry/combos/express-prisma/variants/base/src/seed.ts +77 -19
  43. package/registry/combos/express-prisma/variants/base/src/{auth.service.ts → services/auth.service.ts} +454 -105
  44. package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +80 -25
  45. package/registry/combos/express-prisma/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
  46. package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +147 -28
  47. package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +72 -20
  48. package/registry/combos/express-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  49. package/registry/combos/express-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +272 -64
  50. package/registry/combos/express-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +86 -23
  51. package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +545 -0
  52. package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +194 -0
  53. package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +108 -28
  54. package/registry/combos/express-prisma/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +518 -119
  55. package/registry/combos/nestjs-drizzle/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
  56. package/registry/combos/nestjs-drizzle/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
  57. package/registry/combos/nestjs-drizzle/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
  58. package/registry/combos/nestjs-drizzle/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
  59. package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/interceptors}/response.interceptor.ts +10 -2
  60. package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +63 -0
  61. package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
  62. package/registry/combos/nestjs-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
  63. package/registry/combos/nestjs-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +21 -7
  64. package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
  65. package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1097 -307
  66. package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +44 -20
  67. package/registry/combos/nestjs-drizzle/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +228 -62
  68. package/registry/combos/nestjs-drizzle/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
  69. package/registry/combos/nestjs-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +27 -10
  70. package/registry/combos/nestjs-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +249 -51
  71. package/registry/combos/nestjs-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +499 -116
  72. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +48 -22
  73. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +269 -70
  74. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
  75. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
  76. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +29 -11
  77. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +323 -71
  78. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +131 -30
  79. package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +988 -0
  80. package/registry/combos/nestjs-prisma/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
  81. package/registry/combos/nestjs-prisma/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
  82. package/registry/combos/nestjs-prisma/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
  83. package/registry/combos/nestjs-prisma/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
  84. package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/interceptors}/response.interceptor.ts +10 -2
  85. package/registry/combos/nestjs-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +25 -8
  86. package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
  87. package/registry/combos/nestjs-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
  88. package/registry/combos/nestjs-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
  89. package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
  90. package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1097 -307
  91. package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +58 -27
  92. package/registry/combos/nestjs-prisma/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +469 -110
  93. package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.gateway.ts → gateways/audit-log.gateway.ts} +22 -6
  94. package/registry/combos/nestjs-prisma/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
  95. package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +97 -26
  96. package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  97. package/registry/combos/nestjs-prisma/variants/base/src/{country.repository.ts → repositories/country.repository.ts} +98 -25
  98. package/registry/combos/nestjs-prisma/variants/base/src/{customer.repository.ts → repositories/customer.repository.ts} +106 -27
  99. package/registry/combos/nestjs-prisma/variants/base/src/{language.repository.ts → repositories/language.repository.ts} +93 -25
  100. package/registry/combos/nestjs-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +229 -55
  101. package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +77 -19
  102. package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +1064 -0
  103. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +54 -26
  104. package/registry/combos/nestjs-prisma/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +544 -128
  105. package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
  106. package/registry/combos/nestjs-prisma/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
  107. package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +103 -28
  108. package/registry/combos/nestjs-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  109. package/registry/combos/nestjs-prisma/variants/workspaces/src/{country.repository.ts → repositories/country.repository.ts} +127 -26
  110. package/registry/combos/nestjs-prisma/variants/workspaces/src/{customer.repository.ts → repositories/customer.repository.ts} +137 -28
  111. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +243 -0
  112. package/registry/combos/nestjs-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +314 -74
  113. package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +94 -24
  114. package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +108 -28
  115. package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +961 -0
  116. package/registry.json +4 -4
  117. package/simple-auth-kit.ts +42 -11
  118. package/registry/combos/express-drizzle/shared/src/auth.router.ts +0 -266
  119. package/registry/combos/express-drizzle/shared/src/password-reset.repository.ts +0 -35
  120. package/registry/combos/express-drizzle/variants/base/src/admin.router.ts +0 -307
  121. package/registry/combos/express-drizzle/variants/workspaces/src/admin.router.ts +0 -323
  122. package/registry/combos/express-drizzle/variants/workspaces/src/workspace.router.ts +0 -123
  123. package/registry/combos/express-prisma/shared/src/auth.router.ts +0 -269
  124. package/registry/combos/express-prisma/shared/src/password-reset.repository.ts +0 -29
  125. package/registry/combos/express-prisma/variants/base/src/admin.router.ts +0 -314
  126. package/registry/combos/express-prisma/variants/workspaces/src/admin.router.ts +0 -330
  127. package/registry/combos/express-prisma/variants/workspaces/src/workspace.router.ts +0 -123
  128. package/registry/combos/nestjs-drizzle/shared/src/oauth.repository.ts +0 -36
  129. package/registry/combos/nestjs-drizzle/shared/src/password-reset.repository.ts +0 -29
  130. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.service.ts +0 -553
  131. package/registry/combos/nestjs-prisma/shared/src/password-reset.repository.ts +0 -29
  132. package/registry/combos/nestjs-prisma/variants/base/src/auth.service.ts +0 -618
  133. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.service.ts +0 -509
  134. package/registry/combos/nestjs-prisma/variants/workspaces/src/language.repository.ts +0 -143
@@ -1,8 +1,11 @@
1
- import { PrismaClient } from "../generated/prisma/client.js";
2
- import { HttpError } from "./http-error.js";
3
- import { provisionDefaultRoles, WORKSPACE_CREATOR_ROLES } from "./rbac.defaults.js";
1
+ import { PrismaClient } from "../../generated/prisma/client.js";
2
+ import { HttpError } from "../http-error.js";
3
+ import {
4
+ provisionDefaultRoles,
5
+ WORKSPACE_CREATOR_ROLES,
6
+ } from "../rbac.defaults.js";
4
7
  import { RbacRepository } from "./rbac.repository.js";
5
- import { toId } from "./id.helper.js";
8
+ import { toId } from "../id.helper.js";
6
9
 
7
10
  export interface WorkspaceSummary {
8
11
  id: string;
@@ -40,11 +43,23 @@ export class WorkspaceRepository {
40
43
  async create(userId: string, name: string): Promise<WorkspaceSummary> {
41
44
  const userIdBig = toId(userId);
42
45
  const workspace = await this.prisma.$transaction(async (tx) => {
43
- const created = await tx.workspace.create({ data: { name, createdBy: userIdBig, updatedBy: userIdBig } });
46
+ const created = await tx.workspace.create({
47
+ data: { name, createdBy: userIdBig, updatedBy: userIdBig },
48
+ });
44
49
  await provisionDefaultRoles(tx, created.id);
45
- const roles = await tx.role.findMany({ where: { workspaceId: created.id, slug: { in: WORKSPACE_CREATOR_ROLES } }, select: { id: true } });
50
+ const roles = await tx.role.findMany({
51
+ where: {
52
+ workspaceId: created.id,
53
+ slug: { in: WORKSPACE_CREATOR_ROLES },
54
+ },
55
+ select: { id: true },
56
+ });
46
57
  await tx.workspaceMember.create({
47
- data: { workspaceId: created.id, userId: userIdBig, roles: { create: roles.map((role) => ({ roleId: role.id })) } },
58
+ data: {
59
+ workspaceId: created.id,
60
+ userId: userIdBig,
61
+ roles: { create: roles.map((role) => ({ roleId: role.id })) },
62
+ },
48
63
  });
49
64
  return created;
50
65
  });
@@ -59,7 +74,10 @@ export class WorkspaceRepository {
59
74
  async listForUser(userId: string): Promise<WorkspaceSummary[]> {
60
75
  const memberships = await this.prisma.workspaceMember.findMany({
61
76
  where: { userId: toId(userId), workspace: { isDeleted: false } },
62
- include: { workspace: true, roles: { select: { role: { select: { slug: true } } } } },
77
+ include: {
78
+ workspace: true,
79
+ roles: { select: { role: { select: { slug: true } } } },
80
+ },
63
81
  orderBy: { createdAt: "asc" },
64
82
  });
65
83
  return memberships.map((m) => ({
@@ -73,7 +91,10 @@ export class WorkspaceRepository {
73
91
  async listMembers(workspaceId: string): Promise<MembershipSummary[]> {
74
92
  const rows = await this.prisma.workspaceMember.findMany({
75
93
  where: { workspaceId: toId(workspaceId), user: { isDeleted: false } },
76
- include: { user: true, roles: { select: { role: { select: { slug: true } } } } },
94
+ include: {
95
+ user: true,
96
+ roles: { select: { role: { select: { slug: true } } } },
97
+ },
77
98
  orderBy: { createdAt: "asc" },
78
99
  });
79
100
  return rows.map((row) => ({
@@ -85,15 +106,33 @@ export class WorkspaceRepository {
85
106
  }));
86
107
  }
87
108
 
88
- private async resolveMemberRoles(workspaceIdBig: bigint, roleSlugs?: string[]) {
109
+ private async resolveMemberRoles(
110
+ workspaceIdBig: bigint,
111
+ roleSlugs?: string[],
112
+ ) {
89
113
  const roles = await this.prisma.role.findMany({
90
114
  where: roleSlugs
91
- ? { workspaceId: workspaceIdBig, slug: { in: roleSlugs }, isDeleted: false }
92
- : { workspaceId: workspaceIdBig, isDefault: true, isActive: true, isDeleted: false },
115
+ ? {
116
+ workspaceId: workspaceIdBig,
117
+ slug: { in: roleSlugs },
118
+ isDeleted: false,
119
+ }
120
+ : {
121
+ workspaceId: workspaceIdBig,
122
+ isDefault: true,
123
+ isActive: true,
124
+ isDeleted: false,
125
+ },
93
126
  select: { id: true, slug: true },
94
127
  });
95
- const unknown = (roleSlugs ?? []).filter((slug) => !roles.some((role) => role.slug === slug));
96
- if (unknown.length) throw new HttpError(404, `role(s) not defined in this workspace: ${unknown.join(", ")}`);
128
+ const unknown = (roleSlugs ?? []).filter(
129
+ (slug) => !roles.some((role) => role.slug === slug),
130
+ );
131
+ if (unknown.length)
132
+ throw new HttpError(
133
+ 404,
134
+ `role(s) not defined in this workspace: ${unknown.join(", ")}`,
135
+ );
97
136
  return roles;
98
137
  }
99
138
 
@@ -102,17 +141,32 @@ export class WorkspaceRepository {
102
141
  * consuming app's job. With no roles named, the new membership gets whichever of this
103
142
  * workspace's roles are flagged `isDefault`, not a slug spelled in code.
104
143
  */
105
- async addMember(workspaceId: string, email: string, roleSlugs?: string[]): Promise<MembershipSummary> {
144
+ async addMember(
145
+ workspaceId: string,
146
+ email: string,
147
+ roleSlugs?: string[],
148
+ ): Promise<MembershipSummary> {
106
149
  const workspaceIdBig = toId(workspaceId);
107
- const user = await this.prisma.user.findUnique({ where: { email, isDeleted: false } });
150
+ const user = await this.prisma.user.findUnique({
151
+ where: { email, isDeleted: false },
152
+ });
108
153
  if (!user) throw new HttpError(404, "no user with that email");
109
154
 
110
- const existing = await this.prisma.workspaceMember.findUnique({ where: { userId_workspaceId: { userId: user.id, workspaceId: workspaceIdBig } } });
111
- if (existing) throw new HttpError(409, "already a member of this workspace");
155
+ const existing = await this.prisma.workspaceMember.findUnique({
156
+ where: {
157
+ userId_workspaceId: { userId: user.id, workspaceId: workspaceIdBig },
158
+ },
159
+ });
160
+ if (existing)
161
+ throw new HttpError(409, "already a member of this workspace");
112
162
 
113
163
  const roles = await this.resolveMemberRoles(workspaceIdBig, roleSlugs);
114
164
  const member = await this.prisma.workspaceMember.create({
115
- data: { workspaceId: workspaceIdBig, userId: user.id, roles: { create: roles.map((role) => ({ roleId: role.id })) } },
165
+ data: {
166
+ workspaceId: workspaceIdBig,
167
+ userId: user.id,
168
+ roles: { create: roles.map((role) => ({ roleId: role.id })) },
169
+ },
116
170
  });
117
171
  return {
118
172
  memberId: member.id.toString(),
@@ -143,7 +197,9 @@ export class WorkspaceRepository {
143
197
  actorUserId: string | null,
144
198
  ): Promise<MembershipSummary> {
145
199
  const workspaceIdBig = toId(workspaceId);
146
- const existing = await this.prisma.user.findUnique({ where: { email: input.email } });
200
+ const existing = await this.prisma.user.findUnique({
201
+ where: { email: input.email },
202
+ });
147
203
  if (existing) throw new HttpError(409, "email already registered");
148
204
 
149
205
  const roles = await this.resolveMemberRoles(workspaceIdBig, input.roles);
@@ -160,7 +216,11 @@ export class WorkspaceRepository {
160
216
  },
161
217
  });
162
218
  const member = await this.prisma.workspaceMember.create({
163
- data: { workspaceId: workspaceIdBig, userId: user.id, roles: { create: roles.map((role) => ({ roleId: role.id })) } },
219
+ data: {
220
+ workspaceId: workspaceIdBig,
221
+ userId: user.id,
222
+ roles: { create: roles.map((role) => ({ roleId: role.id })) },
223
+ },
164
224
  });
165
225
  return {
166
226
  memberId: member.id.toString(),
@@ -174,8 +234,11 @@ export class WorkspaceRepository {
174
234
  async removeMember(workspaceId: string, memberId: string): Promise<void> {
175
235
  const workspaceIdBig = toId(workspaceId);
176
236
  const memberIdBig = toId(memberId);
177
- const member = await this.prisma.workspaceMember.findUnique({ where: { id: memberIdBig } });
178
- if (!member || member.workspaceId !== workspaceIdBig) throw new HttpError(404, "member not found in this workspace");
237
+ const member = await this.prisma.workspaceMember.findUnique({
238
+ where: { id: memberIdBig },
239
+ });
240
+ if (!member || member.workspaceId !== workspaceIdBig)
241
+ throw new HttpError(404, "member not found in this workspace");
179
242
 
180
243
  // Role assignments and direct grants belong to the membership, so they go with it — that is
181
244
  // the point of hanging them off the member row. `onDelete: Cascade` on both join tables is