@jskit-ai/workspaces-web 0.1.138 → 0.1.139-oldline.2

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 (24) hide show
  1. package/package.descriptor.mjs +492 -0
  2. package/package.json +9 -564
  3. package/src/client/account-settings/accountSettingsInvitesRuntime.js +2 -2
  4. package/src/client/account-settings/useAccountSettingsInvitesSectionRuntime.js +3 -3
  5. package/src/client/components/MembersAdminClientElement.vue +1 -1
  6. package/src/client/components/{WorkspaceProfileSurfaceSwitchMenuItem.vue → UsersProfileSurfaceSwitchMenuItem.vue} +1 -1
  7. package/src/client/components/{WorkspaceMembersMenuItem.vue → UsersWorkspaceMembersMenuItem.vue} +2 -2
  8. package/src/client/components/{WorkspacePermissionMenuItem.vue → UsersWorkspacePermissionMenuItem.vue} +3 -3
  9. package/src/client/components/{WorkspaceSelector.vue → UsersWorkspaceSelector.vue} +1 -1
  10. package/src/client/components/{WorkspaceSettingsMenuItem.vue → UsersWorkspaceSettingsMenuItem.vue} +2 -2
  11. package/src/client/components/WorkspaceInviteLanding.vue +4 -4
  12. package/src/client/components/WorkspaceMembersClientElement.vue +6 -6
  13. package/src/client/components/WorkspacesClientElement.vue +13 -13
  14. package/src/client/composables/useWorkspaceRouteContext.js +1 -1
  15. package/src/client/lib/httpClient.js +10 -0
  16. package/src/client/lib/permissions.js +27 -0
  17. package/src/client/lib/surfaceAccessPolicy.js +1 -4
  18. package/src/client/providers/WorkspacesWebClientProvider.js +11 -11
  19. package/src/client/runtime/bootstrapPlacementRuntime.js +1 -1
  20. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +2 -2
  21. package/test/{packageMetadataOwnership.test.js → packageDescriptorOwnership.test.js} +2 -4
  22. package/test/settingsPlacementContract.test.js +20 -22
  23. package/test/{workspaceSelectorContract.test.js → usersWorkspaceSelectorContract.test.js} +3 -3
  24. /package/src/client/components/{WorkspaceToolsWidget.vue → UsersWorkspaceToolsWidget.vue} +0 -0
@@ -1,8 +1,8 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
- import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
4
- import { hasPermission, normalizePermissionList } from "@jskit-ai/http-web/client/lib/permissions";
5
- import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
3
+ import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
4
+ import { hasPermission, normalizePermissionList } from "@jskit-ai/users-web/client/lib/permissions";
5
+ import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
6
6
 
7
7
  const props = defineProps({
8
8
  label: {
@@ -9,7 +9,7 @@ import {
9
9
  import { TENANCY_MODE_NONE } from "@jskit-ai/workspaces-core/shared/tenancyProfile";
10
10
  import { mdiBriefcaseOutline } from "@mdi/js";
11
11
  import { findWorkspaceBySlug, normalizeWorkspaceEntry, normalizeWorkspaceList } from "../lib/bootstrap.js";
12
- import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
12
+ import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
13
13
  import { resolveSurfaceSwitchTargetsFromPlacementContext, surfaceRequiresWorkspaceFromPlacementContext } from "../lib/workspaceSurfaceContext.js";
14
14
  import { resolveWorkspaceSurfaceIdFromPlacementPathname, extractWorkspaceSlugFromSurfacePathname } from "../lib/workspaceSurfacePaths.js";
15
15
 
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { mdiCogOutline } from "@mdi/js";
3
- import WorkspacePermissionMenuItem from "./WorkspacePermissionMenuItem.vue";
3
+ import UsersWorkspacePermissionMenuItem from "./UsersWorkspacePermissionMenuItem.vue";
4
4
 
5
5
  const props = defineProps({
6
6
  label: {
@@ -28,7 +28,7 @@ const WORKSPACE_SETTINGS_MENU_PERMISSIONS = Object.freeze([
28
28
  </script>
29
29
 
30
30
  <template>
31
- <WorkspacePermissionMenuItem
31
+ <UsersWorkspacePermissionMenuItem
32
32
  :label="props.label"
33
33
  :to="props.to"
34
34
  :icon="props.icon"
@@ -62,12 +62,12 @@
62
62
  import { computed, onMounted } from "vue";
63
63
  import { useRoute, useRouter } from "vue-router";
64
64
  import { useAuthStore } from "@jskit-ai/auth-web/client";
65
- import { useEndpointResource } from "@jskit-ai/http-web/client/composables/useEndpointResource";
65
+ import { useEndpointResource } from "@jskit-ai/users-web/client/composables/useEndpointResource";
66
66
  import {
67
67
  WORKSPACE_INVITATION_RESOLVE_TRANSPORT,
68
68
  WORKSPACE_INVITE_REDEEM_TRANSPORT
69
69
  } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
70
- import { httpWebClient } from "@jskit-ai/http-web/client/lib/httpClient";
70
+ import { workspacesWebHttpClient } from "../lib/httpClient.js";
71
71
 
72
72
  const route = useRoute();
73
73
  const router = useRouter();
@@ -84,7 +84,7 @@ const inviteResource = useEndpointResource({
84
84
  queryKey: computed(() => ["workspaces-web", "invite-landing", token.value]),
85
85
  path: "/api/workspace/invitations/resolve",
86
86
  enabled: computed(() => Boolean(token.value)),
87
- client: httpWebClient,
87
+ client: workspacesWebHttpClient,
88
88
  readQuery: inviteQuery,
89
89
  transport: WORKSPACE_INVITATION_RESOLVE_TRANSPORT,
90
90
  fallbackLoadError: "Unable to load invitation."
@@ -94,7 +94,7 @@ const redeemResource = useEndpointResource({
94
94
  queryKey: computed(() => ["workspaces-web", "invite-landing", "redeem", token.value]),
95
95
  path: "/api/workspace/invitations/redeem",
96
96
  enabled: false,
97
- client: httpWebClient,
97
+ client: workspacesWebHttpClient,
98
98
  writeMethod: "POST",
99
99
  transport: WORKSPACE_INVITE_REDEEM_TRANSPORT,
100
100
  fallbackSaveError: "Unable to accept invitation."
@@ -41,12 +41,12 @@ import {
41
41
  WORKSPACE_SETTINGS_TRANSPORT
42
42
  } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
43
43
  import MembersAdminClientElement from "./MembersAdminClientElement.vue";
44
- import { useCommand } from "@jskit-ai/http-web/client/composables/useCommand";
45
- import { useList } from "@jskit-ai/http-web/client/composables/useList";
46
- import { useView } from "@jskit-ai/http-web/client/composables/useView";
47
- import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
48
- import { useAccess } from "@jskit-ai/http-web/client/composables/useAccess";
49
- import { useUiFeedback } from "@jskit-ai/http-web/client/composables/useUiFeedback";
44
+ import { useCommand } from "@jskit-ai/users-web/client/composables/useCommand";
45
+ import { useList } from "@jskit-ai/users-web/client/composables/useList";
46
+ import { useView } from "@jskit-ai/users-web/client/composables/useView";
47
+ import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
48
+ import { useAccess } from "@jskit-ai/users-web/client/composables/useAccess";
49
+ import { useUiFeedback } from "@jskit-ai/users-web/client/composables/runtime/useUiFeedback";
50
50
  import { useWorkspaceRouteContext } from "../composables/useWorkspaceRouteContext.js";
51
51
  import { createWorkspaceRealtimeMatcher } from "../support/realtimeWorkspace.js";
52
52
  import { buildWorkspaceQueryKey } from "../support/workspaceQueryKeys.js";
@@ -12,10 +12,10 @@ import {
12
12
  WORKSPACES_TRANSPORT,
13
13
  WORKSPACE_INVITE_REDEEM_TRANSPORT
14
14
  } from "@jskit-ai/workspaces-core/shared/jsonApiTransports";
15
- import { useCommand } from "@jskit-ai/http-web/client/composables/useCommand";
16
- import { useView } from "@jskit-ai/http-web/client/composables/useView";
17
- import { usePaths } from "@jskit-ai/shell-web/client/navigation/usePaths";
18
- import { useRealtimeQueryInvalidation } from "@jskit-ai/http-web/client/composables/useRealtimeQueryInvalidation";
15
+ import { useCommand } from "@jskit-ai/users-web/client/composables/useCommand";
16
+ import { useView } from "@jskit-ai/users-web/client/composables/useView";
17
+ import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
18
+ import { useRealtimeQueryInvalidation } from "@jskit-ai/users-web/client/composables/useRealtimeQueryInvalidation";
19
19
  import { useWorkspaceSurfaceId } from "../composables/useWorkspaceSurfaceId.js";
20
20
  import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
21
21
 
@@ -76,7 +76,7 @@ const redeemInviteModel = reactive({
76
76
  token: "",
77
77
  decision: ""
78
78
  });
79
- const bootstrapQueryKey = Object.freeze(["workspaces-web", "bootstrap", "__none__"]);
79
+ const bootstrapQueryKey = Object.freeze(["users-web", "bootstrap", "__none__"]);
80
80
  const OWNERSHIP_PUBLIC = ROUTE_VISIBILITY_PUBLIC;
81
81
 
82
82
  const bootstrapView = useView({
@@ -179,12 +179,12 @@ function reportFeedback({
179
179
  }
180
180
 
181
181
  errorRuntime.report({
182
- source: "workspaces-web.workspaces-view",
182
+ source: "users-web.workspaces-view",
183
183
  message: normalizedMessage,
184
184
  intent: "action-feedback",
185
185
  severity,
186
186
  channel,
187
- dedupeKey: dedupeKey || `workspaces-web.workspaces-view:${severity}:${normalizedMessage}`,
187
+ dedupeKey: dedupeKey || `users-web.workspaces-view:${severity}:${normalizedMessage}`,
188
188
  dedupeWindowMs: 3000
189
189
  });
190
190
  }
@@ -235,7 +235,7 @@ async function openWorkspace(workspaceSlug) {
235
235
  reportFeedback({
236
236
  message: "Workspace surface is not configured.",
237
237
  severity: "error",
238
- dedupeKey: "workspaces-web.workspaces-view:workspace-surface-missing"
238
+ dedupeKey: "users-web.workspaces-view:workspace-surface-missing"
239
239
  });
240
240
  return;
241
241
  }
@@ -259,7 +259,7 @@ async function openWorkspace(workspaceSlug) {
259
259
  reportFeedback({
260
260
  message: String(error?.message || "Unable to open workspace."),
261
261
  severity: "error",
262
- dedupeKey: `workspaces-web.workspaces-view:open-workspace:${normalizedSlug}`
262
+ dedupeKey: `users-web.workspaces-view:open-workspace:${normalizedSlug}`
263
263
  });
264
264
  } finally {
265
265
  selectingWorkspaceSlug.value = "";
@@ -301,7 +301,7 @@ async function respondToInvite(invite, decision) {
301
301
  reportFeedback({
302
302
  message: "Invitation refused.",
303
303
  severity: "success",
304
- dedupeKey: `workspaces-web.workspaces-view:invite-refused:${token}`
304
+ dedupeKey: `users-web.workspaces-view:invite-refused:${token}`
305
305
  });
306
306
  } catch (error) {
307
307
  reportFeedback({
@@ -309,7 +309,7 @@ async function respondToInvite(invite, decision) {
309
309
  error?.message || (normalizedDecision === "accept" ? "Unable to accept invite." : "Unable to refuse invite.")
310
310
  ),
311
311
  severity: "error",
312
- dedupeKey: `workspaces-web.workspaces-view:invite-${normalizedDecision}:${token}`
312
+ dedupeKey: `users-web.workspaces-view:invite-${normalizedDecision}:${token}`
313
313
  });
314
314
  } finally {
315
315
  inviteAction.value = {
@@ -339,7 +339,7 @@ async function createWorkspace() {
339
339
  reportFeedback({
340
340
  message: "Workspace name is required.",
341
341
  severity: "error",
342
- dedupeKey: "workspaces-web.workspaces-view:create-workspace-name-required"
342
+ dedupeKey: "users-web.workspaces-view:create-workspace-name-required"
343
343
  });
344
344
  return;
345
345
  }
@@ -358,7 +358,7 @@ async function createWorkspace() {
358
358
  reportFeedback({
359
359
  message: String(error?.message || "Unable to create workspace."),
360
360
  severity: "error",
361
- dedupeKey: "workspaces-web.workspaces-view:create-workspace-error"
361
+ dedupeKey: "users-web.workspaces-view:create-workspace-error"
362
362
  });
363
363
  }
364
364
  }
@@ -1,5 +1,5 @@
1
1
  import { computed } from "vue";
2
- import { useSurfaceRouteContext } from "@jskit-ai/shell-web/client/navigation/useSurfaceRouteContext";
2
+ import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
3
3
  import { readWorkspaceRouteScope } from "../support/workspaceScopeSupport.js";
4
4
 
5
5
  function useWorkspaceRouteContext() {
@@ -0,0 +1,10 @@
1
+ import { createTransientRetryHttpClient } from "@jskit-ai/http-runtime/client";
2
+
3
+ const workspacesWebHttpClient = createTransientRetryHttpClient({
4
+ credentials: "include",
5
+ csrf: {
6
+ sessionPath: "/api/session"
7
+ }
8
+ });
9
+
10
+ export { workspacesWebHttpClient };
@@ -0,0 +1,27 @@
1
+ import { hasPermission, normalizePermissionList } from "@jskit-ai/kernel/shared/support";
2
+
3
+ function toPermissionSet(values) {
4
+ const normalized = normalizePermissionList(values);
5
+ if (normalized.length < 1) {
6
+ return new Set();
7
+ }
8
+ return new Set(normalized);
9
+ }
10
+
11
+ function arePermissionListsEqual(left, right) {
12
+ const leftSet = toPermissionSet(left);
13
+ const rightSet = toPermissionSet(right);
14
+ if (leftSet.size !== rightSet.size) {
15
+ return false;
16
+ }
17
+
18
+ for (const permission of leftSet) {
19
+ if (!rightSet.has(permission)) {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ return true;
25
+ }
26
+
27
+ export { normalizePermissionList, arePermissionListsEqual, hasPermission };
@@ -4,10 +4,7 @@ import {
4
4
  normalizeRecord,
5
5
  normalizeWorkspaceBootstrapStatusValue
6
6
  } from "../support/runtimeNormalization.js";
7
- import {
8
- hasPermission,
9
- normalizePermissionList
10
- } from "@jskit-ai/http-web/client/lib/permissions";
7
+ import { hasPermission, normalizePermissionList } from "./permissions.js";
11
8
 
12
9
  const WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND = "not_found";
13
10
  const WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN = "forbidden";
@@ -1,8 +1,8 @@
1
- import WorkspaceProfileSurfaceSwitchMenuItem from "../components/WorkspaceProfileSurfaceSwitchMenuItem.vue";
2
- import WorkspaceSelector from "../components/WorkspaceSelector.vue";
3
- import WorkspaceToolsWidget from "../components/WorkspaceToolsWidget.vue";
4
- import WorkspaceSettingsMenuItem from "../components/WorkspaceSettingsMenuItem.vue";
5
- import WorkspaceMembersMenuItem from "../components/WorkspaceMembersMenuItem.vue";
1
+ import UsersProfileSurfaceSwitchMenuItem from "../components/UsersProfileSurfaceSwitchMenuItem.vue";
2
+ import UsersWorkspaceSelector from "../components/UsersWorkspaceSelector.vue";
3
+ import UsersWorkspaceToolsWidget from "../components/UsersWorkspaceToolsWidget.vue";
4
+ import UsersWorkspaceSettingsMenuItem from "../components/UsersWorkspaceSettingsMenuItem.vue";
5
+ import UsersWorkspaceMembersMenuItem from "../components/UsersWorkspaceMembersMenuItem.vue";
6
6
  import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
7
7
  import { registerBootstrapPayloadHandler } from "@jskit-ai/shell-web/client/bootstrap";
8
8
  import { createBootstrapPlacementRuntime } from "../runtime/bootstrapPlacementRuntime.js";
@@ -13,18 +13,18 @@ import {
13
13
 
14
14
  class WorkspacesWebClientProvider {
15
15
  static id = "workspaces.web.client";
16
- static startsAfter = ["shell.web.client"];
16
+ static dependsOn = ["users.web.client"];
17
17
 
18
18
  register(app) {
19
19
  if (!app || typeof app.singleton !== "function" || typeof app.tag !== "function") {
20
20
  throw new Error("WorkspacesWebClientProvider requires application singleton()/tag().");
21
21
  }
22
22
 
23
- app.singleton("workspaces.web.profile.menu.surface-switch-item", () => WorkspaceProfileSurfaceSwitchMenuItem);
24
- app.singleton("workspaces.web.workspace.selector", () => WorkspaceSelector);
25
- app.singleton("workspaces.web.workspace.tools.widget", () => WorkspaceToolsWidget);
26
- app.singleton("workspaces.web.workspace-settings.menu-item", () => WorkspaceSettingsMenuItem);
27
- app.singleton("workspaces.web.workspace-members.menu-item", () => WorkspaceMembersMenuItem);
23
+ app.singleton("workspaces.web.profile.menu.surface-switch-item", () => UsersProfileSurfaceSwitchMenuItem);
24
+ app.singleton("workspaces.web.workspace.selector", () => UsersWorkspaceSelector);
25
+ app.singleton("workspaces.web.workspace.tools.widget", () => UsersWorkspaceToolsWidget);
26
+ app.singleton("workspaces.web.workspace-settings.menu-item", () => UsersWorkspaceSettingsMenuItem);
27
+ app.singleton("workspaces.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
28
28
  app.singleton("workspaces.web.members-admin.element", () => MembersAdminClientElement);
29
29
  app.singleton("workspaces.web.bootstrap-placement.runtime", (scope) => createBootstrapPlacementRuntime({ app: scope }));
30
30
  registerBootstrapPayloadHandler(app, "workspaces.web.bootstrap.handler", (scope) => {
@@ -2,7 +2,7 @@ import {
2
2
  findWorkspaceBySlug,
3
3
  normalizeWorkspaceList
4
4
  } from "../lib/bootstrap.js";
5
- import { normalizePermissionList } from "@jskit-ai/http-web/client/lib/permissions";
5
+ import { normalizePermissionList } from "../lib/permissions.js";
6
6
  import {
7
7
  persistBootstrapThemePreference,
8
8
  resolveBootstrapThemeName,
@@ -7,7 +7,7 @@ import {
7
7
  } from "@jskit-ai/shell-web/client/placement";
8
8
  import { parseWorkspacePathname } from "@jskit-ai/workspaces-core/shared/support/workspacePathModel";
9
9
  import { extractWorkspaceSlugFromSurfacePathname } from "../lib/workspaceSurfacePaths.js";
10
- import { httpWebClient } from "@jskit-ai/http-web/client/lib/httpClient";
10
+ import { workspacesWebHttpClient } from "../lib/httpClient.js";
11
11
  import { buildBootstrapApiPath } from "../lib/bootstrap.js";
12
12
  import {
13
13
  normalizeWorkspaceBootstrapStatusValue
@@ -127,7 +127,7 @@ function countPendingInvites(entries = []) {
127
127
  }
128
128
 
129
129
  async function fetchBootstrapPayload(workspaceSlug = "") {
130
- return httpWebClient.request(buildBootstrapApiPath(workspaceSlug), {
130
+ return workspacesWebHttpClient.request(buildBootstrapApiPath(workspaceSlug), {
131
131
  method: "GET"
132
132
  });
133
133
  }
@@ -1,11 +1,9 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
- import packageJson from "../package.json" with { type: "json" };
4
-
5
- const packageMetadata = packageJson.jskit;
3
+ import descriptor from "../package.descriptor.mjs";
6
4
 
7
5
  test("workspaces-web leaves editable workspace scaffolds app-owned", () => {
8
- const fileMutations = packageMetadata.mutations.files;
6
+ const fileMutations = descriptor.mutations.files;
9
7
 
10
8
  assert.ok(fileMutations.length > 0);
11
9
  for (const mutation of fileMutations) {
@@ -4,15 +4,13 @@ import test from "node:test";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { assertGeneratedUiSourceContract } from "@jskit-ai/kernel/shared/support/generatedUiContract";
7
- import packageJson from "../package.json" with { type: "json" };
8
-
9
- const packageMetadata = packageJson.jskit;
7
+ import descriptor from "../package.descriptor.mjs";
10
8
 
11
9
  const TEST_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
12
10
  const PACKAGE_DIR = path.resolve(TEST_DIRECTORY, "..");
13
11
 
14
12
  function readOutlets(target = "") {
15
- const outlets = packageMetadata?.metadata?.ui?.placements?.outlets;
13
+ const outlets = descriptor?.metadata?.ui?.placements?.outlets;
16
14
  const normalizedTarget = String(target || "").trim();
17
15
  return Array.isArray(outlets)
18
16
  ? outlets.filter((entry) => String(entry?.target || "").trim() === normalizedTarget)
@@ -20,7 +18,7 @@ function readOutlets(target = "") {
20
18
  }
21
19
 
22
20
  function findTopology(id, owner = "") {
23
- const placements = packageMetadata?.metadata?.ui?.placements?.topology?.placements;
21
+ const placements = descriptor?.metadata?.ui?.placements?.topology?.placements;
24
22
  const normalizedId = String(id || "").trim();
25
23
  const normalizedOwner = String(owner || "").trim();
26
24
  return Array.isArray(placements)
@@ -33,28 +31,28 @@ function findTopology(id, owner = "") {
33
31
  }
34
32
 
35
33
  function findContribution(id) {
36
- const contributions = packageMetadata?.metadata?.ui?.placements?.contributions;
34
+ const contributions = descriptor?.metadata?.ui?.placements?.contributions;
37
35
  return Array.isArray(contributions)
38
36
  ? contributions.find((entry) => String(entry?.id || "").trim() === id) || null
39
37
  : null;
40
38
  }
41
39
 
42
40
  function findTextMutation(id) {
43
- const textMutations = packageMetadata?.mutations?.text;
41
+ const textMutations = descriptor?.mutations?.text;
44
42
  return Array.isArray(textMutations)
45
43
  ? textMutations.find((entry) => String(entry?.id || "").trim() === id) || null
46
44
  : null;
47
45
  }
48
46
 
49
47
  function findSourceMutation(id) {
50
- const sourceMutations = packageMetadata?.mutations?.source;
48
+ const sourceMutations = descriptor?.mutations?.source;
51
49
  return Array.isArray(sourceMutations)
52
50
  ? sourceMutations.find((entry) => String(entry?.id || "").trim() === id) || null
53
51
  : null;
54
52
  }
55
53
 
56
54
  function findFileMutation(id) {
57
- const fileMutations = packageMetadata?.mutations?.files;
55
+ const fileMutations = descriptor?.mutations?.files;
58
56
  return Array.isArray(fileMutations)
59
57
  ? fileMutations.find((entry) => String(entry?.id || "").trim() === id) || null
60
58
  : null;
@@ -98,13 +96,13 @@ test("workspaces-web installs an app-owned account invites section wrapper", asy
98
96
  source,
99
97
  /@jskit-ai\/workspaces-web\/client\/components\/AccountSettingsInvitesSection/
100
98
  );
101
- assert.deepEqual(findFileMutation("workspaces-web-main-component-account-settings-invites-section"), {
99
+ assert.deepEqual(findFileMutation("users-web-main-component-account-settings-invites-section"), {
102
100
  from: "templates/packages/main/src/client/components/AccountSettingsInvitesSection.vue",
103
101
  to: "packages/main/src/client/components/AccountSettingsInvitesSection.vue",
104
102
  ownership: "app",
105
103
  reason: "Install app-owned account invites section scaffold for multihoming account settings.",
106
104
  category: "workspaces-web",
107
- id: "workspaces-web-main-component-account-settings-invites-section"
105
+ id: "users-web-main-component-account-settings-invites-section"
108
106
  });
109
107
  });
110
108
 
@@ -158,7 +156,7 @@ test("workspaces-web resource load states expose local retry actions", async ()
158
156
  }
159
157
  });
160
158
 
161
- test("workspaces-web command loading state uses http-web proxyRefs contract", async () => {
159
+ test("workspaces-web command loading state uses users-web proxyRefs contract", async () => {
162
160
  const expectations = new Map([
163
161
  [
164
162
  "src/client/components/WorkspaceMembersClientElement.vue",
@@ -204,13 +202,13 @@ test("workspaces-web installs an account invites cue scaffold that reads placeme
204
202
  assert.doesNotMatch(source, /\buseQuery\b/);
205
203
  assert.match(source, /placementContext\.value\?\.pendingInvitesCount/);
206
204
  assert.match(source, /placementContext\.value\?\.workspaceInvitesEnabled/);
207
- assert.deepEqual(findFileMutation("workspaces-web-main-component-account-pending-invites-cue"), {
205
+ assert.deepEqual(findFileMutation("users-web-main-component-account-pending-invites-cue"), {
208
206
  from: "templates/packages/main/src/client/components/AccountPendingInvitesCue.vue",
209
207
  to: "packages/main/src/client/components/AccountPendingInvitesCue.vue",
210
208
  ownership: "app",
211
209
  reason: "Install app-owned account pending invites cue component scaffold.",
212
210
  category: "workspaces-web",
213
- id: "workspaces-web-main-component-account-pending-invites-cue"
211
+ id: "users-web-main-component-account-pending-invites-cue"
214
212
  });
215
213
  });
216
214
 
@@ -284,7 +282,7 @@ test("workspaces-web starter surfaces avoid instructional placeholder copy", asy
284
282
  assert.doesNotMatch(adminSource, /Use this area|Privileged workspace workflows/);
285
283
  });
286
284
 
287
- test("workspaces-web packageMetadata metadata advertises admin settings outlets", () => {
285
+ test("workspaces-web descriptor metadata advertises admin settings outlets", () => {
288
286
  assert.deepEqual(
289
287
  readOutlets("admin-settings:primary-menu"),
290
288
  [
@@ -301,7 +299,7 @@ test("workspaces-web packageMetadata metadata advertises admin settings outlets"
301
299
  {
302
300
  target: "admin-cog:primary-menu",
303
301
  surfaces: ["admin"],
304
- source: "src/client/components/WorkspaceToolsWidget.vue"
302
+ source: "src/client/components/UsersWorkspaceToolsWidget.vue"
305
303
  }
306
304
  ]
307
305
  );
@@ -418,29 +416,29 @@ test("workspaces-web packageMetadata metadata advertises admin settings outlets"
418
416
  assert.match(findTextMutation("workspaces-web-admin-placement-topology")?.value || "", /outlet: "admin-settings:primary-menu"/);
419
417
  assert.match(findTextMutation("workspaces-web-admin-placement-topology")?.value || "", /id: "admin\.tools-menu"/);
420
418
  assert.match(findTextMutation("workspaces-web-admin-placement-topology")?.value || "", /outlet: "admin-cog:primary-menu"/);
421
- assert.deepEqual(findFileMutation("workspaces-web-page-admin-workspace-settings"), {
419
+ assert.deepEqual(findFileMutation("users-web-page-admin-workspace-settings"), {
422
420
  from: "templates/src/pages/admin/workspace/settings/index.vue",
423
421
  toSurface: "admin",
424
422
  toSurfacePath: "workspace/settings/index.vue",
425
423
  ownership: "app",
426
424
  reason: "Install workspace settings index stub scaffold for app-owned landing or redirect behavior.",
427
425
  category: "workspaces-web",
428
- id: "workspaces-web-page-admin-workspace-settings",
426
+ id: "users-web-page-admin-workspace-settings",
429
427
  when: {
430
428
  config: "tenancyMode",
431
429
  in: ["personal", "workspaces"]
432
430
  }
433
431
  });
434
- assert.deepEqual(findSourceMutation("workspaces-web-main-client-provider-account-settings-section-import"), {
432
+ assert.deepEqual(findSourceMutation("users-web-main-client-provider-account-settings-section-import"), {
435
433
  op: "ensure-import",
436
434
  file: "packages/main/src/client/providers/MainClientProvider.js",
437
435
  defaultImport: "AccountSettingsInvitesSection",
438
436
  from: "../components/AccountSettingsInvitesSection.vue",
439
437
  reason: "Bind app-owned account invites section component into local main client provider imports.",
440
438
  category: "workspaces-web",
441
- id: "workspaces-web-main-client-provider-account-settings-section-import"
439
+ id: "users-web-main-client-provider-account-settings-section-import"
442
440
  });
443
- assert.deepEqual(findSourceMutation("workspaces-web-main-client-provider-account-settings-section-register"), {
441
+ assert.deepEqual(findSourceMutation("users-web-main-client-provider-account-settings-section-register"), {
444
442
  op: "ensure-call",
445
443
  file: "packages/main/src/client/providers/MainClientProvider.js",
446
444
  callee: "registerMainClientComponent",
@@ -448,6 +446,6 @@ test("workspaces-web packageMetadata metadata advertises admin settings outlets"
448
446
  beforeClass: "MainClientProvider",
449
447
  reason: "Bind app-owned account invites section component token into local main client provider registry.",
450
448
  category: "workspaces-web",
451
- id: "workspaces-web-main-client-provider-account-settings-section-register"
449
+ id: "users-web-main-client-provider-account-settings-section-register"
452
450
  });
453
451
  });
@@ -6,9 +6,9 @@ import { readFile } from "node:fs/promises";
6
6
 
7
7
  const TEST_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
8
8
  const PACKAGE_DIR = path.resolve(TEST_DIRECTORY, "..");
9
- const COMPONENT_PATH = path.join(PACKAGE_DIR, "src", "client", "components", "WorkspaceSelector.vue");
9
+ const COMPONENT_PATH = path.join(PACKAGE_DIR, "src", "client", "components", "UsersWorkspaceSelector.vue");
10
10
 
11
- test("WorkspaceSelector passes workspaceSlug through generic page params", async () => {
11
+ test("UsersWorkspaceSelector passes workspaceSlug through generic page params", async () => {
12
12
  const source = await readFile(COMPONENT_PATH, "utf8");
13
13
 
14
14
  assert.match(
@@ -18,7 +18,7 @@ test("WorkspaceSelector passes workspaceSlug through generic page params", async
18
18
  assert.doesNotMatch(source, /workspaceSlug:\s*normalizedSlug,\s*mode:\s*"workspace"/s);
19
19
  });
20
20
 
21
- test("WorkspaceSelector activator preserves the generated tap-target contract", async () => {
21
+ test("UsersWorkspaceSelector activator preserves the generated tap-target contract", async () => {
22
22
  const source = await readFile(COMPONENT_PATH, "utf8");
23
23
 
24
24
  assert.match(source, /class="users-workspace-selector__activator text-none"/);