@jskit-ai/users-core 0.1.30 → 0.1.32

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 (37) hide show
  1. package/package.descriptor.mjs +8 -6
  2. package/package.json +6 -6
  3. package/src/server/UsersCoreServiceProvider.js +1 -3
  4. package/src/server/accountProfile/avatarService.js +18 -59
  5. package/src/server/accountProfile/avatarStorageService.js +14 -95
  6. package/src/server/accountProfile/bootAccountProfileRoutes.js +10 -14
  7. package/src/server/common/formatters/workspaceFormatter.js +2 -2
  8. package/src/server/common/repositories/userProfilesRepository.js +6 -6
  9. package/src/server/common/repositories/workspaceInvitesRepository.js +2 -2
  10. package/src/server/common/repositories/workspaceMembershipsRepository.js +9 -9
  11. package/src/server/common/repositories/workspacesRepository.js +2 -2
  12. package/src/server/common/services/authProfileSyncService.js +5 -5
  13. package/src/server/common/services/workspaceContextService.js +3 -3
  14. package/src/server/common/validators/authenticatedUserValidator.js +2 -2
  15. package/src/server/workspaceBootstrapContributor.js +2 -2
  16. package/src/server/workspaceMembers/bootWorkspaceMembers.js +2 -2
  17. package/src/server/workspaceMembers/workspaceMembersActions.js +2 -2
  18. package/src/server/workspaceMembers/workspaceMembersService.js +11 -11
  19. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +1 -1
  20. package/src/shared/resources/workspaceMembersResource.js +11 -11
  21. package/src/shared/resources/workspacePendingInvitationsResource.js +2 -2
  22. package/src/shared/resources/workspaceResource.js +2 -2
  23. package/src/shared/roles.js +8 -8
  24. package/templates/migrations/users_core_initial.cjs +5 -5
  25. package/test/authProfileSyncService.test.js +5 -5
  26. package/test/avatarService.test.js +4 -4
  27. package/test/usersRouteRequestInputValidator.test.js +4 -4
  28. package/test/workspaceActionContextContributor.test.js +9 -9
  29. package/test/workspaceAuthPolicyContextResolver.test.js +2 -2
  30. package/test/workspaceBootstrapContributor.test.js +1 -1
  31. package/test/workspaceInvitesRepository.test.js +3 -3
  32. package/test/workspaceMembersService.test.js +10 -10
  33. package/test/workspacePendingInvitationsResource.test.js +2 -2
  34. package/test/workspacePendingInvitationsService.test.js +3 -3
  35. package/test/workspaceService.test.js +10 -10
  36. package/src/server/accountProfile/registerAvatarMultipartSupport.js +0 -40
  37. package/test/registerAvatarMultipartSupport.test.js +0 -63
@@ -103,7 +103,7 @@ function bootWorkspaceMembers(app) {
103
103
  input: {
104
104
  workspaceSlug: request.input.params.workspaceSlug,
105
105
  memberUserId: request.input.params.memberUserId,
106
- roleId: request.input.body.roleId
106
+ roleSid: request.input.body.roleSid
107
107
  }
108
108
  });
109
109
  reply.code(200).send(response);
@@ -195,7 +195,7 @@ function bootWorkspaceMembers(app) {
195
195
  input: {
196
196
  workspaceSlug: request.input.params.workspaceSlug,
197
197
  email: request.input.body.email,
198
- roleId: request.input.body.roleId
198
+ roleSid: request.input.body.roleSid
199
199
  }
200
200
  });
201
201
  reply.code(200).send(response);
@@ -68,7 +68,7 @@ const workspaceMembersActions = Object.freeze([
68
68
  async execute(input, context, deps) {
69
69
  return deps.workspaceMembersService.updateMemberRole(resolveWorkspace(context, input), {
70
70
  memberUserId: input.memberUserId,
71
- roleId: input.roleId
71
+ roleSid: input.roleSid
72
72
  }, {
73
73
  context
74
74
  });
@@ -150,7 +150,7 @@ const workspaceMembersActions = Object.freeze([
150
150
  resolveActionUser(context, input),
151
151
  {
152
152
  email: input.email,
153
- roleId: input.roleId
153
+ roleSid: input.roleSid
154
154
  },
155
155
  {
156
156
  context
@@ -62,12 +62,12 @@ function createService({
62
62
 
63
63
  async function updateMemberRole(workspace, payload = {}, options = {}) {
64
64
  const memberUserId = payload.memberUserId;
65
- const roleId = payload.roleId;
66
- if (!assignableRoleIds.includes(roleId)) {
65
+ const roleSid = payload.roleSid;
66
+ if (!assignableRoleIds.includes(roleSid)) {
67
67
  throw new AppError(400, "Validation failed.", {
68
68
  details: {
69
69
  fieldErrors: {
70
- roleId: "Role is not assignable."
70
+ roleSid: "Role is not assignable."
71
71
  }
72
72
  }
73
73
  });
@@ -77,7 +77,7 @@ function createService({
77
77
  if (!existingMembership || existingMembership.status !== "active") {
78
78
  throw new AppError(404, "Member not found.");
79
79
  }
80
- if (Number(memberUserId) === Number(workspace.ownerUserId) || existingMembership.roleId === OWNER_ROLE_ID) {
80
+ if (Number(memberUserId) === Number(workspace.ownerUserId) || existingMembership.roleSid === OWNER_ROLE_ID) {
81
81
  throw new AppError(409, "Cannot change workspace owner role.");
82
82
  }
83
83
 
@@ -85,7 +85,7 @@ function createService({
85
85
  workspace.id,
86
86
  memberUserId,
87
87
  {
88
- roleId,
88
+ roleSid,
89
89
  status: "active"
90
90
  },
91
91
  options
@@ -101,7 +101,7 @@ function createService({
101
101
  if (!existingMembership || existingMembership.status !== "active") {
102
102
  throw new AppError(404, "Member not found.");
103
103
  }
104
- if (Number(memberUserId) === Number(workspace.ownerUserId) || existingMembership.roleId === OWNER_ROLE_ID) {
104
+ if (Number(memberUserId) === Number(workspace.ownerUserId) || existingMembership.roleSid === OWNER_ROLE_ID) {
105
105
  throw new AppError(409, "Cannot remove workspace owner.");
106
106
  }
107
107
 
@@ -109,7 +109,7 @@ function createService({
109
109
  workspace.id,
110
110
  memberUserId,
111
111
  {
112
- roleId: existingMembership.roleId,
112
+ roleSid: existingMembership.roleSid,
113
113
  status: "revoked"
114
114
  },
115
115
  options
@@ -134,12 +134,12 @@ function createService({
134
134
 
135
135
  async function createInvite(workspace, user, payload = {}, options = {}) {
136
136
  const email = payload.email;
137
- const roleId = payload.roleId;
138
- if (!assignableRoleIds.includes(roleId)) {
137
+ const roleSid = payload.roleSid;
138
+ if (!assignableRoleIds.includes(roleSid)) {
139
139
  throw new AppError(400, "Validation failed.", {
140
140
  details: {
141
141
  fieldErrors: {
142
- roleId: "Role is not assignable."
142
+ roleSid: "Role is not assignable."
143
143
  }
144
144
  }
145
145
  });
@@ -152,7 +152,7 @@ function createService({
152
152
  {
153
153
  workspaceId: workspace.id,
154
154
  email,
155
- roleId,
155
+ roleSid,
156
156
  status: "pending",
157
157
  tokenHash,
158
158
  invitedByUserId: Number(user?.id || 0) || null,
@@ -99,7 +99,7 @@ function createService({
99
99
  workspaceId,
100
100
  resolvedInvite.user.id,
101
101
  {
102
- roleId: resolvedInvite.invite.roleId,
102
+ roleSid: resolvedInvite.invite.roleSid,
103
103
  status: "active"
104
104
  },
105
105
  options
@@ -19,7 +19,7 @@ const workspaceSummaryOutputSchema = Type.Object(
19
19
  const memberSummaryOutputSchema = Type.Object(
20
20
  {
21
21
  userId: Type.Integer({ minimum: 1 }),
22
- roleId: Type.String({ minLength: 1 }),
22
+ roleSid: Type.String({ minLength: 1 }),
23
23
  status: Type.String({ minLength: 1 }),
24
24
  displayName: Type.String(),
25
25
  email: Type.String({ minLength: 1 }),
@@ -32,7 +32,7 @@ const inviteSummaryOutputSchema = Type.Object(
32
32
  {
33
33
  id: Type.Integer({ minimum: 1 }),
34
34
  email: Type.String({ minLength: 3, format: "email" }),
35
- roleId: Type.String({ minLength: 1 }),
35
+ roleSid: Type.String({ minLength: 1 }),
36
36
  status: Type.String({ minLength: 1 }),
37
37
  expiresAt: Type.String({ minLength: 1 }),
38
38
  invitedByUserId: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()])
@@ -57,13 +57,13 @@ function normalizeMemberSummary(member, workspace) {
57
57
 
58
58
  return {
59
59
  userId: Number(source.userId),
60
- roleId: normalizeLowerText(source.roleId || "member") || "member",
60
+ roleSid: normalizeLowerText(source.roleSid || "member") || "member",
61
61
  status: normalizeLowerText(source.status || "active") || "active",
62
62
  displayName: normalizeText(source.displayName),
63
63
  email: normalizeLowerText(source.email),
64
64
  isOwner:
65
65
  Number(source.userId) === Number(workspace.ownerUserId) ||
66
- normalizeLowerText(source.roleId) === OWNER_ROLE_ID
66
+ normalizeLowerText(source.roleSid) === OWNER_ROLE_ID
67
67
  };
68
68
  }
69
69
 
@@ -73,7 +73,7 @@ function normalizeInviteSummary(invite) {
73
73
  return {
74
74
  id: Number(source.id),
75
75
  email: normalizeLowerText(source.email),
76
- roleId: normalizeLowerText(source.roleId || "member") || "member",
76
+ roleSid: normalizeLowerText(source.roleSid || "member") || "member",
77
77
  status: normalizeLowerText(source.status || "pending") || "pending",
78
78
  expiresAt: source.expiresAt,
79
79
  invitedByUserId: source.invitedByUserId == null ? null : Number(source.invitedByUserId)
@@ -160,7 +160,7 @@ const workspaceInvitesOutputValidator = Object.freeze({
160
160
  const updateMemberRoleBodyValidator = Object.freeze({
161
161
  schema: Type.Object(
162
162
  {
163
- roleId: Type.String({ minLength: 1 })
163
+ roleSid: Type.String({ minLength: 1 })
164
164
  },
165
165
  { additionalProperties: false }
166
166
  ),
@@ -168,7 +168,7 @@ const updateMemberRoleBodyValidator = Object.freeze({
168
168
  const source = normalizeObjectInput(payload);
169
169
 
170
170
  return {
171
- roleId: normalizeLowerText(source.roleId)
171
+ roleSid: normalizeLowerText(source.roleSid)
172
172
  };
173
173
  }
174
174
  });
@@ -177,7 +177,7 @@ const updateMemberRoleInputValidator = Object.freeze({
177
177
  schema: Type.Object(
178
178
  {
179
179
  memberUserId: Type.Integer({ minimum: 1 }),
180
- roleId: Type.String({ minLength: 1 })
180
+ roleSid: Type.String({ minLength: 1 })
181
181
  },
182
182
  { additionalProperties: false }
183
183
  ),
@@ -186,7 +186,7 @@ const updateMemberRoleInputValidator = Object.freeze({
186
186
 
187
187
  return {
188
188
  memberUserId: normalizePositiveInteger(source.memberUserId),
189
- roleId: normalizeLowerText(source.roleId)
189
+ roleSid: normalizeLowerText(source.roleSid)
190
190
  };
191
191
  }
192
192
  });
@@ -211,7 +211,7 @@ const createInviteBodyValidator = Object.freeze({
211
211
  schema: Type.Object(
212
212
  {
213
213
  email: Type.String({ minLength: 3, format: "email" }),
214
- roleId: Type.String({ minLength: 1 })
214
+ roleSid: Type.String({ minLength: 1 })
215
215
  },
216
216
  { additionalProperties: false }
217
217
  ),
@@ -220,7 +220,7 @@ const createInviteBodyValidator = Object.freeze({
220
220
 
221
221
  return {
222
222
  email: normalizeLowerText(source.email),
223
- roleId: normalizeLowerText(source.roleId || "member") || "member"
223
+ roleSid: normalizeLowerText(source.roleSid || "member") || "member"
224
224
  };
225
225
  }
226
226
  });
@@ -25,7 +25,7 @@ function normalizePendingInvite(invite) {
25
25
  workspaceSlug: normalizeText(invite?.workspaceSlug),
26
26
  workspaceName: normalizeText(invite?.workspaceName || invite?.workspaceSlug),
27
27
  workspaceAvatarUrl: normalizeText(invite?.workspaceAvatarUrl),
28
- roleId: normalizeLowerText(invite?.roleId || "member") || "member",
28
+ roleSid: normalizeLowerText(invite?.roleSid || "member") || "member",
29
29
  status: normalizeLowerText(invite?.status || "pending") || "pending",
30
30
  expiresAt: invite?.expiresAt || null,
31
31
  token: encodeInviteTokenHash(tokenHash)
@@ -44,7 +44,7 @@ const pendingInviteRecordValidator = Object.freeze({
44
44
  workspaceSlug: Type.String({ minLength: 1 }),
45
45
  workspaceName: Type.String({ minLength: 1 }),
46
46
  workspaceAvatarUrl: Type.String(),
47
- roleId: Type.String({ minLength: 1 }),
47
+ roleSid: Type.String({ minLength: 1 }),
48
48
  status: Type.String({ minLength: 1 }),
49
49
  expiresAt: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
50
50
  token: Type.String({ minLength: 1 })
@@ -63,7 +63,7 @@ function normalizeWorkspaceListItemOutput(payload = {}) {
63
63
  slug: normalizeLowerText(source.slug),
64
64
  name: normalizeText(source.name),
65
65
  avatarUrl: normalizeText(source.avatarUrl),
66
- roleId: normalizeLowerText(source.roleId || "member") || "member",
66
+ roleSid: normalizeLowerText(source.roleSid || "member") || "member",
67
67
  isAccessible: source.isAccessible !== false
68
68
  };
69
69
  }
@@ -85,7 +85,7 @@ const listItemSchema = Type.Object(
85
85
  slug: Type.String({ minLength: 1 }),
86
86
  name: Type.String({ minLength: 1, maxLength: 160 }),
87
87
  avatarUrl: Type.String(),
88
- roleId: Type.String({ minLength: 1 }),
88
+ roleSid: Type.String({ minLength: 1 }),
89
89
  isAccessible: Type.Boolean()
90
90
  },
91
91
  { additionalProperties: false }
@@ -20,13 +20,13 @@ function normalizeRoleId(value) {
20
20
  .toLowerCase();
21
21
  }
22
22
 
23
- function createRoleDescriptor(roleId, configuredDefinition) {
23
+ function createRoleDescriptor(roleSid, configuredDefinition) {
24
24
  const source = asRecord(configuredDefinition);
25
- const assignable = roleId === OWNER_ROLE_ID ? false : source.assignable === true;
25
+ const assignable = roleSid === OWNER_ROLE_ID ? false : source.assignable === true;
26
26
  const permissions = normalizePermissionList(source.permissions);
27
27
 
28
28
  return Object.freeze({
29
- id: roleId,
29
+ id: roleSid,
30
30
  assignable,
31
31
  permissions: Object.freeze([...permissions])
32
32
  });
@@ -46,8 +46,8 @@ function normalizeConfiguredRoles(appConfig = {}) {
46
46
  const configuredRoles = asRecord(workspaceRoles.roles);
47
47
  const normalizedRoles = {};
48
48
 
49
- for (const [roleId, roleDefinition] of Object.entries(configuredRoles)) {
50
- const normalizedRoleId = normalizeRoleId(roleId);
49
+ for (const [roleSid, roleDefinition] of Object.entries(configuredRoles)) {
50
+ const normalizedRoleId = normalizeRoleId(roleSid);
51
51
  if (!normalizedRoleId) {
52
52
  continue;
53
53
  }
@@ -60,7 +60,7 @@ function normalizeConfiguredRoles(appConfig = {}) {
60
60
  function createWorkspaceRoleCatalog(appConfig = {}) {
61
61
  const configuredRoles = normalizeConfiguredRoles(appConfig);
62
62
  const roleIds = listConfiguredRoleIds(appConfig);
63
- const roles = roleIds.map((roleId) => createRoleDescriptor(roleId, configuredRoles[roleId]));
63
+ const roles = roleIds.map((roleSid) => createRoleDescriptor(roleSid, configuredRoles[roleSid]));
64
64
  const assignableRoleIds = roles.filter((role) => role.assignable).map((role) => role.id);
65
65
  const configuredDefaultInviteRole = resolveConfiguredDefaultInviteRole(appConfig);
66
66
  const defaultInviteRole = assignableRoleIds.includes(configuredDefaultInviteRole)
@@ -109,8 +109,8 @@ function listRoleDescriptors(appConfig = {}) {
109
109
  }));
110
110
  }
111
111
 
112
- function resolveRolePermissions(roleId, appConfig = {}) {
113
- const normalizedRoleId = normalizeRoleId(roleId);
112
+ function resolveRolePermissions(roleSid, appConfig = {}) {
113
+ const normalizedRoleId = normalizeRoleId(roleSid);
114
114
  if (!normalizedRoleId) {
115
115
  return [];
116
116
  }
@@ -5,7 +5,7 @@ exports.up = async function up(knex) {
5
5
  await knex.schema.createTable("users", (table) => {
6
6
  table.increments("id").primary();
7
7
  table.string("auth_provider", 64).notNullable();
8
- table.string("auth_provider_user_id", 191).notNullable();
8
+ table.string("auth_provider_user_sid", 191).notNullable();
9
9
  table.string("email", 255).notNullable();
10
10
  table.string("username", 120).notNullable();
11
11
  table.string("display_name", 160).notNullable();
@@ -13,7 +13,7 @@ exports.up = async function up(knex) {
13
13
  table.string("avatar_version", 64).nullable();
14
14
  table.timestamp("avatar_updated_at", { useTz: false }).nullable();
15
15
  table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
16
- table.unique(["auth_provider", "auth_provider_user_id"], "uq_users_identity");
16
+ table.unique(["auth_provider", "auth_provider_user_sid"], "uq_users_identity");
17
17
  table.unique(["email"], "uq_users_email");
18
18
  table.unique(["username"], "uq_users_username");
19
19
  });
@@ -35,7 +35,7 @@ exports.up = async function up(knex) {
35
35
  table.increments("id").primary();
36
36
  table.integer("workspace_id").unsigned().notNullable().references("id").inTable("workspaces").onDelete("CASCADE");
37
37
  table.integer("user_id").unsigned().notNullable().references("id").inTable("users").onDelete("CASCADE");
38
- table.string("role_id", 64).notNullable().defaultTo("member");
38
+ table.string("role_sid", 64).notNullable().defaultTo("member");
39
39
  table.string("status", 32).notNullable().defaultTo("active");
40
40
  table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
41
41
  table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
@@ -63,7 +63,7 @@ exports.up = async function up(knex) {
63
63
  table.increments("id").primary();
64
64
  table.integer("workspace_id").unsigned().notNullable().references("id").inTable("workspaces").onDelete("CASCADE");
65
65
  table.string("email", 255).notNullable();
66
- table.string("role_id", 64).notNullable().defaultTo("member");
66
+ table.string("role_sid", 64).notNullable().defaultTo("member");
67
67
  table.string("status", 32).notNullable().defaultTo("pending");
68
68
  table.string("token_hash", 191).notNullable();
69
69
  table.integer("invited_by_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL");
@@ -97,7 +97,7 @@ exports.up = async function up(knex) {
97
97
 
98
98
  await knex.schema.createTable("console_settings", (table) => {
99
99
  table.integer("id").primary();
100
- table.integer("owner_user_id").unsigned().nullable();
100
+ table.integer("owner_user_id").unsigned().nullable().references("id").inTable("users").onDelete("SET NULL");
101
101
  table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
102
102
  table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
103
103
  });
@@ -17,7 +17,7 @@ test("authProfileSyncService.syncIdentityProfile uses shared transaction for pro
17
17
  return {
18
18
  id: 13,
19
19
  authProvider: payload.authProvider,
20
- authProviderUserId: payload.authProviderUserId,
20
+ authProviderUserSid: payload.authProviderUserSid,
21
21
  email: payload.email,
22
22
  displayName: payload.displayName
23
23
  };
@@ -42,7 +42,7 @@ test("authProfileSyncService.syncIdentityProfile uses shared transaction for pro
42
42
 
43
43
  const profile = await service.syncIdentityProfile({
44
44
  authProvider: "supabase",
45
- authProviderUserId: "abc-1",
45
+ authProviderUserSid: "abc-1",
46
46
  email: "tony@example.com",
47
47
  displayName: "Tony"
48
48
  });
@@ -69,7 +69,7 @@ test("authProfileSyncService.syncIdentityProfile skips write path when profile i
69
69
  return {
70
70
  id: 7,
71
71
  authProvider: "supabase",
72
- authProviderUserId: "abc-7",
72
+ authProviderUserSid: "abc-7",
73
73
  email: "tony@example.com",
74
74
  displayName: "Tony"
75
75
  };
@@ -96,7 +96,7 @@ test("authProfileSyncService.syncIdentityProfile skips write path when profile i
96
96
 
97
97
  const profile = await service.syncIdentityProfile({
98
98
  authProvider: "supabase",
99
- authProviderUserId: "abc-7",
99
+ authProviderUserSid: "abc-7",
100
100
  email: "tony@example.com",
101
101
  displayName: "Tony"
102
102
  });
@@ -127,7 +127,7 @@ test("authProfileSyncService.findByIdentity normalizes provider identity input",
127
127
 
128
128
  await service.findByIdentity({
129
129
  authProvider: " SUPABASE ",
130
- authProviderUserId: " user-1 "
130
+ authProviderUserSid: " user-1 "
131
131
  });
132
132
 
133
133
  assert.deepEqual(capturedIdentity, {
@@ -41,7 +41,7 @@ test("avatarService uploadForUser stores bytes and updates profile avatar fields
41
41
  const repository = createRepositoryDouble({
42
42
  id: 7,
43
43
  authProvider: "local",
44
- authProviderUserId: "u-7",
44
+ authProviderUserSid: "u-7",
45
45
  email: "test@example.com",
46
46
  displayName: "Tester",
47
47
  avatarStorageKey: null,
@@ -65,7 +65,7 @@ test("avatarService uploadForUser stores bytes and updates profile avatar fields
65
65
 
66
66
  const user = {
67
67
  authProvider: "local",
68
- authProviderUserId: "u-7"
68
+ authProviderUserSid: "u-7"
69
69
  };
70
70
 
71
71
  const result = await avatarService.uploadForUser(user, {
@@ -84,7 +84,7 @@ test("avatarService clearForUser removes stored avatar and clears profile fields
84
84
  const repository = createRepositoryDouble({
85
85
  id: 7,
86
86
  authProvider: "local",
87
- authProviderUserId: "u-7",
87
+ authProviderUserSid: "u-7",
88
88
  email: "test@example.com",
89
89
  displayName: "Tester",
90
90
  avatarStorageKey: "users/avatars/7/avatar",
@@ -105,7 +105,7 @@ test("avatarService clearForUser removes stored avatar and clears profile fields
105
105
 
106
106
  const profile = await avatarService.clearForUser({
107
107
  authProvider: "local",
108
- authProviderUserId: "u-7"
108
+ authProviderUserSid: "u-7"
109
109
  });
110
110
 
111
111
  assert.deepEqual(deletedKeys, ["users/avatars/7/avatar"]);
@@ -379,7 +379,7 @@ test("workspace invite and member handlers build action input from request.input
379
379
  createActionRequest({
380
380
  input: {
381
381
  params: { workspaceSlug: "acme", memberUserId: "12" },
382
- body: { roleId: "admin" }
382
+ body: { roleSid: "admin" }
383
383
  },
384
384
  executeAction
385
385
  }),
@@ -389,7 +389,7 @@ test("workspace invite and member handlers build action input from request.input
389
389
  createActionRequest({
390
390
  input: {
391
391
  params: { workspaceSlug: "acme" },
392
- body: { email: "user@example.com", roleId: "member" }
392
+ body: { email: "user@example.com", roleSid: "member" }
393
393
  },
394
394
  executeAction
395
395
  }),
@@ -419,8 +419,8 @@ test("workspace invite and member handlers build action input from request.input
419
419
  input: { name: "Operations", slug: "operations" }
420
420
  });
421
421
  assert.deepEqual(calls[1].input, { payload: { token: "token-1", decision: "accept" } });
422
- assert.deepEqual(calls[2].input, { workspaceSlug: "acme", memberUserId: "12", roleId: "admin" });
423
- assert.deepEqual(calls[3].input, { workspaceSlug: "acme", email: "user@example.com", roleId: "member" });
422
+ assert.deepEqual(calls[2].input, { workspaceSlug: "acme", memberUserId: "12", roleSid: "admin" });
423
+ assert.deepEqual(calls[3].input, { workspaceSlug: "acme", email: "user@example.com", roleSid: "member" });
424
424
  assert.deepEqual(calls[4].input, { workspaceSlug: "acme", memberUserId: "44" });
425
425
  assert.deepEqual(calls[5].input, { workspaceSlug: "acme", inviteId: "55" });
426
426
  });
@@ -19,7 +19,7 @@ test("workspace action context contributor resolves workspace context for worksp
19
19
  slug: "acme"
20
20
  },
21
21
  membership: {
22
- roleId: "owner"
22
+ roleSid: "owner"
23
23
  },
24
24
  permissions: ["workspace.settings.update"]
25
25
  };
@@ -64,7 +64,7 @@ test("workspace action context contributor resolves workspace context for worksp
64
64
  slug: "acme"
65
65
  },
66
66
  membership: {
67
- roleId: "owner"
67
+ roleSid: "owner"
68
68
  },
69
69
  permissions: ["workspace.settings.update"]
70
70
  }
@@ -74,7 +74,7 @@ test("workspace action context contributor resolves workspace context for worksp
74
74
  slug: "acme"
75
75
  },
76
76
  membership: {
77
- roleId: "owner"
77
+ roleSid: "owner"
78
78
  },
79
79
  permissions: ["workspace.settings.update"]
80
80
  });
@@ -113,7 +113,7 @@ test("workspace action context contributor always resolves and stores resolved c
113
113
  ownerUserId: 77
114
114
  },
115
115
  membership: {
116
- roleId: "owner"
116
+ roleSid: "owner"
117
117
  },
118
118
  permissions: ["workspace.settings.update"]
119
119
  };
@@ -161,13 +161,13 @@ test("workspace action context contributor always resolves and stores resolved c
161
161
  ownerUserId: 77
162
162
  },
163
163
  membership: {
164
- roleId: "owner"
164
+ roleSid: "owner"
165
165
  },
166
166
  permissions: ["workspace.settings.update"]
167
167
  }
168
168
  },
169
169
  membership: {
170
- roleId: "owner"
170
+ roleSid: "owner"
171
171
  },
172
172
  permissions: ["workspace.settings.update"]
173
173
  });
@@ -185,7 +185,7 @@ test("workspace action context contributor resolves context for workspace-visibl
185
185
  slug: "acme"
186
186
  },
187
187
  membership: {
188
- roleId: "admin"
188
+ roleSid: "admin"
189
189
  },
190
190
  permissions: ["assistant.chat.use"]
191
191
  };
@@ -234,7 +234,7 @@ test("workspace action context contributor resolves context for workspace-visibl
234
234
  slug: "acme"
235
235
  },
236
236
  membership: {
237
- roleId: "admin"
237
+ roleSid: "admin"
238
238
  },
239
239
  permissions: ["assistant.chat.use"]
240
240
  }
@@ -244,7 +244,7 @@ test("workspace action context contributor resolves context for workspace-visibl
244
244
  slug: "acme"
245
245
  },
246
246
  membership: {
247
- roleId: "admin"
247
+ roleSid: "admin"
248
248
  },
249
249
  permissions: ["assistant.chat.use"]
250
250
  });
@@ -45,7 +45,7 @@ test("workspace auth policy context resolver resolves workspace context from use
45
45
  slug: workspaceSlug
46
46
  },
47
47
  membership: {
48
- roleId: "owner"
48
+ roleSid: "owner"
49
49
  },
50
50
  permissions: ["projects.read"]
51
51
  };
@@ -85,7 +85,7 @@ test("workspace auth policy context resolver resolves workspace context from use
85
85
  slug: "acme"
86
86
  },
87
87
  membership: {
88
- roleId: "owner"
88
+ roleSid: "owner"
89
89
  },
90
90
  permissions: ["projects.read"]
91
91
  });
@@ -10,7 +10,7 @@ function createAuthenticatedProfile(overrides = {}) {
10
10
  return {
11
11
  id: 7,
12
12
  authProvider: "local",
13
- authProviderUserId: "user-7",
13
+ authProviderUserSid: "user-7",
14
14
  username: "tester",
15
15
  displayName: "Test User",
16
16
  email: "test@example.com",
@@ -11,7 +11,7 @@ function createKnexStub() {
11
11
  id: 1,
12
12
  workspace_id: 1,
13
13
  email: "invitee@example.com",
14
- role_id: "member",
14
+ role_sid: "member",
15
15
  status: "pending",
16
16
  token_hash: "hash",
17
17
  invited_by_user_id: 1,
@@ -57,7 +57,7 @@ test("workspaceInvitesRepository.insert normalizes expiresAt ISO input to databa
57
57
  await repository.insert({
58
58
  workspaceId: 1,
59
59
  email: "invitee@example.com",
60
- roleId: "member",
60
+ roleSid: "member",
61
61
  status: "pending",
62
62
  tokenHash: "hash",
63
63
  invitedByUserId: 1,
@@ -76,7 +76,7 @@ test("workspaceInvitesRepository.findPendingByTokenHash reads from invites table
76
76
  id: 44,
77
77
  workspace_id: 9,
78
78
  email: "invitee@example.com",
79
- role_id: "member",
79
+ role_sid: "member",
80
80
  status: "pending",
81
81
  token_hash: "hash-token",
82
82
  invited_by_user_id: 1,