@jskit-ai/workspaces-core 0.1.14 → 0.1.16

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 (83) hide show
  1. package/package.descriptor.mjs +2 -2
  2. package/package.json +18 -3
  3. package/src/server/WorkspacesCoreServiceProvider.js +41 -2
  4. package/src/server/common/contributors/workspaceActionContextContributor.js +88 -0
  5. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +34 -0
  6. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +78 -0
  7. package/src/server/common/formatters/workspaceFormatter.js +53 -0
  8. package/src/server/common/repositories/repositoryUtils.js +59 -0
  9. package/src/server/common/repositories/workspaceInvitesRepository.js +208 -0
  10. package/src/server/common/repositories/workspaceMembershipsRepository.js +190 -0
  11. package/src/server/common/repositories/workspacesRepository.js +202 -0
  12. package/src/server/common/services/workspaceContextService.js +281 -0
  13. package/src/server/common/support/deepFreeze.js +1 -0
  14. package/src/server/common/support/realtimeServiceEvents.js +91 -0
  15. package/src/server/common/support/resolveActionUser.js +9 -0
  16. package/src/server/common/support/workspaceRoutePaths.js +18 -0
  17. package/src/server/common/validators/authenticatedUserValidator.js +43 -0
  18. package/src/server/common/validators/routeParamsValidator.js +62 -0
  19. package/src/server/registerWorkspaceBootstrap.js +27 -0
  20. package/src/server/registerWorkspaceCore.js +100 -0
  21. package/src/server/registerWorkspaceRepositories.js +26 -0
  22. package/src/server/support/resolveWorkspace.js +16 -0
  23. package/src/server/support/workspaceActionSurfaces.js +118 -0
  24. package/src/server/support/workspaceInvitationsPolicy.js +45 -0
  25. package/src/server/support/workspaceRouteInput.js +22 -0
  26. package/src/server/workspaceBootstrapContributor.js +233 -0
  27. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +133 -0
  28. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +19 -0
  29. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +133 -0
  30. package/src/server/workspaceMembers/bootWorkspaceMembers.js +236 -0
  31. package/src/server/workspaceMembers/registerWorkspaceMembers.js +108 -0
  32. package/src/server/workspaceMembers/workspaceMembersActions.js +186 -0
  33. package/src/server/workspaceMembers/workspaceMembersService.js +222 -0
  34. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +62 -0
  35. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +119 -0
  36. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +74 -0
  37. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +138 -0
  38. package/src/server/workspaceSettings/bootWorkspaceSettings.js +76 -0
  39. package/src/server/workspaceSettings/registerWorkspaceSettings.js +62 -0
  40. package/src/server/workspaceSettings/workspaceSettingsActions.js +72 -0
  41. package/src/server/workspaceSettings/workspaceSettingsRepository.js +154 -0
  42. package/src/server/workspaceSettings/workspaceSettingsService.js +66 -0
  43. package/src/shared/operationMessages.js +16 -0
  44. package/src/shared/resources/resolveGlobalArrayRegistry.js +6 -0
  45. package/src/shared/resources/workspaceMembersResource.js +354 -0
  46. package/src/shared/resources/workspacePendingInvitationsResource.js +82 -0
  47. package/src/shared/resources/workspaceResource.js +176 -0
  48. package/src/shared/resources/workspaceSettingsFields.js +59 -0
  49. package/src/shared/resources/workspaceSettingsResource.js +169 -0
  50. package/src/shared/roles.js +161 -0
  51. package/src/shared/settings.js +119 -0
  52. package/src/shared/support/workspacePathModel.js +145 -0
  53. package/src/shared/tenancyMode.js +35 -0
  54. package/src/shared/tenancyProfile.js +73 -0
  55. package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +2 -2
  56. package/test/registerServiceRealtimeEvents.test.js +116 -0
  57. package/test/registerWorkspaceDirectory.test.js +31 -0
  58. package/test/registerWorkspaceSettings.test.js +40 -0
  59. package/test/repositoryContracts.test.js +34 -0
  60. package/test/resourcesCanonical.test.js +74 -0
  61. package/test/roles.test.js +159 -0
  62. package/test/routeParamsValidator.test.js +49 -0
  63. package/test/settingsFieldRegistriesSingleton.test.js +14 -0
  64. package/test/tenancyProfile.test.js +67 -0
  65. package/test/usersRouteResources.test.js +97 -0
  66. package/test/workspaceActionContextContributor.test.js +344 -0
  67. package/test/workspaceActionSurfaces.test.js +85 -0
  68. package/test/workspaceAuthPolicyContextResolver.test.js +119 -0
  69. package/test/workspaceBootstrapContributor.test.js +169 -0
  70. package/test/workspaceInvitationsPolicy.test.js +71 -0
  71. package/test/workspaceInvitesRepository.test.js +111 -0
  72. package/test/workspaceMembersService.test.js +398 -0
  73. package/test/workspacePathModel.test.js +93 -0
  74. package/test/workspacePendingInvitationsResource.test.js +38 -0
  75. package/test/workspacePendingInvitationsService.test.js +151 -0
  76. package/test/workspaceRouteVisibilityResolver.test.js +83 -0
  77. package/test/workspaceService.test.js +546 -0
  78. package/test/workspaceSettingsActions.test.js +52 -0
  79. package/test/workspaceSettingsRepository.test.js +202 -0
  80. package/test/workspaceSettingsResource.test.js +169 -0
  81. package/test/workspaceSettingsService.test.js +140 -0
  82. package/test/workspacesRouteRequestInputValidator.test.js +5 -5
  83. package/test-support/registerDefaultSettingsFields.js +1 -0
@@ -0,0 +1,236 @@
1
+ import { withStandardErrorResponses } from "@jskit-ai/http-runtime/shared/validators/errorResponses";
2
+ import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
3
+ import { resolveWorkspaceRoutePath } from "../common/support/workspaceRoutePaths.js";
4
+ import {
5
+ routeParamsValidator,
6
+ workspaceSlugParamsValidator
7
+ } from "../common/validators/routeParamsValidator.js";
8
+ import { resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig } from "../support/workspaceActionSurfaces.js";
9
+
10
+ function bootWorkspaceMembers(app) {
11
+ if (!app || typeof app.make !== "function") {
12
+ throw new Error("bootWorkspaceMembers requires application make().");
13
+ }
14
+
15
+ const router = app.make("jskit.http.router");
16
+ const appConfig = typeof app.has === "function" && app.has("appConfig") ? app.make("appConfig") : {};
17
+ const workspaceInvitationsEnabled =
18
+ typeof app.has === "function" && app.has("workspaces.invitations.enabled")
19
+ ? app.make("workspaces.invitations.enabled") === true
20
+ : false;
21
+ const workspaceRouteSurfaceId = resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig(appConfig);
22
+
23
+ router.register(
24
+ "GET",
25
+ resolveWorkspaceRoutePath("/roles"),
26
+ {
27
+ auth: "required",
28
+ surface: workspaceRouteSurfaceId,
29
+ visibility: "workspace",
30
+ contextPolicy: "required",
31
+ meta: {
32
+ tags: ["workspace"],
33
+ summary: "Get workspace role catalog by workspace slug"
34
+ },
35
+ paramsValidator: workspaceSlugParamsValidator,
36
+ responseValidators: withStandardErrorResponses({
37
+ 200: workspaceMembersResource.operations.rolesList.outputValidator
38
+ })
39
+ },
40
+ async function (request, reply) {
41
+ const response = await request.executeAction({
42
+ actionId: "workspace.roles.list",
43
+ input: {
44
+ workspaceSlug: request.input.params.workspaceSlug
45
+ }
46
+ });
47
+ reply.code(200).send(response);
48
+ }
49
+ );
50
+
51
+ router.register(
52
+ "GET",
53
+ resolveWorkspaceRoutePath("/members"),
54
+ {
55
+ auth: "required",
56
+ surface: workspaceRouteSurfaceId,
57
+ visibility: "workspace",
58
+ contextPolicy: "required",
59
+ meta: {
60
+ tags: ["workspace"],
61
+ summary: "List members by workspace slug"
62
+ },
63
+ paramsValidator: workspaceSlugParamsValidator,
64
+ responseValidators: withStandardErrorResponses({
65
+ 200: workspaceMembersResource.operations.membersList.outputValidator
66
+ })
67
+ },
68
+ async function (request, reply) {
69
+ const response = await request.executeAction({
70
+ actionId: "workspace.members.list",
71
+ input: {
72
+ workspaceSlug: request.input.params.workspaceSlug
73
+ }
74
+ });
75
+ reply.code(200).send(response);
76
+ }
77
+ );
78
+
79
+ router.register(
80
+ "PATCH",
81
+ resolveWorkspaceRoutePath("/members/:memberUserId/role"),
82
+ {
83
+ auth: "required",
84
+ surface: workspaceRouteSurfaceId,
85
+ visibility: "workspace",
86
+ contextPolicy: "required",
87
+ meta: {
88
+ tags: ["workspace"],
89
+ summary: "Update workspace member role by workspace slug"
90
+ },
91
+ paramsValidator: routeParamsValidator,
92
+ bodyValidator: workspaceMembersResource.operations.updateMemberRole.bodyValidator,
93
+ responseValidators: withStandardErrorResponses(
94
+ {
95
+ 200: workspaceMembersResource.operations.updateMemberRole.outputValidator
96
+ },
97
+ { includeValidation400: true }
98
+ )
99
+ },
100
+ async function (request, reply) {
101
+ const response = await request.executeAction({
102
+ actionId: "workspace.member.role.update",
103
+ input: {
104
+ workspaceSlug: request.input.params.workspaceSlug,
105
+ memberUserId: request.input.params.memberUserId,
106
+ roleSid: request.input.body.roleSid
107
+ }
108
+ });
109
+ reply.code(200).send(response);
110
+ }
111
+ );
112
+
113
+ router.register(
114
+ "DELETE",
115
+ resolveWorkspaceRoutePath("/members/:memberUserId"),
116
+ {
117
+ auth: "required",
118
+ surface: workspaceRouteSurfaceId,
119
+ visibility: "workspace",
120
+ contextPolicy: "required",
121
+ meta: {
122
+ tags: ["workspace"],
123
+ summary: "Remove workspace member by workspace slug"
124
+ },
125
+ paramsValidator: routeParamsValidator,
126
+ responseValidators: withStandardErrorResponses({
127
+ 200: workspaceMembersResource.operations.removeMember.outputValidator
128
+ })
129
+ },
130
+ async function (request, reply) {
131
+ const response = await request.executeAction({
132
+ actionId: "workspace.member.remove",
133
+ input: {
134
+ workspaceSlug: request.input.params.workspaceSlug,
135
+ memberUserId: request.input.params.memberUserId
136
+ }
137
+ });
138
+ reply.code(200).send(response);
139
+ }
140
+ );
141
+
142
+ if (workspaceInvitationsEnabled) {
143
+ router.register(
144
+ "GET",
145
+ resolveWorkspaceRoutePath("/invites"),
146
+ {
147
+ auth: "required",
148
+ surface: workspaceRouteSurfaceId,
149
+ visibility: "workspace",
150
+ contextPolicy: "required",
151
+ meta: {
152
+ tags: ["workspace"],
153
+ summary: "List workspace invites by workspace slug"
154
+ },
155
+ paramsValidator: workspaceSlugParamsValidator,
156
+ responseValidators: withStandardErrorResponses({
157
+ 200: workspaceMembersResource.operations.invitesList.outputValidator
158
+ })
159
+ },
160
+ async function (request, reply) {
161
+ const response = await request.executeAction({
162
+ actionId: "workspace.invites.list",
163
+ input: {
164
+ workspaceSlug: request.input.params.workspaceSlug
165
+ }
166
+ });
167
+ reply.code(200).send(response);
168
+ }
169
+ );
170
+
171
+ router.register(
172
+ "POST",
173
+ resolveWorkspaceRoutePath("/invites"),
174
+ {
175
+ auth: "required",
176
+ surface: workspaceRouteSurfaceId,
177
+ visibility: "workspace",
178
+ contextPolicy: "required",
179
+ meta: {
180
+ tags: ["workspace"],
181
+ summary: "Create workspace invite by workspace slug"
182
+ },
183
+ paramsValidator: workspaceSlugParamsValidator,
184
+ bodyValidator: workspaceMembersResource.operations.createInvite.bodyValidator,
185
+ responseValidators: withStandardErrorResponses(
186
+ {
187
+ 200: workspaceMembersResource.operations.createInvite.outputValidator
188
+ },
189
+ { includeValidation400: true }
190
+ )
191
+ },
192
+ async function (request, reply) {
193
+ const response = await request.executeAction({
194
+ actionId: "workspace.invite.create",
195
+ input: {
196
+ workspaceSlug: request.input.params.workspaceSlug,
197
+ email: request.input.body.email,
198
+ roleSid: request.input.body.roleSid
199
+ }
200
+ });
201
+ reply.code(200).send(response);
202
+ }
203
+ );
204
+
205
+ router.register(
206
+ "DELETE",
207
+ resolveWorkspaceRoutePath("/invites/:inviteId"),
208
+ {
209
+ auth: "required",
210
+ surface: workspaceRouteSurfaceId,
211
+ visibility: "workspace",
212
+ contextPolicy: "required",
213
+ meta: {
214
+ tags: ["workspace"],
215
+ summary: "Revoke workspace invite by workspace slug"
216
+ },
217
+ paramsValidator: routeParamsValidator,
218
+ responseValidators: withStandardErrorResponses({
219
+ 200: workspaceMembersResource.operations.revokeInvite.outputValidator
220
+ })
221
+ },
222
+ async function (request, reply) {
223
+ const response = await request.executeAction({
224
+ actionId: "workspace.invite.revoke",
225
+ input: {
226
+ workspaceSlug: request.input.params.workspaceSlug,
227
+ inviteId: request.input.params.inviteId
228
+ }
229
+ });
230
+ reply.code(200).send(response);
231
+ }
232
+ );
233
+ }
234
+ }
235
+
236
+ export { bootWorkspaceMembers };
@@ -0,0 +1,108 @@
1
+ import { withActionDefaults } from "@jskit-ai/kernel/shared/actions";
2
+ import { normalizeDbRecordId } from "@jskit-ai/database-runtime/shared";
3
+ import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
4
+ import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
5
+ import { deepFreeze } from "../common/support/deepFreeze.js";
6
+ import { createService as createWorkspaceMembersService } from "./workspaceMembersService.js";
7
+ import { workspaceMembersActions } from "./workspaceMembersActions.js";
8
+ import { createWorkspaceRoleCatalog } from "../../shared/roles.js";
9
+ import { createWorkspaceEntityAndBootstrapEvents } from "../common/support/realtimeServiceEvents.js";
10
+
11
+
12
+ function resolveWorkspaceMembersInviteExpiresInMs(appConfig = {}) {
13
+ const inviteExpiresInMs = Number(appConfig?.workspaceMembers?.defaults?.inviteExpiresInMs);
14
+ if (!Number.isInteger(inviteExpiresInMs) || inviteExpiresInMs < 1) {
15
+ throw new TypeError("users.core requires appConfig.workspaceMembers.defaults.inviteExpiresInMs.");
16
+ }
17
+
18
+ return inviteExpiresInMs;
19
+ }
20
+
21
+ const INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE = Object.freeze({
22
+ preset: "event_scope",
23
+ async userQuery({ knex, event } = {}) {
24
+ if (typeof knex !== "function") {
25
+ return [];
26
+ }
27
+
28
+ const inviteId = normalizeRecordId(event?.entityId, { fallback: null });
29
+ if (!inviteId) {
30
+ return [];
31
+ }
32
+
33
+ const row = await knex("workspace_invites as wi")
34
+ .join("users as up", "up.email", "wi.email")
35
+ .where("wi.id", inviteId)
36
+ .first("up.id as user_id");
37
+
38
+ const userId = normalizeDbRecordId(row?.user_id, { fallback: null });
39
+ if (!userId) {
40
+ return [];
41
+ }
42
+
43
+ return [
44
+ {
45
+ userId
46
+ }
47
+ ];
48
+ }
49
+ });
50
+
51
+ function registerWorkspaceMembers(app) {
52
+ if (!app || typeof app.singleton !== "function" || typeof app.service !== "function" || typeof app.actions !== "function") {
53
+ throw new Error("registerWorkspaceMembers requires application singleton()/service()/actions().");
54
+ }
55
+
56
+ app.service(
57
+ "workspaces.members.service",
58
+ (scope) => {
59
+ const appConfig = resolveAppConfig(scope);
60
+ return createWorkspaceMembersService({
61
+ workspaceMembershipsRepository: scope.make("workspaceMembershipsRepository"),
62
+ workspaceInvitesRepository: scope.make("workspaceInvitesRepository"),
63
+ inviteExpiresInMs: resolveWorkspaceMembersInviteExpiresInMs(appConfig),
64
+ roleCatalog: createWorkspaceRoleCatalog(appConfig),
65
+ workspaceInvitationsEnabled: scope.make("workspaces.invitations.enabled") === true
66
+ });
67
+ },
68
+ {
69
+ events: deepFreeze({
70
+ updateMemberRole: createWorkspaceEntityAndBootstrapEvents({
71
+ workspaceEntity: "member",
72
+ workspaceOperation: "updated",
73
+ workspaceRealtimeEvent: "workspace.members.changed"
74
+ }),
75
+ removeMember: createWorkspaceEntityAndBootstrapEvents({
76
+ workspaceEntity: "member",
77
+ workspaceOperation: "updated",
78
+ workspaceRealtimeEvent: "workspace.members.changed"
79
+ }),
80
+ createInvite: createWorkspaceEntityAndBootstrapEvents({
81
+ workspaceEntity: "invite",
82
+ workspaceOperation: "created",
83
+ workspaceRealtimeEvent: "workspace.invites.changed",
84
+ bootstrapEntityId: ({ result }) => result?.createdInviteId,
85
+ bootstrapAudience: INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE
86
+ }),
87
+ revokeInvite: createWorkspaceEntityAndBootstrapEvents({
88
+ workspaceEntity: "invite",
89
+ workspaceOperation: "updated",
90
+ workspaceRealtimeEvent: "workspace.invites.changed",
91
+ bootstrapEntityId: ({ result }) => result?.revokedInviteId,
92
+ bootstrapAudience: INVITE_RECIPIENT_BOOTSTRAP_AUDIENCE
93
+ })
94
+ })
95
+ }
96
+ );
97
+
98
+ app.actions(
99
+ withActionDefaults(workspaceMembersActions, {
100
+ domain: "workspace",
101
+ dependencies: {
102
+ workspaceMembersService: "workspaces.members.service"
103
+ }
104
+ })
105
+ );
106
+ }
107
+
108
+ export { registerWorkspaceMembers };
@@ -0,0 +1,186 @@
1
+ import { resolveWorkspace } from "../support/resolveWorkspace.js";
2
+ import { resolveActionUser } from "../common/support/resolveActionUser.js";
3
+ import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
4
+ import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
5
+
6
+ const workspaceMembersActions = Object.freeze([
7
+ {
8
+ id: "workspace.roles.list",
9
+ version: 1,
10
+ kind: "query",
11
+ channels: ["api", "automation", "internal"],
12
+ surfacesFrom: "workspace",
13
+ permission: {
14
+ require: "all",
15
+ permissions: ["workspace.roles.view"]
16
+ },
17
+ inputValidator: workspaceSlugParamsValidator,
18
+ outputValidator: workspaceMembersResource.operations.rolesList.outputValidator,
19
+ idempotency: "none",
20
+ audit: {
21
+ actionName: "workspace.roles.list"
22
+ },
23
+ observability: {},
24
+ async execute(_input, context, deps) {
25
+ return deps.workspaceMembersService.listRoles({ context });
26
+ }
27
+ },
28
+ {
29
+ id: "workspace.members.list",
30
+ version: 1,
31
+ kind: "query",
32
+ channels: ["api", "automation", "internal"],
33
+ surfacesFrom: "workspace",
34
+ permission: {
35
+ require: "all",
36
+ permissions: ["workspace.members.view"]
37
+ },
38
+ inputValidator: workspaceSlugParamsValidator,
39
+ outputValidator: workspaceMembersResource.operations.membersList.outputValidator,
40
+ idempotency: "none",
41
+ audit: {
42
+ actionName: "workspace.members.list"
43
+ },
44
+ observability: {},
45
+ async execute(input, context, deps) {
46
+ return deps.workspaceMembersService.listMembers(resolveWorkspace(context, input), {
47
+ context
48
+ });
49
+ }
50
+ },
51
+ {
52
+ id: "workspace.member.role.update",
53
+ version: 1,
54
+ kind: "command",
55
+ channels: ["api", "automation", "internal"],
56
+ surfacesFrom: "workspace",
57
+ permission: {
58
+ require: "all",
59
+ permissions: ["workspace.members.manage"]
60
+ },
61
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.updateMemberRole.inputValidator],
62
+ outputValidator: workspaceMembersResource.operations.updateMemberRole.outputValidator,
63
+ idempotency: "optional",
64
+ audit: {
65
+ actionName: "workspace.member.role.update"
66
+ },
67
+ observability: {},
68
+ async execute(input, context, deps) {
69
+ return deps.workspaceMembersService.updateMemberRole(resolveWorkspace(context, input), {
70
+ memberUserId: input.memberUserId,
71
+ roleSid: input.roleSid
72
+ }, {
73
+ context
74
+ });
75
+ }
76
+ },
77
+ {
78
+ id: "workspace.member.remove",
79
+ version: 1,
80
+ kind: "command",
81
+ channels: ["api", "automation", "internal"],
82
+ surfacesFrom: "workspace",
83
+ permission: {
84
+ require: "all",
85
+ permissions: ["workspace.members.manage"]
86
+ },
87
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.removeMember.inputValidator],
88
+ outputValidator: workspaceMembersResource.operations.removeMember.outputValidator,
89
+ idempotency: "optional",
90
+ audit: {
91
+ actionName: "workspace.member.remove"
92
+ },
93
+ observability: {},
94
+ async execute(input, context, deps) {
95
+ return deps.workspaceMembersService.removeMember(resolveWorkspace(context, input), {
96
+ memberUserId: input.memberUserId
97
+ }, {
98
+ context
99
+ });
100
+ }
101
+ },
102
+ {
103
+ id: "workspace.invites.list",
104
+ version: 1,
105
+ kind: "query",
106
+ channels: ["api", "automation", "internal"],
107
+ surfacesFrom: "workspace",
108
+ permission: {
109
+ require: "all",
110
+ permissions: ["workspace.members.view"]
111
+ },
112
+ inputValidator: workspaceSlugParamsValidator,
113
+ outputValidator: workspaceMembersResource.operations.invitesList.outputValidator,
114
+ idempotency: "none",
115
+ audit: {
116
+ actionName: "workspace.invites.list"
117
+ },
118
+ observability: {},
119
+ async execute(input, context, deps) {
120
+ return deps.workspaceMembersService.listInvites(resolveWorkspace(context, input), {
121
+ context
122
+ });
123
+ }
124
+ },
125
+ {
126
+ id: "workspace.invite.create",
127
+ version: 1,
128
+ kind: "command",
129
+ channels: ["api", "assistant_tool", "automation", "internal"],
130
+ surfacesFrom: "workspace",
131
+ permission: {
132
+ require: "all",
133
+ permissions: ["workspace.members.invite"]
134
+ },
135
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.createInvite.bodyValidator],
136
+ outputValidator: workspaceMembersResource.operations.createInvite.outputValidator,
137
+ idempotency: "optional",
138
+ audit: {
139
+ actionName: "workspace.invite.create"
140
+ },
141
+ observability: {},
142
+ extensions: {
143
+ assistant: {
144
+ description: "Invite a person to the workspace."
145
+ }
146
+ },
147
+ async execute(input, context, deps) {
148
+ return deps.workspaceMembersService.createInvite(
149
+ resolveWorkspace(context, input),
150
+ resolveActionUser(context, input),
151
+ {
152
+ email: input.email,
153
+ roleSid: input.roleSid
154
+ },
155
+ {
156
+ context
157
+ }
158
+ );
159
+ }
160
+ },
161
+ {
162
+ id: "workspace.invite.revoke",
163
+ version: 1,
164
+ kind: "command",
165
+ channels: ["api", "automation", "internal"],
166
+ surfacesFrom: "workspace",
167
+ permission: {
168
+ require: "all",
169
+ permissions: ["workspace.invites.revoke"]
170
+ },
171
+ inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.revokeInvite.inputValidator],
172
+ outputValidator: workspaceMembersResource.operations.revokeInvite.outputValidator,
173
+ idempotency: "optional",
174
+ audit: {
175
+ actionName: "workspace.invite.revoke"
176
+ },
177
+ observability: {},
178
+ async execute(input, context, deps) {
179
+ return deps.workspaceMembersService.revokeInvite(resolveWorkspace(context, input), input.inviteId, {
180
+ context
181
+ });
182
+ }
183
+ }
184
+ ]);
185
+
186
+ export { workspaceMembersActions };