@jskit-ai/users-core 0.1.47 → 0.1.49

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 (104) hide show
  1. package/package.descriptor.mjs +9 -46
  2. package/package.json +8 -19
  3. package/src/server/UsersCoreServiceProvider.js +0 -4
  4. package/src/server/common/registerCommonRepositories.js +0 -5
  5. package/src/server/common/services/authProfileSyncService.js +28 -7
  6. package/src/server/common/support/realtimeServiceEvents.js +1 -59
  7. package/src/server/profileSyncLifecycleContributorRegistry.js +56 -0
  8. package/src/server/registerUsersBootstrap.js +1 -3
  9. package/src/server/registerUsersCore.js +2 -14
  10. package/src/server/usersBootstrapContributor.js +10 -85
  11. package/src/shared/index.js +2 -99
  12. package/src/shared/settings.js +1 -119
  13. package/templates/migrations/users_core_generic_initial.cjs +0 -16
  14. package/test/authProfileSyncService.test.js +19 -10
  15. package/test/registerServiceRealtimeEvents.test.js +0 -94
  16. package/test/registerUsersCore.test.js +6 -19
  17. package/test/repositoryContracts.test.js +1 -11
  18. package/test/resourcesCanonical.test.js +1 -19
  19. package/test/settingsFieldRegistriesSingleton.test.js +0 -10
  20. package/test/usersBootstrapContributor.test.js +20 -38
  21. package/test/usersRouteRequestInputValidator.test.js +2 -43
  22. package/test/usersRouteResources.test.js +2 -20
  23. package/test-support/registerDefaultSettingsFields.js +0 -1
  24. package/src/server/UsersWorkspacesServiceProvider.js +0 -44
  25. package/src/server/common/contributors/workspaceActionContextContributor.js +0 -88
  26. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +0 -34
  27. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +0 -78
  28. package/src/server/common/formatters/workspaceFormatter.js +0 -53
  29. package/src/server/common/repositories/workspaceInvitesRepository.js +0 -208
  30. package/src/server/common/repositories/workspaceMembershipsRepository.js +0 -190
  31. package/src/server/common/repositories/workspacesRepository.js +0 -202
  32. package/src/server/common/services/workspaceContextService.js +0 -281
  33. package/src/server/common/support/workspaceRoutePaths.js +0 -17
  34. package/src/server/common/validators/routeParamsValidator.js +0 -62
  35. package/src/server/consoleSettings/bootConsoleSettingsRoutes.js +0 -63
  36. package/src/server/consoleSettings/consoleService.js +0 -36
  37. package/src/server/consoleSettings/consoleSettingsActions.js +0 -55
  38. package/src/server/consoleSettings/consoleSettingsRepository.js +0 -115
  39. package/src/server/consoleSettings/consoleSettingsService.js +0 -40
  40. package/src/server/consoleSettings/registerConsoleSettings.js +0 -56
  41. package/src/server/registerWorkspaceBootstrap.js +0 -27
  42. package/src/server/registerWorkspaceCore.js +0 -73
  43. package/src/server/registerWorkspaceRepositories.js +0 -26
  44. package/src/server/support/resolveWorkspace.js +0 -16
  45. package/src/server/support/workspaceActionSurfaces.js +0 -135
  46. package/src/server/support/workspaceInvitationsPolicy.js +0 -45
  47. package/src/server/support/workspaceRouteInput.js +0 -22
  48. package/src/server/workspaceBootstrapContributor.js +0 -211
  49. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +0 -133
  50. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +0 -19
  51. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +0 -133
  52. package/src/server/workspaceMembers/bootWorkspaceMembers.js +0 -236
  53. package/src/server/workspaceMembers/registerWorkspaceMembers.js +0 -108
  54. package/src/server/workspaceMembers/workspaceMembersActions.js +0 -186
  55. package/src/server/workspaceMembers/workspaceMembersService.js +0 -222
  56. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +0 -62
  57. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +0 -119
  58. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +0 -74
  59. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +0 -138
  60. package/src/server/workspaceSettings/bootWorkspaceSettings.js +0 -76
  61. package/src/server/workspaceSettings/registerWorkspaceSettings.js +0 -62
  62. package/src/server/workspaceSettings/workspaceSettingsActions.js +0 -72
  63. package/src/server/workspaceSettings/workspaceSettingsRepository.js +0 -154
  64. package/src/server/workspaceSettings/workspaceSettingsService.js +0 -66
  65. package/src/shared/resources/consoleSettingsFields.js +0 -54
  66. package/src/shared/resources/consoleSettingsResource.js +0 -119
  67. package/src/shared/resources/workspaceMembersResource.js +0 -354
  68. package/src/shared/resources/workspacePendingInvitationsResource.js +0 -82
  69. package/src/shared/resources/workspaceResource.js +0 -176
  70. package/src/shared/resources/workspaceSettingsFields.js +0 -59
  71. package/src/shared/resources/workspaceSettingsResource.js +0 -169
  72. package/src/shared/roles.js +0 -161
  73. package/src/shared/support/usersApiPaths.js +0 -43
  74. package/src/shared/support/usersVisibility.js +0 -42
  75. package/src/shared/support/workspacePathModel.js +0 -145
  76. package/src/shared/tenancyMode.js +0 -35
  77. package/src/shared/tenancyProfile.js +0 -73
  78. package/templates/migrations/users_core_console_owner.cjs +0 -37
  79. package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +0 -11
  80. package/test/consoleService.test.js +0 -57
  81. package/test/consoleSettingsService.test.js +0 -86
  82. package/test/registerWorkspaceDirectory.test.js +0 -31
  83. package/test/registerWorkspaceSettings.test.js +0 -40
  84. package/test/roles.test.js +0 -159
  85. package/test/tenancyProfile.test.js +0 -67
  86. package/test/usersApiPaths.test.js +0 -49
  87. package/test/usersRouteValidators.test.js +0 -49
  88. package/test/usersVisibility.test.js +0 -27
  89. package/test/workspaceActionContextContributor.test.js +0 -344
  90. package/test/workspaceActionSurfaces.test.js +0 -105
  91. package/test/workspaceAuthPolicyContextResolver.test.js +0 -119
  92. package/test/workspaceBootstrapContributor.test.js +0 -154
  93. package/test/workspaceInvitationsPolicy.test.js +0 -71
  94. package/test/workspaceInvitesRepository.test.js +0 -111
  95. package/test/workspaceMembersService.test.js +0 -398
  96. package/test/workspacePathModel.test.js +0 -93
  97. package/test/workspacePendingInvitationsResource.test.js +0 -38
  98. package/test/workspacePendingInvitationsService.test.js +0 -151
  99. package/test/workspaceRouteVisibilityResolver.test.js +0 -83
  100. package/test/workspaceService.test.js +0 -546
  101. package/test/workspaceSettingsActions.test.js +0 -52
  102. package/test/workspaceSettingsRepository.test.js +0 -202
  103. package/test/workspaceSettingsResource.test.js +0 -169
  104. package/test/workspaceSettingsService.test.js +0 -140
@@ -1,67 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import {
4
- TENANCY_MODE_NONE,
5
- TENANCY_MODE_PERSONAL,
6
- TENANCY_MODE_WORKSPACES,
7
- WORKSPACE_SLUG_POLICY_NONE,
8
- WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME,
9
- WORKSPACE_SLUG_POLICY_USER_SELECTED,
10
- resolveTenancyProfile,
11
- isWorkspacesTenancyMode
12
- } from "../src/shared/tenancyProfile.js";
13
-
14
- test("resolveTenancyProfile returns mode-specific workspace policy matrix", () => {
15
- const noneProfile = resolveTenancyProfile({ tenancyMode: TENANCY_MODE_NONE });
16
- assert.deepEqual(noneProfile, {
17
- mode: TENANCY_MODE_NONE,
18
- workspace: {
19
- enabled: false,
20
- autoProvision: false,
21
- allowSelfCreate: false,
22
- slugPolicy: WORKSPACE_SLUG_POLICY_NONE
23
- }
24
- });
25
-
26
- const personalProfile = resolveTenancyProfile({ tenancyMode: TENANCY_MODE_PERSONAL });
27
- assert.deepEqual(personalProfile, {
28
- mode: TENANCY_MODE_PERSONAL,
29
- workspace: {
30
- enabled: true,
31
- autoProvision: true,
32
- allowSelfCreate: false,
33
- slugPolicy: WORKSPACE_SLUG_POLICY_IMMUTABLE_USERNAME
34
- }
35
- });
36
-
37
- const workspaceProfile = resolveTenancyProfile({ tenancyMode: TENANCY_MODE_WORKSPACES });
38
- assert.deepEqual(workspaceProfile, {
39
- mode: TENANCY_MODE_WORKSPACES,
40
- workspace: {
41
- enabled: true,
42
- autoProvision: false,
43
- allowSelfCreate: false,
44
- slugPolicy: WORKSPACE_SLUG_POLICY_USER_SELECTED
45
- }
46
- });
47
- });
48
-
49
- test("isWorkspacesTenancyMode is true only for workspace mode", () => {
50
- assert.equal(isWorkspacesTenancyMode(TENANCY_MODE_WORKSPACES), true);
51
- assert.equal(isWorkspacesTenancyMode(TENANCY_MODE_PERSONAL), false);
52
- assert.equal(isWorkspacesTenancyMode(TENANCY_MODE_NONE), false);
53
- });
54
-
55
- test("resolveTenancyProfile allows explicit workspace self-create policy override", () => {
56
- const workspaceProfile = resolveTenancyProfile({
57
- tenancyMode: TENANCY_MODE_WORKSPACES,
58
- tenancyPolicy: {
59
- workspace: {
60
- allowSelfCreate: true
61
- }
62
- }
63
- });
64
-
65
- assert.equal(workspaceProfile.mode, TENANCY_MODE_WORKSPACES);
66
- assert.equal(workspaceProfile.workspace.allowSelfCreate, true);
67
- });
@@ -1,49 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import {
4
- normalizeSurfaceWorkspaceRequirement,
5
- resolveApiBasePath
6
- } from "../src/shared/support/usersApiPaths.js";
7
-
8
- test("normalizeSurfaceWorkspaceRequirement only accepts explicit true", () => {
9
- assert.equal(normalizeSurfaceWorkspaceRequirement(true), true);
10
- assert.equal(normalizeSurfaceWorkspaceRequirement(false), false);
11
- assert.equal(normalizeSurfaceWorkspaceRequirement("true"), false);
12
- assert.equal(normalizeSurfaceWorkspaceRequirement(1), false);
13
- });
14
-
15
- test("resolveApiBasePath resolves workspace and non-workspace API base paths", () => {
16
- assert.equal(
17
- resolveApiBasePath({
18
- surfaceRequiresWorkspace: true,
19
- relativePath: "/customers"
20
- }),
21
- "/api/w/:workspaceSlug/customers"
22
- );
23
-
24
- assert.equal(
25
- resolveApiBasePath({
26
- surfaceRequiresWorkspace: false,
27
- relativePath: "/customers"
28
- }),
29
- "/api/customers"
30
- );
31
- });
32
-
33
- test("resolveApiBasePath preserves query strings and hash fragments", () => {
34
- assert.equal(
35
- resolveApiBasePath({
36
- surfaceRequiresWorkspace: true,
37
- relativePath: "/customers?search=buddy#top"
38
- }),
39
- "/api/w/:workspaceSlug/customers?search=buddy#top"
40
- );
41
-
42
- assert.equal(
43
- resolveApiBasePath({
44
- surfaceRequiresWorkspace: false,
45
- relativePath: "/?cursor=2"
46
- }),
47
- "/api?cursor=2"
48
- );
49
- });
@@ -1,49 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import { Type } from "@fastify/type-provider-typebox";
4
- import { compileRouteValidator } from "@jskit-ai/kernel/_testable";
5
- import { routeParamsValidator } from "../src/server/common/validators/routeParamsValidator.js";
6
-
7
- test("routeParamsValidator exposes a shared route params validator", () => {
8
- assert.equal(typeof routeParamsValidator.schema, "object");
9
- assert.equal(typeof routeParamsValidator.normalize, "function");
10
- });
11
-
12
- test("route validator pipeline uses the shared params validator and merges query arrays automatically", () => {
13
- const paginationQueryValidator = Object.freeze({
14
- schema: Type.Object(
15
- {
16
- cursor: Type.Optional(Type.String({ minLength: 1 })),
17
- limit: Type.Optional(Type.String({ pattern: "^[0-9]+$" }))
18
- },
19
- { additionalProperties: false }
20
- )
21
- });
22
- const searchQueryValidator = Object.freeze({
23
- schema: Type.Object(
24
- {
25
- search: Type.Optional(Type.String({ minLength: 1 }))
26
- },
27
- { additionalProperties: false }
28
- )
29
- });
30
-
31
- const compiled = compileRouteValidator({
32
- paramsValidator: routeParamsValidator,
33
- queryValidator: [paginationQueryValidator, searchQueryValidator]
34
- });
35
-
36
- assert.equal(compiled.schema.params.type, "object");
37
- assert.equal(compiled.schema.params.additionalProperties, false);
38
- assert.equal(typeof compiled.schema.params.properties.workspaceSlug, "object");
39
- assert.equal(typeof compiled.schema.params.properties.memberUserId, "object");
40
- assert.equal(typeof compiled.schema.params.properties.inviteId, "object");
41
- assert.equal(typeof compiled.schema.params.properties.provider, "object");
42
- assert.equal(compiled.input.params({ workspaceSlug: " ACME " }).workspaceSlug, "acme");
43
-
44
- assert.equal(compiled.schema.querystring.type, "object");
45
- assert.equal(compiled.schema.querystring.additionalProperties, false);
46
- assert.equal(typeof compiled.schema.querystring.properties.cursor, "object");
47
- assert.equal(typeof compiled.schema.querystring.properties.limit, "object");
48
- assert.equal(typeof compiled.schema.querystring.properties.search, "object");
49
- });
@@ -1,27 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import {
4
- isWorkspaceVisibility,
5
- checkRouteVisibility
6
- } from "../src/shared/support/usersVisibility.js";
7
-
8
- test("checkRouteVisibility normalizes valid users visibility levels and throws on invalid input", () => {
9
- assert.equal(checkRouteVisibility("WORKSPACE"), "workspace");
10
- assert.equal(checkRouteVisibility("workspace_user"), "workspace_user");
11
- assert.equal(checkRouteVisibility("user"), "user");
12
- assert.throws(
13
- () => checkRouteVisibility(""),
14
- /must be one of/
15
- );
16
- assert.throws(
17
- () => checkRouteVisibility("unknown"),
18
- /must be one of/
19
- );
20
- });
21
-
22
- test("isWorkspaceVisibility recognizes workspace-only visibility levels", () => {
23
- assert.equal(isWorkspaceVisibility("workspace"), true);
24
- assert.equal(isWorkspaceVisibility("workspace_user"), true);
25
- assert.equal(isWorkspaceVisibility("public"), false);
26
- assert.equal(isWorkspaceVisibility("user"), false);
27
- });
@@ -1,344 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { createWorkspaceActionContextContributor } from "../src/server/common/contributors/workspaceActionContextContributor.js";
4
-
5
- test("workspace action context contributor resolves workspace context for workspace actions", async () => {
6
- const calls = [];
7
- const contributor = createWorkspaceActionContextContributor({
8
- workspaceService: {
9
- async resolveWorkspaceContextForUserBySlug(user, workspaceSlug, options) {
10
- calls.push({
11
- user,
12
- workspaceSlug,
13
- options
14
- });
15
-
16
- return {
17
- workspace: {
18
- id: 10,
19
- slug: "acme"
20
- },
21
- membership: {
22
- roleSid: "owner"
23
- },
24
- permissions: ["workspace.settings.update"]
25
- };
26
- }
27
- },
28
- workspaceSurfaceIds: ["admin", "app"]
29
- });
30
-
31
- const request = {
32
- user: {
33
- id: 42,
34
- email: "user@example.com"
35
- }
36
- };
37
-
38
- const contribution = await contributor.contribute({
39
- definition: {
40
- id: "workspace.settings.update",
41
- surfaces: ["admin", "app"]
42
- },
43
- input: {
44
- workspaceSlug: "Acme"
45
- },
46
- context: {
47
- requestMeta: {
48
- request
49
- }
50
- },
51
- request
52
- });
53
-
54
- assert.deepEqual(calls, [
55
- {
56
- user: request.user,
57
- workspaceSlug: "Acme",
58
- options: {
59
- request
60
- }
61
- }
62
- ]);
63
- assert.deepEqual(contribution, {
64
- requestMeta: {
65
- resolvedWorkspaceContext: {
66
- workspace: {
67
- id: 10,
68
- slug: "acme"
69
- },
70
- membership: {
71
- roleSid: "owner"
72
- },
73
- permissions: ["workspace.settings.update"]
74
- }
75
- },
76
- workspace: {
77
- id: 10,
78
- slug: "acme"
79
- },
80
- membership: {
81
- roleSid: "owner"
82
- },
83
- permissions: ["workspace.settings.update"]
84
- });
85
- });
86
-
87
- test("workspace action context contributor ignores actions that do not require workspace context", async () => {
88
- const contributor = createWorkspaceActionContextContributor({
89
- workspaceService: {
90
- async resolveWorkspaceContextForUserBySlug() {
91
- throw new Error("should not be called");
92
- }
93
- }
94
- });
95
-
96
- const contribution = await contributor.contribute({
97
- actionId: "workspace.workspaces.list",
98
- input: {
99
- workspaceSlug: "acme"
100
- },
101
- context: {}
102
- });
103
-
104
- assert.deepEqual(contribution, {});
105
- });
106
-
107
- test("workspace action context contributor always resolves and stores resolved context", async () => {
108
- const calls = [];
109
- const contributor = createWorkspaceActionContextContributor({
110
- workspaceService: {
111
- async resolveWorkspaceContextForUserBySlug(user, workspaceSlug, options) {
112
- calls.push({ user, workspaceSlug, options });
113
- return {
114
- workspace: {
115
- id: 10,
116
- slug: "acme",
117
- ownerUserId: 77
118
- },
119
- membership: {
120
- roleSid: "owner"
121
- },
122
- permissions: ["workspace.settings.update"]
123
- };
124
- }
125
- },
126
- workspaceSurfaceIds: ["admin", "app"]
127
- });
128
-
129
- const request = {
130
- user: {
131
- id: 42
132
- }
133
- };
134
-
135
- const contribution = await contributor.contribute({
136
- definition: {
137
- id: "workspace.members.list",
138
- surfaces: ["admin", "app"]
139
- },
140
- input: {
141
- workspaceSlug: "acme"
142
- },
143
- context: {
144
- workspace: {
145
- id: 1
146
- },
147
- requestMeta: {
148
- request
149
- }
150
- },
151
- request
152
- });
153
-
154
- assert.deepEqual(calls, [
155
- {
156
- user: request.user,
157
- workspaceSlug: "acme",
158
- options: {
159
- request
160
- }
161
- }
162
- ]);
163
- assert.deepEqual(contribution, {
164
- requestMeta: {
165
- resolvedWorkspaceContext: {
166
- workspace: {
167
- id: 10,
168
- slug: "acme",
169
- ownerUserId: 77
170
- },
171
- membership: {
172
- roleSid: "owner"
173
- },
174
- permissions: ["workspace.settings.update"]
175
- }
176
- },
177
- membership: {
178
- roleSid: "owner"
179
- },
180
- permissions: ["workspace.settings.update"]
181
- });
182
- });
183
-
184
- test("workspace action context contributor resolves context for workspace-visible routes outside legacy action list", async () => {
185
- const calls = [];
186
- const contributor = createWorkspaceActionContextContributor({
187
- workspaceService: {
188
- async resolveWorkspaceContextForUserBySlug(user, workspaceSlug, options) {
189
- calls.push({ user, workspaceSlug, options });
190
- return {
191
- workspace: {
192
- id: 33,
193
- slug: "acme"
194
- },
195
- membership: {
196
- roleSid: "admin"
197
- },
198
- permissions: ["assistant.chat.use"]
199
- };
200
- }
201
- }
202
- });
203
-
204
- const request = {
205
- user: {
206
- id: 42
207
- },
208
- routeOptions: {
209
- config: {
210
- visibility: "workspace"
211
- }
212
- }
213
- };
214
-
215
- const contribution = await contributor.contribute({
216
- definition: {
217
- id: "assistant.conversations.list",
218
- surfaces: ["admin"]
219
- },
220
- input: {
221
- workspaceSlug: "acme"
222
- },
223
- context: {
224
- requestMeta: {
225
- request
226
- }
227
- },
228
- request
229
- });
230
-
231
- assert.deepEqual(calls, [
232
- {
233
- user: request.user,
234
- workspaceSlug: "acme",
235
- options: {
236
- request
237
- }
238
- }
239
- ]);
240
- assert.deepEqual(contribution, {
241
- requestMeta: {
242
- resolvedWorkspaceContext: {
243
- workspace: {
244
- id: 33,
245
- slug: "acme"
246
- },
247
- membership: {
248
- roleSid: "admin"
249
- },
250
- permissions: ["assistant.chat.use"]
251
- }
252
- },
253
- workspace: {
254
- id: 33,
255
- slug: "acme"
256
- },
257
- membership: {
258
- roleSid: "admin"
259
- },
260
- permissions: ["assistant.chat.use"]
261
- });
262
- });
263
-
264
- test("workspace action context contributor resolves context for workspace surfaces even when route visibility is public", async () => {
265
- const calls = [];
266
- const contributor = createWorkspaceActionContextContributor({
267
- workspaceService: {
268
- async resolveWorkspaceContextForUserBySlug(user, workspaceSlug, options) {
269
- calls.push({ user, workspaceSlug, options });
270
- return {
271
- workspace: {
272
- id: 77,
273
- slug: "acme"
274
- },
275
- membership: {
276
- roleSid: "member"
277
- },
278
- permissions: ["crud.breeds.list"]
279
- };
280
- }
281
- },
282
- workspaceSurfaceIds: ["admin", "app"]
283
- });
284
-
285
- const request = {
286
- user: {
287
- id: 42
288
- },
289
- routeOptions: {
290
- config: {
291
- surface: "admin",
292
- visibility: "public"
293
- }
294
- }
295
- };
296
-
297
- const contribution = await contributor.contribute({
298
- definition: {
299
- id: "crud.breeds.list",
300
- surfaces: ["admin"]
301
- },
302
- input: {
303
- workspaceSlug: "acme"
304
- },
305
- context: {
306
- requestMeta: {
307
- request
308
- }
309
- },
310
- request
311
- });
312
-
313
- assert.deepEqual(calls, [
314
- {
315
- user: request.user,
316
- workspaceSlug: "acme",
317
- options: {
318
- request
319
- }
320
- }
321
- ]);
322
- assert.deepEqual(contribution, {
323
- requestMeta: {
324
- resolvedWorkspaceContext: {
325
- workspace: {
326
- id: 77,
327
- slug: "acme"
328
- },
329
- membership: {
330
- roleSid: "member"
331
- },
332
- permissions: ["crud.breeds.list"]
333
- }
334
- },
335
- workspace: {
336
- id: 77,
337
- slug: "acme"
338
- },
339
- membership: {
340
- roleSid: "member"
341
- },
342
- permissions: ["crud.breeds.list"]
343
- });
344
- });
@@ -1,105 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import {
4
- materializeWorkspaceActionSurfacesFromAppConfig,
5
- resolveConsoleSurfaceIdsFromAppConfig,
6
- resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig
7
- } from "../src/server/support/workspaceActionSurfaces.js";
8
-
9
- test("materializeWorkspaceActionSurfacesFromAppConfig resolves workspace surfaces from appConfig", () => {
10
- const actionDefinitions = [
11
- {
12
- id: "workspace.settings.read",
13
- surfacesFrom: "workspace"
14
- },
15
- {
16
- id: "auth.session.read",
17
- surfacesFrom: "enabled"
18
- }
19
- ];
20
-
21
- const materialized = materializeWorkspaceActionSurfacesFromAppConfig(actionDefinitions, {
22
- appConfig: {
23
- surfaceDefinitions: {
24
- app: { id: "app", enabled: true, requiresWorkspace: true },
25
- admin: { id: "admin", enabled: true, requiresWorkspace: true },
26
- console: { id: "console", enabled: true, requiresWorkspace: false }
27
- }
28
- }
29
- });
30
-
31
- assert.deepEqual(materialized, [
32
- {
33
- id: "workspace.settings.read",
34
- surfaces: ["app", "admin"]
35
- },
36
- {
37
- id: "auth.session.read",
38
- surfacesFrom: "enabled"
39
- }
40
- ]);
41
- });
42
-
43
- test("materializeWorkspaceActionSurfacesFromAppConfig drops workspace actions when no workspace surfaces are enabled", () => {
44
- const actionDefinitions = [
45
- {
46
- id: "workspace.settings.read",
47
- surfacesFrom: "workspace"
48
- }
49
- ];
50
-
51
- const materialized = materializeWorkspaceActionSurfacesFromAppConfig(actionDefinitions, {
52
- appConfig: {
53
- surfaceDefinitions: {
54
- app: { id: "app", enabled: true, requiresWorkspace: false },
55
- console: { id: "console", enabled: true, requiresWorkspace: false }
56
- }
57
- }
58
- });
59
-
60
- assert.deepEqual(materialized, []);
61
- });
62
-
63
- test("resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig picks a workspace surface when app default is non-workspace", () => {
64
- const surfaceId = resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig({
65
- surfaceDefaultId: "home",
66
- surfaceDefinitions: {
67
- home: { id: "home", enabled: true, requiresWorkspace: false },
68
- app: { id: "app", enabled: true, requiresWorkspace: true },
69
- admin: { id: "admin", enabled: true, requiresWorkspace: true }
70
- }
71
- });
72
-
73
- assert.equal(surfaceId, "app");
74
- });
75
-
76
- test("resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig falls back to app default when no workspace surfaces exist", () => {
77
- const surfaceId = resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig({
78
- surfaceDefaultId: "home",
79
- surfaceDefinitions: {
80
- home: { id: "home", enabled: true, requiresWorkspace: false },
81
- console: { id: "console", enabled: true, requiresWorkspace: false }
82
- }
83
- });
84
-
85
- assert.equal(surfaceId, "home");
86
- });
87
-
88
- test("resolveConsoleSurfaceIdsFromAppConfig resolves all enabled console-owner surfaces", () => {
89
- const surfaceIds = resolveConsoleSurfaceIdsFromAppConfig({
90
- surfaceDefinitions: {
91
- home: { id: "home", enabled: true, requiresWorkspace: false, accessPolicyId: "public" },
92
- console: { id: "console", enabled: true, requiresWorkspace: false, accessPolicyId: "console_owner" },
93
- opsConsole: { id: "opsConsole", enabled: true, requiresWorkspace: false, accessPolicyId: "console_owner" },
94
- app: { id: "app", enabled: true, requiresWorkspace: true, accessPolicyId: "workspace_member" },
95
- disabledConsole: {
96
- id: "disabledConsole",
97
- enabled: false,
98
- requiresWorkspace: false,
99
- accessPolicyId: "console_owner"
100
- }
101
- }
102
- });
103
-
104
- assert.deepEqual(surfaceIds, ["console", "opsconsole"]);
105
- });