@jskit-ai/users-core 0.1.4

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 (148) hide show
  1. package/package.descriptor.mjs +464 -0
  2. package/package.json +35 -0
  3. package/src/server/UsersCoreServiceProvider.js +74 -0
  4. package/src/server/accountNotifications/accountNotificationsActions.js +39 -0
  5. package/src/server/accountNotifications/accountNotificationsService.js +41 -0
  6. package/src/server/accountNotifications/bootAccountNotificationsRoutes.js +41 -0
  7. package/src/server/accountNotifications/registerAccountNotifications.js +39 -0
  8. package/src/server/accountPreferences/accountPreferencesActions.js +39 -0
  9. package/src/server/accountPreferences/accountPreferencesService.js +41 -0
  10. package/src/server/accountPreferences/bootAccountPreferencesRoutes.js +41 -0
  11. package/src/server/accountPreferences/registerAccountPreferences.js +39 -0
  12. package/src/server/accountProfile/accountProfileActions.js +137 -0
  13. package/src/server/accountProfile/accountProfileService.js +124 -0
  14. package/src/server/accountProfile/avatarService.js +141 -0
  15. package/src/server/accountProfile/avatarStorageService.js +132 -0
  16. package/src/server/accountProfile/bootAccountProfileRoutes.js +166 -0
  17. package/src/server/accountProfile/registerAccountProfile.js +62 -0
  18. package/src/server/accountProfile/registerAvatarMultipartSupport.js +43 -0
  19. package/src/server/accountSecurity/accountSecurityActions.js +144 -0
  20. package/src/server/accountSecurity/accountSecurityService.js +103 -0
  21. package/src/server/accountSecurity/bootAccountSecurityRoutes.js +183 -0
  22. package/src/server/accountSecurity/registerAccountSecurity.js +31 -0
  23. package/src/server/common/README.md +21 -0
  24. package/src/server/common/contributors/README.md +11 -0
  25. package/src/server/common/contributors/workspaceActionContextContributor.js +79 -0
  26. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +34 -0
  27. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +79 -0
  28. package/src/server/common/diTokens.js +21 -0
  29. package/src/server/common/formatters/README.md +11 -0
  30. package/src/server/common/formatters/accountAvatarFormatter.js +42 -0
  31. package/src/server/common/formatters/accountSecurityStatusFormatter.js +71 -0
  32. package/src/server/common/formatters/accountSettingsResponseFormatter.js +62 -0
  33. package/src/server/common/formatters/workspaceFormatter.js +46 -0
  34. package/src/server/common/registerCommonRepositories.js +45 -0
  35. package/src/server/common/registerSharedApi.js +9 -0
  36. package/src/server/common/repositories/README.md +24 -0
  37. package/src/server/common/repositories/repositoryUtils.js +50 -0
  38. package/src/server/common/repositories/userProfilesRepository.js +251 -0
  39. package/src/server/common/repositories/userSettingsRepository.js +179 -0
  40. package/src/server/common/repositories/workspaceInvitesRepository.js +172 -0
  41. package/src/server/common/repositories/workspaceMembershipsRepository.js +157 -0
  42. package/src/server/common/repositories/workspacesRepository.js +183 -0
  43. package/src/server/common/routes/README.md +11 -0
  44. package/src/server/common/services/README.md +12 -0
  45. package/src/server/common/services/accountContextService.js +31 -0
  46. package/src/server/common/services/authProfileSyncService.js +128 -0
  47. package/src/server/common/services/workspaceContextService.js +270 -0
  48. package/src/server/common/support/deepFreeze.js +17 -0
  49. package/src/server/common/support/realtimeServiceEvents.js +94 -0
  50. package/src/server/common/support/resolveActionUser.js +11 -0
  51. package/src/server/common/support/workspaceRoutePaths.js +17 -0
  52. package/src/server/common/validators/README.md +11 -0
  53. package/src/server/common/validators/authenticatedUserValidator.js +42 -0
  54. package/src/server/common/validators/routeParamsValidator.js +62 -0
  55. package/src/server/consoleSettings/bootConsoleSettingsRoutes.js +64 -0
  56. package/src/server/consoleSettings/consoleService.js +36 -0
  57. package/src/server/consoleSettings/consoleSettingsActions.js +55 -0
  58. package/src/server/consoleSettings/consoleSettingsRepository.js +111 -0
  59. package/src/server/consoleSettings/consoleSettingsService.js +40 -0
  60. package/src/server/consoleSettings/registerConsoleSettings.js +57 -0
  61. package/src/server/registerWorkspaceBootstrap.js +36 -0
  62. package/src/server/registerWorkspaceCore.js +95 -0
  63. package/src/server/support/resolveWorkspace.js +16 -0
  64. package/src/server/support/workspaceActionSurfaces.js +135 -0
  65. package/src/server/support/workspaceInvitationsPolicy.js +45 -0
  66. package/src/server/support/workspaceRouteInput.js +22 -0
  67. package/src/server/workspaceBootstrapContributor.js +401 -0
  68. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +73 -0
  69. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +19 -0
  70. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +65 -0
  71. package/src/server/workspaceMembers/bootWorkspaceMembers.js +238 -0
  72. package/src/server/workspaceMembers/registerWorkspaceMembers.js +112 -0
  73. package/src/server/workspaceMembers/workspaceMembersActions.js +186 -0
  74. package/src/server/workspaceMembers/workspaceMembersService.js +210 -0
  75. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +63 -0
  76. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +128 -0
  77. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +74 -0
  78. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +137 -0
  79. package/src/server/workspaceSettings/bootWorkspaceSettings.js +77 -0
  80. package/src/server/workspaceSettings/registerWorkspaceSettings.js +67 -0
  81. package/src/server/workspaceSettings/workspaceSettingsActions.js +72 -0
  82. package/src/server/workspaceSettings/workspaceSettingsRepository.js +135 -0
  83. package/src/server/workspaceSettings/workspaceSettingsService.js +65 -0
  84. package/src/shared/events/usersEvents.js +19 -0
  85. package/src/shared/index.js +91 -0
  86. package/src/shared/operationMessages.js +16 -0
  87. package/src/shared/resources/consoleSettingsFields.js +55 -0
  88. package/src/shared/resources/consoleSettingsResource.js +139 -0
  89. package/src/shared/resources/resolveGlobalArrayRegistry.js +6 -0
  90. package/src/shared/resources/userProfileResource.js +148 -0
  91. package/src/shared/resources/userSettingsFields.js +71 -0
  92. package/src/shared/resources/userSettingsResource.js +416 -0
  93. package/src/shared/resources/workspaceMembersResource.js +352 -0
  94. package/src/shared/resources/workspacePendingInvitationsResource.js +87 -0
  95. package/src/shared/resources/workspaceResource.js +149 -0
  96. package/src/shared/resources/workspaceSettingsFields.js +60 -0
  97. package/src/shared/resources/workspaceSettingsResource.js +178 -0
  98. package/src/shared/roles.js +136 -0
  99. package/src/shared/settings.js +31 -0
  100. package/src/shared/support/usersApiPaths.js +34 -0
  101. package/src/shared/support/usersVisibility.js +45 -0
  102. package/src/shared/support/workspacePathModel.js +145 -0
  103. package/src/shared/tenancyMode.js +35 -0
  104. package/src/shared/tenancyProfile.js +73 -0
  105. package/templates/config/workspaceRoles.js +30 -0
  106. package/templates/migrations/users_core_console_owner.cjs +39 -0
  107. package/templates/migrations/users_core_initial.cjs +118 -0
  108. package/templates/migrations/users_core_profile_username.cjs +98 -0
  109. package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +11 -0
  110. package/templates/packages/main/src/shared/resources/userSettingsFields.js +138 -0
  111. package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +105 -0
  112. package/test/authProfileSyncService.test.js +119 -0
  113. package/test/avatarService.test.js +114 -0
  114. package/test/avatarStorageService.test.js +61 -0
  115. package/test/consoleService.test.js +57 -0
  116. package/test/consoleSettingsService.test.js +86 -0
  117. package/test/exportsContract.test.js +38 -0
  118. package/test/registerAvatarMultipartSupport.test.js +64 -0
  119. package/test/registerServiceRealtimeEvents.test.js +160 -0
  120. package/test/registerWorkspaceDirectory.test.js +26 -0
  121. package/test/registerWorkspaceSettings.test.js +44 -0
  122. package/test/resourcesCanonical.test.js +90 -0
  123. package/test/roles.test.js +74 -0
  124. package/test/settingsFieldRegistriesSingleton.test.js +24 -0
  125. package/test/tenancyProfile.test.js +67 -0
  126. package/test/userSettingsResource.test.js +31 -0
  127. package/test/usersApiPaths.test.js +31 -0
  128. package/test/usersRouteRequestInputValidator.test.js +556 -0
  129. package/test/usersRouteResources.test.js +113 -0
  130. package/test/usersRouteValidators.test.js +49 -0
  131. package/test/usersVisibility.test.js +22 -0
  132. package/test/workspaceActionContextContributor.test.js +251 -0
  133. package/test/workspaceActionSurfaces.test.js +105 -0
  134. package/test/workspaceAuthPolicyContextResolver.test.js +119 -0
  135. package/test/workspaceBootstrapContributor.test.js +466 -0
  136. package/test/workspaceInvitationsPolicy.test.js +71 -0
  137. package/test/workspaceInvitesRepository.test.js +111 -0
  138. package/test/workspaceMembersService.test.js +400 -0
  139. package/test/workspacePathModel.test.js +93 -0
  140. package/test/workspacePendingInvitationsResource.test.js +38 -0
  141. package/test/workspacePendingInvitationsService.test.js +151 -0
  142. package/test/workspaceRouteVisibilityResolver.test.js +83 -0
  143. package/test/workspaceService.test.js +480 -0
  144. package/test/workspaceSettingsActions.test.js +42 -0
  145. package/test/workspaceSettingsRepository.test.js +156 -0
  146. package/test/workspaceSettingsResource.test.js +156 -0
  147. package/test/workspaceSettingsService.test.js +120 -0
  148. package/test-support/registerDefaultSettingsFields.js +3 -0
@@ -0,0 +1,464 @@
1
+ export default Object.freeze({
2
+ packageVersion: 1,
3
+ packageId: "@jskit-ai/users-core",
4
+ version: "0.1.4",
5
+ description: "Users/workspace domain runtime plus HTTP routes for workspace, account, and console features.",
6
+ dependsOn: [
7
+ "@jskit-ai/auth-core",
8
+ "@jskit-ai/database-runtime",
9
+ "@jskit-ai/http-runtime",
10
+ "@jskit-ai/storage-runtime"
11
+ ],
12
+ capabilities: {
13
+ provides: [
14
+ "users.core",
15
+ "users.server-routes"
16
+ ],
17
+ requires: [
18
+ "runtime.actions",
19
+ "runtime.database",
20
+ "runtime.storage",
21
+ "auth.provider",
22
+ "auth.policy"
23
+ ]
24
+ },
25
+ runtime: {
26
+ server: {
27
+ providers: [
28
+ {
29
+ entrypoint: "src/server/UsersCoreServiceProvider.js",
30
+ export: "UsersCoreServiceProvider"
31
+ }
32
+ ]
33
+ },
34
+ client: {
35
+ providers: []
36
+ }
37
+ },
38
+ metadata: {
39
+ apiSummary: {
40
+ surfaces: [
41
+ {
42
+ subpath: "./server",
43
+ summary:
44
+ "Exports UsersCoreServiceProvider, users/workspace/console repositories/services, feature route registration modules, and action definitions."
45
+ },
46
+ {
47
+ subpath: "./shared",
48
+ summary: "Exports shared users/workspace role and settings utilities."
49
+ },
50
+ {
51
+ subpath: "./client",
52
+ summary: "Exports no runtime API today (reserved client entrypoint)."
53
+ }
54
+ ],
55
+ containerTokens: {
56
+ server: [
57
+ "users.core",
58
+ "users.profile.sync.service",
59
+ "users.workspace.service",
60
+ "users.workspace.members.service",
61
+ "users.workspace.settings.service",
62
+ "users.settings.service",
63
+ "users.console.settings.service"
64
+ ],
65
+ client: []
66
+ }
67
+ },
68
+ server: {
69
+ routes: [
70
+ {
71
+ method: "POST",
72
+ path: "/api/workspaces",
73
+ summary: "Create a workspace for the authenticated user."
74
+ },
75
+ {
76
+ method: "GET",
77
+ path: "/api/workspaces",
78
+ summary: "List workspaces visible to authenticated user."
79
+ },
80
+ {
81
+ method: "GET",
82
+ path: "/api/workspace/invitations/pending",
83
+ summary: "List pending workspace invitations for authenticated user."
84
+ },
85
+ {
86
+ method: "POST",
87
+ path: "/api/workspace/invitations/redeem",
88
+ summary: "Accept or refuse a workspace invitation using an invite token."
89
+ },
90
+ {
91
+ method: "GET",
92
+ path: "/api/w/:workspaceSlug/workspace/settings",
93
+ summary: "Get workspace settings and role catalog by workspace slug."
94
+ },
95
+ {
96
+ method: "PATCH",
97
+ path: "/api/w/:workspaceSlug/workspace/settings",
98
+ summary: "Update workspace settings by workspace slug."
99
+ },
100
+ {
101
+ method: "GET",
102
+ path: "/api/w/:workspaceSlug/workspace/roles",
103
+ summary: "Get workspace role catalog by workspace slug."
104
+ },
105
+ {
106
+ method: "GET",
107
+ path: "/api/w/:workspaceSlug/workspace/members",
108
+ summary: "List members by workspace slug."
109
+ },
110
+ {
111
+ method: "PATCH",
112
+ path: "/api/w/:workspaceSlug/workspace/members/:memberUserId/role",
113
+ summary: "Update workspace member role by workspace slug."
114
+ },
115
+ {
116
+ method: "GET",
117
+ path: "/api/w/:workspaceSlug/workspace/invites",
118
+ summary: "List workspace invites by workspace slug."
119
+ },
120
+ {
121
+ method: "POST",
122
+ path: "/api/w/:workspaceSlug/workspace/invites",
123
+ summary: "Create workspace invite by workspace slug."
124
+ },
125
+ {
126
+ method: "DELETE",
127
+ path: "/api/w/:workspaceSlug/workspace/invites/:inviteId",
128
+ summary: "Revoke workspace invite by workspace slug."
129
+ },
130
+ {
131
+ method: "GET",
132
+ path: "/api/settings",
133
+ summary: "Get authenticated user settings."
134
+ },
135
+ {
136
+ method: "PATCH",
137
+ path: "/api/settings/profile",
138
+ summary: "Update profile settings."
139
+ },
140
+ {
141
+ method: "GET",
142
+ path: "/api/settings/profile/avatar",
143
+ summary: "Read authenticated user's uploaded avatar."
144
+ },
145
+ {
146
+ method: "POST",
147
+ path: "/api/settings/profile/avatar",
148
+ summary: "Upload profile avatar."
149
+ },
150
+ {
151
+ method: "DELETE",
152
+ path: "/api/settings/profile/avatar",
153
+ summary: "Delete profile avatar."
154
+ },
155
+ {
156
+ method: "PATCH",
157
+ path: "/api/settings/preferences",
158
+ summary: "Update user preferences."
159
+ },
160
+ {
161
+ method: "PATCH",
162
+ path: "/api/settings/notifications",
163
+ summary: "Update notification settings."
164
+ },
165
+ {
166
+ method: "POST",
167
+ path: "/api/settings/security/change-password",
168
+ summary: "Set or change password for authenticated user."
169
+ },
170
+ {
171
+ method: "PATCH",
172
+ path: "/api/settings/security/methods/password",
173
+ summary: "Enable or disable password sign-in method."
174
+ },
175
+ {
176
+ method: "GET",
177
+ path: "/api/settings/security/oauth/:provider/start",
178
+ summary: "Start linking an OAuth provider for authenticated user."
179
+ },
180
+ {
181
+ method: "DELETE",
182
+ path: "/api/settings/security/oauth/:provider",
183
+ summary: "Unlink an OAuth provider from authenticated account."
184
+ },
185
+ {
186
+ method: "POST",
187
+ path: "/api/settings/security/logout-others",
188
+ summary: "Sign out from other active sessions."
189
+ },
190
+ {
191
+ method: "GET",
192
+ path: "/api/console/settings",
193
+ summary: "Get console settings."
194
+ },
195
+ {
196
+ method: "PATCH",
197
+ path: "/api/console/settings",
198
+ summary: "Update console settings."
199
+ }
200
+ ]
201
+ }
202
+ },
203
+ mutations: {
204
+ dependencies: {
205
+ runtime: {
206
+ "@jskit-ai/auth-core": "0.1.4",
207
+ "@jskit-ai/database-runtime": "0.1.4",
208
+ "@jskit-ai/http-runtime": "0.1.4",
209
+ "@jskit-ai/kernel": "0.1.4",
210
+ "@fastify/multipart": "^9.4.0",
211
+ "@fastify/type-provider-typebox": "^6.1.0",
212
+ "typebox": "^1.0.81"
213
+ },
214
+ dev: {}
215
+ },
216
+ packageJson: {
217
+ scripts: {}
218
+ },
219
+ procfile: {},
220
+ files: [
221
+ {
222
+ op: "install-migration",
223
+ from: "templates/migrations/users_core_initial.cjs",
224
+ toDir: "migrations",
225
+ slug: "users_core_initial",
226
+ extension: ".cjs",
227
+ reason: "Install users/workspace core schema migration.",
228
+ category: "migration",
229
+ id: "users-core-initial-schema"
230
+ },
231
+ {
232
+ op: "install-migration",
233
+ from: "templates/migrations/users_core_profile_username.cjs",
234
+ toDir: "migrations",
235
+ slug: "users_core_profile_username",
236
+ extension: ".cjs",
237
+ reason: "Install users profile username migration.",
238
+ category: "migration",
239
+ id: "users-core-profile-username-schema"
240
+ },
241
+ {
242
+ op: "install-migration",
243
+ from: "templates/migrations/users_core_console_owner.cjs",
244
+ toDir: "migrations",
245
+ slug: "users_core_console_owner",
246
+ extension: ".cjs",
247
+ reason: "Install users/workspace console owner migration.",
248
+ category: "migration",
249
+ id: "users-core-console-owner-schema"
250
+ },
251
+ {
252
+ from: "templates/packages/main/src/shared/resources/workspaceSettingsFields.js",
253
+ to: "packages/main/src/shared/resources/workspaceSettingsFields.js",
254
+ preserveOnRemove: true,
255
+ reason: "Install app-owned workspace settings field definitions.",
256
+ category: "users-core",
257
+ id: "users-core-app-owned-workspace-settings-fields"
258
+ },
259
+ {
260
+ from: "templates/packages/main/src/shared/resources/consoleSettingsFields.js",
261
+ to: "packages/main/src/shared/resources/consoleSettingsFields.js",
262
+ preserveOnRemove: true,
263
+ reason: "Install app-owned console settings field definitions.",
264
+ category: "users-core",
265
+ id: "users-core-app-owned-console-settings-fields"
266
+ },
267
+ {
268
+ from: "templates/packages/main/src/shared/resources/userSettingsFields.js",
269
+ to: "packages/main/src/shared/resources/userSettingsFields.js",
270
+ preserveOnRemove: true,
271
+ reason: "Install app-owned user settings field definitions.",
272
+ category: "users-core",
273
+ id: "users-core-app-owned-user-settings-fields"
274
+ },
275
+ {
276
+ from: "templates/config/workspaceRoles.js",
277
+ to: "config/workspaceRoles.js",
278
+ preserveOnRemove: true,
279
+ reason: "Install app-owned workspace role catalog in a dedicated config file.",
280
+ category: "users-core",
281
+ id: "users-core-app-owned-workspace-roles-config"
282
+ }
283
+ ],
284
+ text: [
285
+ {
286
+ op: "upsert-env",
287
+ file: ".env",
288
+ key: "AUTH_PROFILE_MODE",
289
+ value: "users",
290
+ reason: "Enable users-backed auth profile sync when users-core is installed.",
291
+ category: "runtime-config",
292
+ id: "users-core-auth-profile-mode"
293
+ },
294
+ {
295
+ op: "append-text",
296
+ file: "packages/main/src/shared/index.js",
297
+ position: "top",
298
+ skipIfContains: "import \"./resources/workspaceSettingsFields.js\";",
299
+ value: "import \"./resources/workspaceSettingsFields.js\";\n",
300
+ reason: "Load app-owned workspace settings field definitions inside the main shared module.",
301
+ category: "users-core",
302
+ id: "users-core-main-shared-workspace-settings-field-import"
303
+ },
304
+ {
305
+ op: "append-text",
306
+ file: "packages/main/src/shared/index.js",
307
+ position: "top",
308
+ skipIfContains: "import \"./resources/consoleSettingsFields.js\";",
309
+ value: "import \"./resources/consoleSettingsFields.js\";\n",
310
+ reason: "Load app-owned console settings field definitions inside the main shared module.",
311
+ category: "users-core",
312
+ id: "users-core-main-shared-console-settings-field-import"
313
+ },
314
+ {
315
+ op: "append-text",
316
+ file: "packages/main/src/shared/index.js",
317
+ position: "top",
318
+ skipIfContains: "import \"./resources/userSettingsFields.js\";",
319
+ value: "import \"./resources/userSettingsFields.js\";\n",
320
+ reason: "Load app-owned user settings field definitions inside the main shared module.",
321
+ category: "users-core",
322
+ id: "users-core-main-shared-user-settings-field-import"
323
+ },
324
+ {
325
+ op: "append-text",
326
+ file: "src/main.js",
327
+ position: "top",
328
+ skipIfContains: "import \"@local/main/shared\";",
329
+ value: "import \"@local/main/shared\";\n",
330
+ reason: "Ensure client runtime loads app-owned shared settings field registration.",
331
+ category: "users-core",
332
+ id: "users-core-client-import-main-shared"
333
+ },
334
+ {
335
+ op: "append-text",
336
+ file: "server.js",
337
+ position: "top",
338
+ skipIfContains: "import \"@local/main/shared\";",
339
+ value: "import \"@local/main/shared\";\n",
340
+ reason: "Ensure server runtime loads app-owned shared settings field registration.",
341
+ category: "users-core",
342
+ id: "users-core-server-import-main-shared"
343
+ },
344
+ {
345
+ op: "append-text",
346
+ file: "config/public.js",
347
+ position: "top",
348
+ skipIfContains: "import { workspaceRoles } from \"./workspaceRoles.js\";",
349
+ value: "import { workspaceRoles } from \"./workspaceRoles.js\";\n",
350
+ reason: "Load app-owned workspace role catalog from dedicated config file.",
351
+ category: "users-core",
352
+ id: "users-core-workspace-roles-public-import"
353
+ },
354
+ {
355
+ op: "append-text",
356
+ file: "config/public.js",
357
+ position: "top",
358
+ skipIfContains: "import { surfaceAccessPolicies } from \"./surfaceAccessPolicies.js\";",
359
+ value: "import { surfaceAccessPolicies } from \"./surfaceAccessPolicies.js\";\n",
360
+ reason: "Load app-owned surface access policy catalog from dedicated config file.",
361
+ category: "users-core",
362
+ id: "users-core-surface-access-policies-public-import"
363
+ },
364
+ {
365
+ op: "append-text",
366
+ file: "config/surfaceAccessPolicies.js",
367
+ position: "top",
368
+ skipIfContains: "export const surfaceAccessPolicies = {};",
369
+ value: "export const surfaceAccessPolicies = {};\n\n",
370
+ reason: "Initialize app-owned surface access policy config if missing.",
371
+ category: "users-core",
372
+ id: "users-core-surface-access-policies-config-init"
373
+ },
374
+ {
375
+ op: "append-text",
376
+ file: "config/surfaceAccessPolicies.js",
377
+ position: "bottom",
378
+ skipIfContains: "surfaceAccessPolicies.workspace_member = {",
379
+ value: "\nsurfaceAccessPolicies.workspace_member = {\n requireAuth: true,\n requireWorkspaceMembership: true\n};\n",
380
+ reason: "Register workspace-member surface access policy for workspace surfaces.",
381
+ category: "users-core",
382
+ id: "users-core-surface-access-policies-workspace-member"
383
+ },
384
+ {
385
+ op: "append-text",
386
+ file: "config/public.js",
387
+ position: "bottom",
388
+ skipIfContains: "config.surfaceDefinitions.app = {",
389
+ value:
390
+ "\nconfig.surfaceDefinitions.app = {\n id: \"app\",\n label: \"App\",\n pagesRoot: \"w/[workspaceSlug]\",\n enabled: true,\n requiresAuth: true,\n requiresWorkspace: true,\n accessPolicyId: \"workspace_member\",\n origin: \"\"\n};\n\nconfig.surfaceDefinitions.admin = {\n id: \"admin\",\n label: \"Admin\",\n pagesRoot: \"w/[workspaceSlug]/admin\",\n enabled: true,\n requiresAuth: true,\n requiresWorkspace: true,\n accessPolicyId: \"workspace_member\",\n origin: \"\"\n};\n",
391
+ reason: "Append workspace surface topology when tenancy enables workspace routing.",
392
+ category: "users-core",
393
+ id: "users-core-surface-config-workspace",
394
+ when: {
395
+ config: "tenancyMode",
396
+ in: ["personal", "workspace"]
397
+ }
398
+ },
399
+ {
400
+ op: "append-text",
401
+ file: "config/public.js",
402
+ position: "bottom",
403
+ skipIfContains: "config.workspaceSwitching =",
404
+ value:
405
+ "\nconfig.workspaceSwitching = true;\nconfig.workspaceInvitations = {\n enabled: true,\n allowInPersonalMode: true\n};\nconfig.assistantEnabled = false;\nconfig.assistantRequiredPermission = \"\";\nconfig.socialEnabled = false;\nconfig.socialFederationEnabled = false;\n",
406
+ reason: "Append default public users/workspace feature toggles into app-owned config.",
407
+ category: "users-core",
408
+ id: "users-core-public-config"
409
+ },
410
+ {
411
+ op: "append-text",
412
+ file: "config/public.js",
413
+ position: "bottom",
414
+ skipIfContains: "config.workspaceRoles = workspaceRoles;",
415
+ value: "\nconfig.workspaceRoles = workspaceRoles;\n",
416
+ reason: "Bind app-owned workspace role catalog onto public config.",
417
+ category: "users-core",
418
+ id: "users-core-workspace-roles-public-config"
419
+ },
420
+ {
421
+ op: "append-text",
422
+ file: "config/public.js",
423
+ position: "bottom",
424
+ skipIfContains: "config.surfaceAccessPolicies = surfaceAccessPolicies;",
425
+ value: "\nconfig.surfaceAccessPolicies = surfaceAccessPolicies;\n",
426
+ reason: "Bind app-owned surface access policies onto public config.",
427
+ category: "users-core",
428
+ id: "users-core-surface-access-policies-public-config"
429
+ },
430
+ {
431
+ op: "append-text",
432
+ file: "config/server.js",
433
+ position: "bottom",
434
+ skipIfContains: "config.workspaceColor =",
435
+ value: "\nconfig.workspaceColor = \"indigo\";\n",
436
+ reason: "Append default server-only users/workspace settings into app-owned config.",
437
+ category: "users-core",
438
+ id: "users-core-server-config"
439
+ },
440
+ {
441
+ op: "append-text",
442
+ file: "config/server.js",
443
+ position: "bottom",
444
+ skipIfContains: "config.workspaceSettings =",
445
+ value:
446
+ "\nconfig.workspaceSettings = {\n defaults: {\n invitesEnabled: true\n }\n};\n",
447
+ reason: "Append app-owned workspace settings defaults into the server config.",
448
+ category: "users-core",
449
+ id: "users-core-workspace-settings-server-config"
450
+ },
451
+ {
452
+ op: "append-text",
453
+ file: "config/server.js",
454
+ position: "bottom",
455
+ skipIfContains: "config.workspaceMembers =",
456
+ value:
457
+ "\nconfig.workspaceMembers = {\n defaults: {\n inviteExpiresInMs: 604800000\n }\n};\n",
458
+ reason: "Append app-owned workspace member invite policy defaults into the server config.",
459
+ category: "users-core",
460
+ id: "users-core-workspace-members-server-config"
461
+ },
462
+ ]
463
+ }
464
+ });
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@jskit-ai/users-core",
3
+ "version": "0.1.4",
4
+ "type": "module",
5
+ "scripts": {
6
+ "test": "node --test"
7
+ },
8
+ "exports": {
9
+ "./server/support/workspaceActionSurfaces": "./src/server/support/workspaceActionSurfaces.js",
10
+ "./server/support/workspaceRouteInput": "./src/server/support/workspaceRouteInput.js",
11
+ "./server/support/resolveWorkspace": "./src/server/support/resolveWorkspace.js",
12
+ "./server/validators/routeParamsValidator": "./src/server/common/validators/routeParamsValidator.js",
13
+ "./shared/settings": "./src/shared/settings.js",
14
+ "./shared/events/usersEvents": "./src/shared/events/usersEvents.js",
15
+ "./shared/tenancyProfile": "./src/shared/tenancyProfile.js",
16
+ "./shared/support/usersVisibility": "./src/shared/support/usersVisibility.js",
17
+ "./shared/support/workspacePathModel": "./src/shared/support/workspacePathModel.js",
18
+ "./shared/support/usersApiPaths": "./src/shared/support/usersApiPaths.js",
19
+ "./shared/resources/workspaceSettingsResource": "./src/shared/resources/workspaceSettingsResource.js",
20
+ "./shared/resources/workspaceSettingsFields": "./src/shared/resources/workspaceSettingsFields.js",
21
+ "./shared/resources/userProfileResource": "./src/shared/resources/userProfileResource.js",
22
+ "./shared/resources/userSettingsFields": "./src/shared/resources/userSettingsFields.js",
23
+ "./shared/resources/userSettingsResource": "./src/shared/resources/userSettingsResource.js",
24
+ "./shared/resources/consoleSettingsFields": "./src/shared/resources/consoleSettingsFields.js"
25
+ },
26
+ "dependencies": {
27
+ "@jskit-ai/auth-core": "0.1.4",
28
+ "@jskit-ai/database-runtime": "0.1.4",
29
+ "@jskit-ai/http-runtime": "0.1.4",
30
+ "@jskit-ai/kernel": "0.1.4",
31
+ "@fastify/multipart": "^9.4.0",
32
+ "@fastify/type-provider-typebox": "^6.1.0",
33
+ "typebox": "^1.0.81"
34
+ }
35
+ }
@@ -0,0 +1,74 @@
1
+ import { USERS_SHARED_API } from "../shared/index.js";
2
+ import { bootWorkspaceDirectoryRoutes } from "./workspaceDirectory/bootWorkspaceDirectoryRoutes.js";
3
+ import { registerWorkspaceDirectory } from "./workspaceDirectory/registerWorkspaceDirectory.js";
4
+ import {
5
+ registerWorkspacePendingInvitations
6
+ } from "./workspacePendingInvitations/registerWorkspacePendingInvitations.js";
7
+ import { bootWorkspacePendingInvitations } from "./workspacePendingInvitations/bootWorkspacePendingInvitations.js";
8
+ import { registerWorkspaceMembers } from "./workspaceMembers/registerWorkspaceMembers.js";
9
+ import { bootWorkspaceMembers } from "./workspaceMembers/bootWorkspaceMembers.js";
10
+ import { registerWorkspaceSettings } from "./workspaceSettings/registerWorkspaceSettings.js";
11
+ import { bootWorkspaceSettings } from "./workspaceSettings/bootWorkspaceSettings.js";
12
+ import { bootAccountProfileRoutes } from "./accountProfile/bootAccountProfileRoutes.js";
13
+ import { bootAccountPreferencesRoutes } from "./accountPreferences/bootAccountPreferencesRoutes.js";
14
+ import { bootAccountNotificationsRoutes } from "./accountNotifications/bootAccountNotificationsRoutes.js";
15
+ import { bootAccountSecurityRoutes } from "./accountSecurity/bootAccountSecurityRoutes.js";
16
+ import { bootConsoleSettingsRoutes } from "./consoleSettings/bootConsoleSettingsRoutes.js";
17
+ import {
18
+ USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN,
19
+ USERS_WORKSPACE_ENABLED_TOKEN
20
+ } from "./common/diTokens.js";
21
+ import { registerSharedApi } from "./common/registerSharedApi.js";
22
+ import { registerCommonRepositories } from "./common/registerCommonRepositories.js";
23
+ import { registerWorkspaceCore } from "./registerWorkspaceCore.js";
24
+ import { registerWorkspaceBootstrap } from "./registerWorkspaceBootstrap.js";
25
+ import { registerAccountPreferences } from "./accountPreferences/registerAccountPreferences.js";
26
+ import { registerAccountNotifications } from "./accountNotifications/registerAccountNotifications.js";
27
+ import { registerAccountProfile } from "./accountProfile/registerAccountProfile.js";
28
+ import { registerAccountSecurity } from "./accountSecurity/registerAccountSecurity.js";
29
+ import { registerConsoleSettings } from "./consoleSettings/registerConsoleSettings.js";
30
+ import { registerAvatarMultipartSupport } from "./accountProfile/registerAvatarMultipartSupport.js";
31
+ import { registerUsersCoreActionSurfaceSources } from "./support/workspaceActionSurfaces.js";
32
+
33
+ class UsersCoreServiceProvider {
34
+ static id = "users.core";
35
+
36
+ static dependsOn = ["runtime.server", "runtime.actions", "runtime.database", "runtime.storage", "auth.provider"];
37
+
38
+ register(app) {
39
+ registerUsersCoreActionSurfaceSources(app);
40
+ registerSharedApi(app, USERS_SHARED_API);
41
+ registerCommonRepositories(app);
42
+ registerWorkspaceCore(app);
43
+ registerWorkspaceBootstrap(app);
44
+ registerWorkspaceDirectory(app);
45
+ registerWorkspaceMembers(app);
46
+ registerWorkspaceSettings(app);
47
+ registerWorkspacePendingInvitations(app);
48
+
49
+ registerAccountProfile(app);
50
+ registerAccountPreferences(app);
51
+ registerAccountNotifications(app);
52
+ registerAccountSecurity(app);
53
+ registerConsoleSettings(app);
54
+ }
55
+
56
+ async boot(app) {
57
+ if (app.make(USERS_WORKSPACE_ENABLED_TOKEN) === true) {
58
+ bootWorkspaceDirectoryRoutes(app);
59
+ if (app.make(USERS_WORKSPACE_INVITATIONS_ENABLED_TOKEN) === true) {
60
+ bootWorkspacePendingInvitations(app);
61
+ }
62
+ bootWorkspaceSettings(app);
63
+ bootWorkspaceMembers(app);
64
+ }
65
+ await registerAvatarMultipartSupport(app);
66
+ bootAccountProfileRoutes(app);
67
+ bootAccountPreferencesRoutes(app);
68
+ bootAccountNotificationsRoutes(app);
69
+ bootAccountSecurityRoutes(app);
70
+ bootConsoleSettingsRoutes(app);
71
+ }
72
+ }
73
+
74
+ export { UsersCoreServiceProvider };
@@ -0,0 +1,39 @@
1
+ import {
2
+ resolveRequest
3
+ } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
4
+ import { userSettingsResource } from "../../shared/resources/userSettingsResource.js";
5
+ import { resolveActionUser } from "../common/support/resolveActionUser.js";
6
+
7
+ const accountNotificationsActions = Object.freeze([
8
+ {
9
+ id: "settings.notifications.update",
10
+ version: 1,
11
+ kind: "command",
12
+ channels: ["api", "automation", "internal"],
13
+ surfacesFrom: "enabled",
14
+ permission: {
15
+ require: "authenticated"
16
+ },
17
+ inputValidator: {
18
+ payload: userSettingsResource.operations.notificationsUpdate.bodyValidator
19
+ },
20
+ outputValidator: userSettingsResource.operations.view.outputValidator,
21
+ idempotency: "optional",
22
+ audit: {
23
+ actionName: "settings.notifications.update"
24
+ },
25
+ observability: {},
26
+ async execute(input, context, deps) {
27
+ return deps.accountNotificationsService.updateNotifications(
28
+ resolveRequest(context),
29
+ resolveActionUser(context, input),
30
+ input.payload,
31
+ {
32
+ context
33
+ }
34
+ );
35
+ }
36
+ }
37
+ ]);
38
+
39
+ export { accountNotificationsActions };
@@ -0,0 +1,41 @@
1
+ import { AppError } from "@jskit-ai/kernel/server/runtime/errors";
2
+ import {
3
+ resolveUserProfile,
4
+ resolveSecurityStatus
5
+ } from "../common/services/accountContextService.js";
6
+ import {
7
+ accountSettingsResponseFormatter
8
+ } from "../common/formatters/accountSettingsResponseFormatter.js";
9
+
10
+ function createService({
11
+ userSettingsRepository,
12
+ userProfilesRepository,
13
+ authService
14
+ } = {}) {
15
+ if (!userSettingsRepository || !userProfilesRepository) {
16
+ throw new Error("accountNotificationsService requires repositories.");
17
+ }
18
+
19
+ async function updateNotifications(request, user, payload = {}, options = {}) {
20
+ const profile = await resolveUserProfile(userProfilesRepository, user);
21
+ if (!profile) {
22
+ throw new AppError(404, "User profile was not found.");
23
+ }
24
+
25
+ const settings = await userSettingsRepository.updateNotifications(profile.id, payload);
26
+ const securityStatus = await resolveSecurityStatus(authService, request);
27
+
28
+ return accountSettingsResponseFormatter({
29
+ profile,
30
+ settings,
31
+ securityStatus,
32
+ authService
33
+ });
34
+ }
35
+
36
+ return Object.freeze({
37
+ updateNotifications
38
+ });
39
+ }
40
+
41
+ export { createService };