@headless-lms/core 0.4.0 → 0.5.0

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 (249) hide show
  1. package/dist/assets/events.d.ts +27 -21
  2. package/dist/assets/file-urls.d.ts +11 -7
  3. package/dist/assets/file-urls.js +14 -4
  4. package/dist/assets/file-urls.js.map +1 -1
  5. package/dist/assets/index.d.ts +4 -4
  6. package/dist/assets/index.js +3 -3
  7. package/dist/assets/ports.d.ts +34 -15
  8. package/dist/assets/service.d.ts +30 -14
  9. package/dist/assets/service.js +230 -56
  10. package/dist/assets/service.js.map +1 -1
  11. package/dist/automations/actions.js.map +1 -1
  12. package/dist/automations/catalog.js +69 -4
  13. package/dist/automations/catalog.js.map +1 -1
  14. package/dist/automations/community-derivations.js +16 -16
  15. package/dist/automations/community-derivations.js.map +1 -1
  16. package/dist/automations/community-mail.d.ts +34 -4
  17. package/dist/automations/community-mail.js +32 -4
  18. package/dist/automations/community-mail.js.map +1 -1
  19. package/dist/automations/event-permissions.d.ts +12 -0
  20. package/dist/automations/event-permissions.js +38 -0
  21. package/dist/automations/event-permissions.js.map +1 -0
  22. package/dist/automations/index.d.ts +2 -1
  23. package/dist/automations/index.js +2 -1
  24. package/dist/automations/notifications/applicable.d.ts +8 -0
  25. package/dist/automations/notifications/applicable.js +12 -0
  26. package/dist/automations/notifications/applicable.js.map +1 -0
  27. package/dist/automations/notifications/debounce.js +1 -1
  28. package/dist/automations/notifications/debounce.js.map +1 -1
  29. package/dist/automations/notifications/defaults.js +33 -3
  30. package/dist/automations/notifications/defaults.js.map +1 -1
  31. package/dist/automations/notifications/processor.js +3 -3
  32. package/dist/automations/notifications/processor.js.map +1 -1
  33. package/dist/automations/notifications/rules/content.js +60 -3
  34. package/dist/automations/notifications/rules/content.js.map +1 -1
  35. package/dist/automations/notifications/rules/discussion.js +29 -29
  36. package/dist/automations/notifications/rules/discussion.js.map +1 -1
  37. package/dist/automations/notifications/rules/entitlements.js +36 -9
  38. package/dist/automations/notifications/rules/entitlements.js.map +1 -1
  39. package/dist/automations/notifications/rules/events.d.ts +9 -0
  40. package/dist/automations/notifications/rules/events.js +27 -0
  41. package/dist/automations/notifications/rules/events.js.map +1 -0
  42. package/dist/automations/notifications/rules/organizations.js +17 -10
  43. package/dist/automations/notifications/rules/organizations.js.map +1 -1
  44. package/dist/automations/notifications/rules/recipients.js +0 -1
  45. package/dist/automations/notifications/rules/recipients.js.map +1 -1
  46. package/dist/automations/notifications/service.d.ts +8 -6
  47. package/dist/automations/notifications/service.js +13 -13
  48. package/dist/automations/notifications/service.js.map +1 -1
  49. package/dist/automations/notifications/types.js +94 -7
  50. package/dist/automations/notifications/types.js.map +1 -1
  51. package/dist/automations/ports.d.ts +30 -31
  52. package/dist/automations/service.d.ts +20 -17
  53. package/dist/automations/service.js +91 -62
  54. package/dist/automations/service.js.map +1 -1
  55. package/dist/content/event-sight.d.ts +11 -0
  56. package/dist/content/event-sight.js +11 -0
  57. package/dist/content/event-sight.js.map +1 -0
  58. package/dist/content/events.d.ts +413 -72
  59. package/dist/content/events.js +34 -1
  60. package/dist/content/events.js.map +1 -1
  61. package/dist/content/index.d.ts +6 -4
  62. package/dist/content/index.js +3 -1
  63. package/dist/content/jobs.d.ts +16 -0
  64. package/dist/content/jobs.js +37 -0
  65. package/dist/content/jobs.js.map +1 -0
  66. package/dist/content/model.d.ts +2 -2
  67. package/dist/content/notification-categories.d.ts +5 -4
  68. package/dist/content/notification-categories.js +15 -6
  69. package/dist/content/notification-categories.js.map +1 -1
  70. package/dist/content/ports.d.ts +113 -68
  71. package/dist/content/service.d.ts +99 -67
  72. package/dist/content/service.js +680 -139
  73. package/dist/content/service.js.map +1 -1
  74. package/dist/content/titles.d.ts +6 -3
  75. package/dist/content/titles.js +37 -24
  76. package/dist/content/titles.js.map +1 -1
  77. package/dist/content/types.d.ts +2 -2
  78. package/dist/discussion/authors.d.ts +4 -2
  79. package/dist/discussion/authors.js +9 -5
  80. package/dist/discussion/authors.js.map +1 -1
  81. package/dist/discussion/chats.d.ts +56 -37
  82. package/dist/discussion/chats.js +393 -161
  83. package/dist/discussion/chats.js.map +1 -1
  84. package/dist/discussion/events.d.ts +77 -39
  85. package/dist/discussion/events.js +41 -3
  86. package/dist/discussion/events.js.map +1 -1
  87. package/dist/discussion/index.d.ts +8 -5
  88. package/dist/discussion/index.js +5 -3
  89. package/dist/discussion/live.d.ts +106 -0
  90. package/dist/discussion/live.js +642 -0
  91. package/dist/discussion/live.js.map +1 -0
  92. package/dist/discussion/mentions.js +2 -2
  93. package/dist/discussion/mentions.js.map +1 -1
  94. package/dist/discussion/ports.d.ts +182 -100
  95. package/dist/discussion/ports.js.map +1 -1
  96. package/dist/discussion/posts.d.ts +45 -39
  97. package/dist/discussion/posts.js +268 -154
  98. package/dist/discussion/posts.js.map +1 -1
  99. package/dist/discussion/rules.d.ts +18 -0
  100. package/dist/discussion/rules.js +22 -0
  101. package/dist/discussion/rules.js.map +1 -0
  102. package/dist/discussion/service.d.ts +37 -31
  103. package/dist/discussion/service.js +252 -188
  104. package/dist/discussion/service.js.map +1 -1
  105. package/dist/discussion/subscriptions.d.ts +8 -8
  106. package/dist/discussion/subscriptions.js +29 -13
  107. package/dist/discussion/subscriptions.js.map +1 -1
  108. package/dist/discussion/titles.d.ts +4 -2
  109. package/dist/discussion/titles.js +27 -13
  110. package/dist/discussion/titles.js.map +1 -1
  111. package/dist/entitlements/events.d.ts +20 -20
  112. package/dist/entitlements/index.d.ts +4 -4
  113. package/dist/entitlements/index.js +2 -2
  114. package/dist/entitlements/model.d.ts +2 -2
  115. package/dist/entitlements/ports.d.ts +65 -39
  116. package/dist/entitlements/rules.d.ts +3 -6
  117. package/dist/entitlements/rules.js +5 -10
  118. package/dist/entitlements/rules.js.map +1 -1
  119. package/dist/entitlements/service.d.ts +40 -28
  120. package/dist/entitlements/service.js +370 -163
  121. package/dist/entitlements/service.js.map +1 -1
  122. package/dist/identity/devices.d.ts +3 -3
  123. package/dist/identity/devices.js +7 -5
  124. package/dist/identity/devices.js.map +1 -1
  125. package/dist/identity/events.d.ts +2 -2
  126. package/dist/identity/index.d.ts +2 -2
  127. package/dist/identity/index.js +2 -2
  128. package/dist/identity/notification-settings.d.ts +1 -1
  129. package/dist/identity/notification-settings.js +3 -2
  130. package/dist/identity/notification-settings.js.map +1 -1
  131. package/dist/identity/ports.d.ts +7 -7
  132. package/dist/identity/service.d.ts +8 -7
  133. package/dist/identity/service.js +17 -13
  134. package/dist/identity/service.js.map +1 -1
  135. package/dist/integrations/events.d.ts +3 -3
  136. package/dist/integrations/ports.d.ts +9 -8
  137. package/dist/integrations/service.d.ts +9 -8
  138. package/dist/integrations/service.js +33 -16
  139. package/dist/integrations/service.js.map +1 -1
  140. package/dist/organizations/default-roles.d.ts +22 -0
  141. package/dist/organizations/default-roles.js +89 -0
  142. package/dist/organizations/default-roles.js.map +1 -0
  143. package/dist/organizations/effective-permissions.d.ts +45 -0
  144. package/dist/organizations/effective-permissions.js +113 -0
  145. package/dist/organizations/effective-permissions.js.map +1 -0
  146. package/dist/organizations/events.d.ts +320 -181
  147. package/dist/organizations/events.js +90 -18
  148. package/dist/organizations/events.js.map +1 -1
  149. package/dist/organizations/index.d.ts +14 -10
  150. package/dist/organizations/index.js +7 -3
  151. package/dist/organizations/members.d.ts +66 -8
  152. package/dist/organizations/members.js.map +1 -1
  153. package/dist/organizations/notification-catalog.d.ts +31 -0
  154. package/dist/organizations/notification-catalog.js +32 -0
  155. package/dist/organizations/notification-catalog.js.map +1 -0
  156. package/dist/organizations/notification-categories.d.ts +6 -4
  157. package/dist/organizations/notification-categories.js +25 -10
  158. package/dist/organizations/notification-categories.js.map +1 -1
  159. package/dist/organizations/org-roles.d.ts +33 -0
  160. package/dist/organizations/org-roles.js +49 -0
  161. package/dist/organizations/org-roles.js.map +1 -0
  162. package/dist/organizations/permissions.d.ts +311 -0
  163. package/dist/organizations/permissions.js +327 -0
  164. package/dist/organizations/permissions.js.map +1 -0
  165. package/dist/organizations/ports.d.ts +184 -65
  166. package/dist/organizations/service.d.ts +102 -35
  167. package/dist/organizations/service.js +1245 -328
  168. package/dist/organizations/service.js.map +1 -1
  169. package/dist/organizations/testing.d.ts +18 -0
  170. package/dist/organizations/testing.js +37 -0
  171. package/dist/organizations/testing.js.map +1 -0
  172. package/dist/organizations/types.d.ts +5 -16
  173. package/dist/progress/events.d.ts +14 -14
  174. package/dist/progress/index.d.ts +2 -2
  175. package/dist/progress/ports.d.ts +11 -3
  176. package/dist/progress/service.d.ts +6 -5
  177. package/dist/progress/service.js +23 -8
  178. package/dist/progress/service.js.map +1 -1
  179. package/dist/reporting/admin/index.d.ts +6 -4
  180. package/dist/reporting/admin/model.d.ts +36 -3
  181. package/dist/reporting/admin/ports.d.ts +39 -14
  182. package/dist/reporting/admin/service.d.ts +32 -11
  183. package/dist/reporting/admin/service.js +102 -18
  184. package/dist/reporting/admin/service.js.map +1 -1
  185. package/dist/reporting/events/index.d.ts +27 -0
  186. package/dist/reporting/events/index.js +20 -0
  187. package/dist/reporting/events/index.js.map +1 -0
  188. package/dist/reporting/member/calendar.d.ts +11 -0
  189. package/dist/reporting/member/calendar.js +75 -0
  190. package/dist/reporting/member/calendar.js.map +1 -0
  191. package/dist/reporting/member/index.d.ts +3 -2
  192. package/dist/reporting/member/model.d.ts +26 -5
  193. package/dist/reporting/member/ports.d.ts +48 -29
  194. package/dist/reporting/member/service.d.ts +56 -29
  195. package/dist/reporting/member/service.js +328 -113
  196. package/dist/reporting/member/service.js.map +1 -1
  197. package/dist/shared/actor.d.ts +22 -3
  198. package/dist/shared/errors.d.ts +2 -1
  199. package/dist/shared/errors.js +3 -1
  200. package/dist/shared/errors.js.map +1 -1
  201. package/dist/shared/id.d.ts +4 -0
  202. package/dist/shared/id.js +4 -0
  203. package/dist/shared/id.js.map +1 -1
  204. package/dist/shared/logger.d.ts +2 -1
  205. package/dist/shared/logger.js +10 -1
  206. package/dist/shared/logger.js.map +1 -1
  207. package/dist/shared/ports.d.ts +25 -5
  208. package/dist/types/content.d.ts +2 -2
  209. package/dist/types/discussion.d.ts +4 -5
  210. package/dist/types/email-templates.d.ts +22 -3
  211. package/dist/types/entitlements.d.ts +2 -2
  212. package/dist/types/identity.d.ts +13 -16
  213. package/dist/types/index.d.ts +9 -9
  214. package/dist/types/index.js +2 -1
  215. package/dist/types/notifications.d.ts +4 -4
  216. package/dist/types/organizations.d.ts +3 -2
  217. package/dist/types/ports.d.ts +8 -1
  218. package/dist/types/ports.js +7 -1
  219. package/dist/types/ports.js.map +1 -0
  220. package/dist/types/schemas/assets.d.ts +5 -5
  221. package/dist/types/schemas/assets.js +4 -3
  222. package/dist/types/schemas/assets.js.map +1 -1
  223. package/dist/types/schemas/content.d.ts +537 -13
  224. package/dist/types/schemas/content.js +201 -7
  225. package/dist/types/schemas/content.js.map +1 -1
  226. package/dist/types/schemas/discussion.d.ts +282 -59
  227. package/dist/types/schemas/discussion.js +77 -3
  228. package/dist/types/schemas/discussion.js.map +1 -1
  229. package/dist/types/schemas/entitlements.d.ts +14 -1
  230. package/dist/types/schemas/entitlements.js +11 -4
  231. package/dist/types/schemas/entitlements.js.map +1 -1
  232. package/dist/types/schemas/index.d.ts +5 -5
  233. package/dist/types/schemas/index.js +5 -5
  234. package/dist/types/schemas/notifications.d.ts +13 -12
  235. package/dist/types/schemas/notifications.js +3 -2
  236. package/dist/types/schemas/notifications.js.map +1 -1
  237. package/dist/types/schemas/organizations.d.ts +96 -60
  238. package/dist/types/schemas/organizations.js +78 -27
  239. package/dist/types/schemas/organizations.js.map +1 -1
  240. package/dist/types/schemas/progress.d.ts +3 -4
  241. package/dist/types/schemas/progress.js +0 -1
  242. package/dist/types/schemas/progress.js.map +1 -1
  243. package/package.json +1 -1
  244. package/dist/organizations/access-scopes.d.ts +0 -19
  245. package/dist/organizations/access-scopes.js +0 -89
  246. package/dist/organizations/access-scopes.js.map +0 -1
  247. package/dist/organizations/roles.d.ts +0 -19
  248. package/dist/organizations/roles.js +0 -82
  249. package/dist/organizations/roles.js.map +0 -1
@@ -1,46 +1,153 @@
1
- import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, CreateOrgUserInput, Invite, InviteRole, NewOrganizationInput, OrgUser, Organization, Role, UpdateOrgUserInput } from "../types/schemas/organizations.js";
1
+ import { ContentType } from "../types/schemas/content.js";
2
+ import { ApiKeySummary, ConnectedApp, CreatedApiKey } from "../types/identity.js";
3
+ import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, CreateOrgUserInput, Invite, NewOrganizationInput, OrgUser, OrgUserProfile, Organization, Permission, RoleAssignment, UpdateOrgUserInput } from "../types/schemas/organizations.js";
4
+ import "../types/index.js";
5
+ import { Actor, EffectivePermissions } from "../shared/actor.js";
2
6
  import { OutboxAppender, UnitOfWork } from "../shared/ports.js";
3
- import { Actor } from "../shared/actor.js";
4
- import "./model.js";
5
- import "./roles.js";
6
- import { Member, MemberRoleChange, MembersQuery, Page } from "./members.js";
7
- import { CreateOrganizationInput, ResendStudentInviteInput, UpdateOrganizationInput } from "./types.js";
8
7
  import { AuthHeaders } from "../identity/ports.js";
9
8
  import "../identity/index.js";
9
+ import { StoredOrgRole } from "./org-roles.js";
10
+ import { AssignmentRow } from "./effective-permissions.js";
11
+ import "./model.js";
12
+ import { AssignmentView, CreateRoleInput, InviteDetails, Member, MembersQuery, Page, RoleView, UpdateRoleInput, ViewerPermissions } from "./members.js";
13
+ import { PermissionListEntry } from "./permissions.js";
14
+ import { CreateOrganizationInput, UpdateOrganizationInput } from "./types.js";
10
15
  //#region src/organizations/ports.d.ts
16
+ interface TransferOwnershipInput {
17
+ newOwnerOrgUserId: string;
18
+ previousOwnerRoleKey?: string | undefined;
19
+ }
20
+ interface CreateApiKeyInput {
21
+ name: string;
22
+ role: string;
23
+ expiresInDays?: number | undefined;
24
+ }
25
+ interface ApiKeyRole {
26
+ key: string;
27
+ name: string;
28
+ description: string;
29
+ }
30
+ type CallerLimit = {
31
+ scopes: readonly Permission[];
32
+ } | {
33
+ roleKey: string;
34
+ };
35
+ interface PlatformOrganizationInput {
36
+ name: string;
37
+ slug: string;
38
+ keyName?: string | undefined;
39
+ }
40
+ interface PlatformOrganization {
41
+ organization: AuthOrganization;
42
+ apiKey: CreatedApiKey;
43
+ }
44
+ interface PlatformAccount {
45
+ email: string;
46
+ name: string;
47
+ }
11
48
  interface OrganizationService {
12
- createOrganization(input: CreateOrganizationInput): Promise<Organization>;
13
- updateOrganization(id: string, input: UpdateOrganizationInput): Promise<Organization>;
49
+ createOrganization(input: NewOrganizationInput, headers: AuthHeaders): Promise<AuthOrganization>;
50
+ provisionOrganization(input: CreateOrganizationInput): Promise<Organization>;
51
+ updateOrganization(input: UpdateOrganizationInput, actor: Actor): Promise<Organization>;
14
52
  deleteOrganization(id: string): Promise<Organization>;
15
53
  addOrgUser(input: AddOrgUserInput): Promise<OrgUser>;
16
- removeOrgUser(orgId: string, userId: string): Promise<OrgUser>;
17
- updateOrgUser(orgId: string, userId: string, patch: UpdateOrgUserInput): Promise<OrgUser>;
54
+ removeOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
18
55
  getByExternalId(externalId: string): Promise<Organization | null>;
56
+ getBySlug(slug: string): Promise<Organization | null>;
57
+ getById(id: string): Promise<Organization | null>;
58
+ portalIdentity(id: string): Promise<Pick<Organization, 'id' | 'name' | 'slug'>>;
19
59
  getOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
20
60
  getOrgUserById(orgId: string, id: string): Promise<OrgUser | null>;
21
61
  getOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]>;
22
62
  getOrgUsersForUser(userId: string): Promise<OrgUser[]>;
23
- getById(id: string): Promise<Organization | null>;
24
63
  orgIds(): Promise<string[]>;
25
- createInvite(actor: Actor, input: CreateInviteInput): Promise<Invite>;
64
+ actorFor(orgId: string, orgUserId: string, limit?: CallerLimit): Promise<Actor | null>;
65
+ resolveCaller(authOrgId: string, authUserId: string, limit?: CallerLimit): Promise<ResolvedCaller | null>;
66
+ systemActor(orgId: string): Actor;
67
+ permissionsOfMany(orgId: string, orgUserIds: string[]): Promise<Map<string, EffectivePermissions>>;
68
+ holders(orgId: string, permission: Permission, on?: string): Promise<string[]>;
69
+ permissionList(): PermissionListEntry[];
70
+ viewerPermissions(actor: Actor): ViewerPermissions;
71
+ auditRoleKeys(): Promise<number>;
72
+ listRoles(actor: Actor): Promise<RoleView[]>;
73
+ getRole(key: string, actor: Actor): Promise<RoleView>;
74
+ updateRole(key: string, input: UpdateRoleInput, actor: Actor): Promise<RoleView>;
75
+ createRole(input: CreateRoleInput, actor: Actor): Promise<RoleView>;
76
+ resetRole(key: string, actor: Actor): Promise<RoleView>;
77
+ deleteRole(key: string, actor: Actor): Promise<void>;
78
+ listTeam(query: MembersQuery, actor: Actor): Promise<Page<Member>>;
79
+ listAssignments(orgUserId: string, actor: Actor): Promise<AssignmentView[]>;
80
+ listAssignmentsOn(contentId: string, actor: Actor): Promise<AssignmentView[]>;
81
+ setOrgRole(orgUserId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
82
+ assignRole(orgUserId: string, contentId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
83
+ unassignRole(orgUserId: string, contentId: string, actor: Actor): Promise<AssignmentView[]>;
84
+ removePerson(orgUserId: string, actor: Actor): Promise<void>;
85
+ transferOwnership(input: TransferOwnershipInput, actor: Actor): Promise<void>;
86
+ createInvite(input: CreateInviteInput, actor: Actor, inviterUserId: string): Promise<Invite>;
87
+ resendInvite(orgUserId: string, actor: Actor, inviterUserId: string): Promise<void>;
88
+ cancelInvite(orgUserId: string, actor: Actor): Promise<void>;
26
89
  peekInvite(token: string): Promise<Invite | null>;
27
- acceptInvite(input: AcceptInviteInput): Promise<OrgUser>;
28
- deleteOrgUser(orgId: string, actor: Actor, id: string): Promise<OrgUser>;
29
- resendStudentInvite(actor: Actor, input: ResendStudentInviteInput): Promise<void>;
30
- getBySlug(slug: string): Promise<Organization | null>;
31
- listMembers(orgId: string, query: MembersQuery): Promise<Page<Member>>;
32
- updateMemberRole(ctx: MemberWriteContext, actor: Actor, id: string, role: Role): Promise<MemberRoleChange | null>;
33
- removeMember(ctx: MemberWriteContext, actor: Actor, id: string): Promise<boolean>;
34
- staffOrgUserIds(orgId: string): Promise<string[]>;
90
+ describeInvite(token: string): Promise<InviteDetails>;
91
+ acceptInvite(input: AcceptInviteInput, headers: AuthHeaders): Promise<OrgUser>;
92
+ listApiKeys(actor: Actor): Promise<ApiKeySummary[]>;
93
+ listApiKeyRoles(actor: Actor): Promise<ApiKeyRole[]>;
94
+ createApiKey(input: CreateApiKeyInput, actor: Actor): Promise<CreatedApiKey>;
95
+ deleteApiKey(keyId: string, actor: Actor): Promise<void>;
96
+ listConnectedApps(actor: Actor): Promise<ConnectedApp[]>;
97
+ revokeConnectedApp(clientId: string, actor: Actor): Promise<void>;
98
+ createPlatformOrganization(input: PlatformOrganizationInput): Promise<PlatformOrganization>;
99
+ createPlatformApiKey(orgId: string, name: string): Promise<CreatedApiKey>;
100
+ isPlatformAccount(email: string): boolean;
101
+ }
102
+ interface ActorFacts {
103
+ orgUserId: string;
104
+ status: OrgUser['status'];
105
+ assignments: AssignmentRow[];
106
+ storedRoles: StoredOrgRole[];
107
+ }
108
+ interface CallerFacts {
109
+ orgId: string;
110
+ userId: string | null;
111
+ orgUser: ActorFacts | null;
112
+ }
113
+ interface ResolvedCaller {
114
+ orgId: string;
115
+ userId: string | null;
116
+ orgUserId: string | null;
117
+ actor: Actor | null;
118
+ }
119
+ interface RolesRepository {
120
+ actorFacts(orgId: string, orgUserId: string): Promise<ActorFacts | null>;
121
+ callerFacts(authOrgId: string, authUserId: string): Promise<CallerFacts | null>;
122
+ storedRoles(orgId: string): Promise<StoredOrgRole[]>;
123
+ saveStoredRole(orgId: string, role: StoredOrgRole): Promise<void>;
124
+ deleteStoredRole(orgId: string, key: string): Promise<boolean>;
125
+ assignmentsOf(orgId: string, orgUserId: string): Promise<RoleAssignment[]>;
126
+ assignmentsOfMany(orgId: string, orgUserIds: string[]): Promise<Map<string, AssignmentRow[]>>;
127
+ assignmentsOn(orgId: string, contentId: string): Promise<RoleAssignment[]>;
128
+ holdersOf(orgId: string, roleKeys: string[], contentId?: string): Promise<string[]>;
129
+ setOrgRole(orgId: string, orgUserId: string, roleKey: string | null, assignedBy: string): Promise<void>;
130
+ setItemRole(orgId: string, orgUserId: string, contentId: string, contentType: ContentType, roleKey: string, assignedBy: string): Promise<void>;
131
+ removeItemRole(orgId: string, orgUserId: string, contentId: string): Promise<RoleAssignment | null>;
132
+ countHolders(orgId: string, roleKey: string, contentType?: ContentType | 'org'): Promise<number>;
133
+ holderCounts(orgId: string): Promise<Record<string, number>>;
134
+ contentTypeOf(orgId: string, contentId: string): Promise<ContentType | null>;
135
+ ownerOrgUserId(orgId: string): Promise<string | null>;
136
+ roleKeyUsage(): Promise<{
137
+ orgId: string;
138
+ roleKey: string;
139
+ level: string;
140
+ count: number;
141
+ stored: boolean;
142
+ }[]>;
143
+ lock(keys: string[]): Promise<void>;
35
144
  }
36
- /** Atomic write scope: tx-bound repo + outbox appender, one transaction. */
37
145
  interface OrganizationsWriteScope {
38
146
  organizations: OrganizationsRepository;
147
+ roles: RolesRepository;
39
148
  outbox: OutboxAppender;
40
149
  }
41
150
  type OrganizationsUnitOfWork = UnitOfWork<OrganizationsWriteScope>;
42
- /** Repo-facing write shape for a new org row. The service mints the id and
43
- * resolves the defaults, so nothing is optional by the time it lands here. */
44
151
  interface NewOrganizationRow {
45
152
  id: string;
46
153
  externalId?: string | null;
@@ -48,10 +155,9 @@ interface NewOrganizationRow {
48
155
  slug: string;
49
156
  ownerId: string;
50
157
  }
51
- /** Repo-facing write shape for a freshly minted invite. */
52
158
  interface NewInviteRow {
53
159
  email: string;
54
- role: InviteRole;
160
+ roleKey: string;
55
161
  invitedBy: string;
56
162
  tokenHash: string;
57
163
  expiresAt: Date;
@@ -59,71 +165,84 @@ interface NewInviteRow {
59
165
  interface OrganizationsRepository {
60
166
  create(input: NewOrganizationRow): Promise<Organization>;
61
167
  update(id: string, input: UpdateOrganizationInput): Promise<Organization | null>;
62
- /** Drops the org row and its dependents; null when none matched. */
63
168
  delete(id: string): Promise<Organization>;
64
169
  findById(id: string): Promise<Organization | null>;
65
170
  listIds(): Promise<string[]>;
66
171
  findByExternalId(externalId: string): Promise<Organization | null>;
67
172
  findBySlug(slug: string): Promise<Organization | null>;
68
- /** Inserts a pending invite, or re-issues the org's existing pending one
69
- * for this email (fresh token/expiry/role) — atomic upsert. */
70
173
  upsertPendingInvite(orgId: string, input: NewInviteRow): Promise<Invite>;
71
174
  setInviteStatus(orgId: string, id: string, status: string): Promise<Invite | null>;
175
+ setInviteRole(orgId: string, id: string, roleKey: string, invitedBy: string): Promise<Invite | null>;
72
176
  findInviteByTokenHash(tokenHash: string): Promise<Invite | null>;
73
177
  findPendingInvite(orgId: string, email: string): Promise<Invite | null>;
74
- setInviteToken(orgId: string, id: string, tokenHash: string, expiresAt: Date): Promise<Invite | null>;
75
- /** The person's row in one org. `(org_id, user_id)` is unique. */
178
+ setInviteToken(orgId: string, id: string, tokenHash: string, expiresAt: Date, invitedBy: string): Promise<Invite | null>;
76
179
  findOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
77
- /** Every org this person belongs to, oldest first. */
78
180
  findOrgUsersByUser(userId: string): Promise<OrgUser[]>;
79
181
  findOrgUserById(orgId: string, id: string): Promise<OrgUser | null>;
80
182
  findOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]>;
81
- findOrgUserIdsByRole(orgId: string, roles: Role[]): Promise<string[]>;
82
- /** Links a user to the org under a role. Throws ConflictError when they
83
- * already hold a row there. */
84
183
  createOrgUser(input: CreateOrgUserInput): Promise<OrgUser>;
85
184
  updateOrgUser(orgId: string, id: string, patch: UpdateOrgUserInput): Promise<OrgUser | null>;
86
- /** Every org this person is a student in — the scope of `student.linked`. */
87
- findStudentOrgUsers(userId: string): Promise<OrgUser[]>;
88
- /** Kills the org's pending invite for an address, if any. */
89
185
  deleteOrgUser(orgId: string, id: string): Promise<OrgUser | null>;
90
186
  }
91
- /** A member row enriched with the ids needed to drive writes. */
92
- interface MemberRecord extends Member {
93
- kind: 'member' | 'invite';
94
- userExternalId: string | null;
95
- inviteId: string | null;
96
- }
97
- interface MembersRepository {
98
- list(orgId: string, query: MembersQuery): Promise<Page<Member>>;
99
- findByEmail(orgId: string, email: string): Promise<MemberRecord | null>;
100
- findById(orgId: string, id: string): Promise<MemberRecord | null>;
187
+ interface GrantReader {
188
+ holdsAnyGrant(orgId: string, orgUserId: string): Promise<boolean>;
101
189
  }
102
- /** The person as this context reads them back after a correction. */
103
- interface PersonRecord {
104
- id: string;
105
- email: string;
106
- firstName: string | null;
107
- lastName: string | null;
190
+ interface TeamRow extends OrgUserProfile {
191
+ status: OrgUser['status'];
192
+ joinedAt: Date;
193
+ invitedAt: Date | null;
194
+ orgRoleKey: string | null;
195
+ inviteRoleKey: string | null;
196
+ items: {
197
+ contentId: string;
198
+ contentType: ContentType;
199
+ roleKey: string;
200
+ }[];
108
201
  }
109
- /** Context for a write: domain org (reads/rules) + auth org & session (writes). */
110
- interface MemberWriteContext {
111
- orgId: string;
112
- authOrgId: string;
113
- headers: Record<string, string | string[] | undefined>;
202
+ interface MembersRepository {
203
+ teamRows(orgId: string, memberRoleKey: string): Promise<TeamRow[]>;
114
204
  }
115
- /** The provider's view of an org: what it stores itself, minus the fields only
116
- * the domain row carries (`ownerId`, `externalId`, `updatedAt`). */
117
205
  type AuthOrganization = Pick<Organization, 'id' | 'name' | 'slug' | 'createdAt'>;
118
206
  interface OrgAdmin {
119
207
  createOrganization(headers: AuthHeaders, input: NewOrganizationInput): Promise<AuthOrganization>;
208
+ createOrganizationFor(ownerExternalId: string, input: NewOrganizationInput): Promise<AuthOrganization>;
120
209
  setActiveOrganization(headers: AuthHeaders, externalId: string): Promise<void>;
121
- updateOrganization(headers: AuthHeaders, id: string, input: UpdateOrganizationInput): Promise<AuthOrganization>;
122
210
  deleteOrganization(headers: AuthHeaders, externalId: string): Promise<void>;
123
- grantMembership(orgExternalId: string, userExternalId: string, role: string): Promise<void>;
124
- updateRole(ctx: MemberWriteContext, userExternalId: string, role: Role): Promise<void>;
125
- removeMember(ctx: MemberWriteContext, userExternalId: string): Promise<void>;
211
+ updateOrganization(externalId: string, input: UpdateOrganizationInput): Promise<void>;
212
+ grantMembership(orgExternalId: string, userExternalId: string): Promise<void>;
213
+ setMembershipOwner(orgExternalId: string, userExternalId: string, owner: boolean): Promise<void>;
214
+ removeMembership(orgExternalId: string, userExternalId: string): Promise<void>;
215
+ }
216
+ interface Accounts {
217
+ createAccount(input: PlatformAccount): Promise<{
218
+ externalId: string;
219
+ }>;
220
+ }
221
+ interface StoredApiKey {
222
+ id: string;
223
+ name: string | null;
224
+ start: string | null;
225
+ roleKey: string | null;
226
+ createdAt: Date;
227
+ lastUsedAt: Date | null;
228
+ expiresAt: Date | null;
229
+ }
230
+ interface NewApiKey {
231
+ name: string;
232
+ roleKey: string;
233
+ expiresInDays?: number | undefined;
234
+ }
235
+ interface ApiKeys {
236
+ list(orgId: string, userExternalId: string): Promise<StoredApiKey[]>;
237
+ create(orgId: string, userExternalId: string, input: NewApiKey): Promise<StoredApiKey & {
238
+ key: string;
239
+ }>;
240
+ countWithRole(orgId: string, roleKey: string): Promise<number>;
241
+ revoke(orgId: string, userExternalId: string, keyId: string): Promise<void>;
242
+ listApps(orgId: string, userExternalId: string): Promise<ConnectedApp[]>;
243
+ revokeApp(orgId: string, userExternalId: string, clientId: string): Promise<void>;
244
+ revokeAllFor(orgId: string, userExternalId: string): Promise<void>;
126
245
  }
127
246
  //#endregion
128
- export { type AuthHeaders, AuthOrganization, MemberRecord, MemberWriteContext, MembersRepository, NewInviteRow, NewOrganizationRow, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork, OrganizationsWriteScope, PersonRecord };
247
+ export { Accounts, ActorFacts, ApiKeyRole, ApiKeys, type AuthHeaders, AuthOrganization, CallerFacts, CallerLimit, CreateApiKeyInput, GrantReader, MembersRepository, NewApiKey, NewInviteRow, NewOrganizationRow, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork, OrganizationsWriteScope, PlatformAccount, PlatformOrganization, PlatformOrganizationInput, ResolvedCaller, RolesRepository, StoredApiKey, TeamRow, TransferOwnershipInput };
129
248
  //# sourceMappingURL=ports.d.ts.map
@@ -1,15 +1,20 @@
1
1
  import { Logger } from "../types/ports.js";
2
- import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, Invite, OrgUser, Organization, Role, UpdateOrgUserInput } from "../types/schemas/organizations.js";
2
+ import { ApiKeySummary, ConnectedApp, CreatedApiKey } from "../types/identity.js";
3
+ import { AcceptInviteInput, AddOrgUserInput, CreateInviteInput, Invite, NewOrganizationInput, OrgUser, Organization, Permission } from "../types/schemas/organizations.js";
4
+ import "../types/index.js";
5
+ import { Actor, EffectivePermissions } from "../shared/actor.js";
3
6
  import "../shared/ports.js";
4
- import { Actor } from "../shared/actor.js";
5
- import "./model.js";
6
- import "./roles.js";
7
- import { Member, MemberRoleChange, MembersQuery, Page } from "./members.js";
8
- import { CreateOrganizationInput, ResendStudentInviteInput, UpdateOrganizationInput } from "./types.js";
9
- import { IdentityService } from "../identity/ports.js";
7
+ import { AssetFiles } from "../assets/ports.js";
8
+ import "../assets/index.js";
10
9
  import { Mailer } from "../shared/mailer.js";
10
+ import { AuthHeaders, IdentityService, SessionAdmin } from "../identity/ports.js";
11
11
  import "../identity/index.js";
12
- import { MemberWriteContext, MembersRepository, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork } from "./ports.js";
12
+ import { RoleDefinition } from "./default-roles.js";
13
+ import "./model.js";
14
+ import { AssignmentView, CreateRoleInput, InviteDetails, Member, MembersQuery, Page, RoleView, UpdateRoleInput, ViewerPermissions } from "./members.js";
15
+ import { PermissionListEntry } from "./permissions.js";
16
+ import { CreateOrganizationInput, UpdateOrganizationInput } from "./types.js";
17
+ import { Accounts, ApiKeyRole, ApiKeys, AuthOrganization, CallerLimit, CreateApiKeyInput, GrantReader, MembersRepository, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork, PlatformAccount, PlatformOrganization, PlatformOrganizationInput, ResolvedCaller, RolesRepository, TransferOwnershipInput } from "./ports.js";
13
18
  //#region src/organizations/service.d.ts
14
19
  interface InviteUrls {
15
20
  studentPortalUrl: string;
@@ -17,57 +22,119 @@ interface InviteUrls {
17
22
  }
18
23
  type OrganizationServiceParams = {
19
24
  repo: OrganizationsRepository;
25
+ roles: RolesRepository;
20
26
  membersRepo: MembersRepository;
21
27
  people: IdentityService;
28
+ images: Pick<AssetFiles, 'syncPublicImage'>;
22
29
  uow: OrganizationsUnitOfWork;
23
30
  orgAdmin: () => OrgAdmin;
31
+ sessions: () => SessionAdmin;
32
+ apiKeys?: () => ApiKeys;
33
+ accounts?: () => Accounts;
34
+ platform?: PlatformAccount;
35
+ grants?: () => GrantReader;
36
+ defaultRoles?: readonly RoleDefinition[];
24
37
  logger?: Logger;
25
38
  mailer?: Pick<Mailer, 'send'>;
26
39
  inviteUrls?: InviteUrls;
27
40
  };
28
41
  declare class OrganizationServiceImpl implements OrganizationService {
29
42
  private readonly repo;
43
+ private readonly roles;
30
44
  private readonly membersRepo;
31
45
  private readonly people;
46
+ private readonly images;
32
47
  private readonly uow;
33
48
  private readonly orgAdmin;
49
+ private readonly sessions;
50
+ private readonly apiKeysPort?;
51
+ private readonly accountsPort?;
52
+ private readonly platform?;
53
+ private readonly grants?;
54
+ private readonly catalog;
34
55
  private readonly logger;
35
56
  private readonly mailer?;
36
57
  private readonly inviteUrls?;
37
- private readonly memberWrites;
38
58
  constructor(params: OrganizationServiceParams);
39
- createOrganization(input: CreateOrganizationInput): Promise<Organization>;
40
- updateOrganization(id: string, input: UpdateOrganizationInput): Promise<Organization>;
59
+ createOrganization(input: NewOrganizationInput, headers: AuthHeaders): Promise<AuthOrganization>;
60
+ provisionOrganization(input: CreateOrganizationInput): Promise<Organization>;
61
+ updateOrganization(input: UpdateOrganizationInput, actor: Actor): Promise<Organization>;
41
62
  deleteOrganization(id: string): Promise<Organization>;
42
- addOrgUser({ orgId, userId, role }: AddOrgUserInput): Promise<OrgUser>;
43
- removeOrgUser(orgId: string, userId: string): Promise<OrgUser>;
44
- updateOrgUser(orgId: string, userId: string, patch: UpdateOrgUserInput): Promise<OrgUser>;
45
- createInvite(actor: Actor, input: CreateInviteInput): Promise<Invite>;
46
- resendStudentInvite(actor: Actor, input: ResendStudentInviteInput): Promise<void>;
47
- peekInvite(token: string): Promise<Invite | null>;
48
- acceptInvite(input: AcceptInviteInput): Promise<OrgUser>;
49
- private acceptStudentInvite;
50
- private acceptStaffInvite;
63
+ addOrgUser({ orgId, userId }: AddOrgUserInput): Promise<OrgUser>;
64
+ removeOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
65
+ getByExternalId(externalId: string): Promise<Organization | null>;
66
+ getBySlug(slug: string): Promise<Organization | null>;
67
+ getById(id: string): Promise<Organization | null>;
68
+ portalIdentity(id: string): Promise<Pick<Organization, 'id' | 'name' | 'slug'>>;
69
+ getOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
51
70
  getOrgUserById(orgId: string, id: string): Promise<OrgUser | null>;
52
71
  getOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]>;
53
- getOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
54
- deleteOrgUser(orgId: string, actor: Actor, id: string): Promise<OrgUser>;
55
72
  getOrgUsersForUser(userId: string): Promise<OrgUser[]>;
56
- getById(id: string): Promise<Organization | null>;
57
73
  orgIds(): Promise<string[]>;
74
+ actorFor(orgId: string, orgUserId: string, limit?: CallerLimit): Promise<Actor | null>;
75
+ resolveCaller(authOrgId: string, authUserId: string, limit?: CallerLimit): Promise<ResolvedCaller | null>;
76
+ systemActor(orgId: string): Actor;
77
+ permissionsOfMany(orgId: string, orgUserIds: string[]): Promise<Map<string, EffectivePermissions>>;
78
+ holders(orgId: string, permission: Permission, on?: string): Promise<string[]>;
79
+ permissionList(): PermissionListEntry[];
80
+ viewerPermissions(actor: Actor): ViewerPermissions;
81
+ auditRoleKeys(): Promise<number>;
82
+ listRoles(actor: Actor): Promise<RoleView[]>;
83
+ getRole(key: string, actor: Actor): Promise<RoleView>;
84
+ updateRole(key: string, input: UpdateRoleInput, actor: Actor): Promise<RoleView>;
85
+ createRole(input: CreateRoleInput, actor: Actor): Promise<RoleView>;
86
+ resetRole(key: string, actor: Actor): Promise<RoleView>;
87
+ deleteRole(key: string, actor: Actor): Promise<void>;
88
+ listTeam(query: MembersQuery, actor: Actor): Promise<Page<Member>>;
89
+ listAssignments(orgUserId: string, actor: Actor): Promise<AssignmentView[]>;
90
+ listAssignmentsOn(contentId: string, actor: Actor): Promise<AssignmentView[]>;
91
+ setOrgRole(orgUserId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
92
+ assignRole(orgUserId: string, contentId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
93
+ unassignRole(orgUserId: string, contentId: string, actor: Actor): Promise<AssignmentView[]>;
94
+ removePerson(orgUserId: string, actor: Actor): Promise<void>;
95
+ transferOwnership(input: TransferOwnershipInput, actor: Actor): Promise<void>;
96
+ createInvite(input: CreateInviteInput, actor: Actor, inviterUserId: string): Promise<Invite>;
97
+ resendInvite(orgUserId: string, actor: Actor, inviterUserId: string): Promise<void>;
98
+ cancelInvite(orgUserId: string, actor: Actor): Promise<void>;
99
+ peekInvite(token: string): Promise<Invite | null>;
100
+ describeInvite(token: string): Promise<InviteDetails>;
101
+ acceptInvite(input: AcceptInviteInput, headers: AuthHeaders): Promise<OrgUser>;
102
+ private checkAcceptance;
103
+ listApiKeys(actor: Actor): Promise<ApiKeySummary[]>;
104
+ listApiKeyRoles(actor: Actor): Promise<ApiKeyRole[]>;
105
+ createApiKey(input: CreateApiKeyInput, actor: Actor): Promise<CreatedApiKey>;
106
+ deleteApiKey(keyId: string, actor: Actor): Promise<void>;
107
+ listConnectedApps(actor: Actor): Promise<ConnectedApp[]>;
108
+ revokeConnectedApp(clientId: string, actor: Actor): Promise<void>;
109
+ createPlatformOrganization(input: PlatformOrganizationInput): Promise<PlatformOrganization>;
110
+ createPlatformApiKey(orgId: string, name: string): Promise<CreatedApiKey>;
111
+ isPlatformAccount(email: string): boolean;
112
+ private platformKey;
113
+ private platformAccountId;
114
+ private platformAccount;
115
+ private accounts;
116
+ private keysWithRole;
117
+ private cleanUpAfterRemoval;
118
+ private apiKeys;
119
+ private externalIdsOf;
120
+ private pendingInviteOf;
121
+ private deleteOrgUserRow;
122
+ private deleteOrgUserIn;
58
123
  private sendInviteEmail;
59
- getByExternalId(externalId: string): Promise<Organization | null>;
60
- getBySlug(slug: string): Promise<Organization | null>;
61
- staffOrgUserIds(orgId: string): Promise<string[]>;
62
- listMembers(orgId: string, query: MembersQuery): Promise<Page<Member>>;
63
- updateMemberRole(ctx: MemberWriteContext, actor: Actor, id: string, role: Role): Promise<MemberRoleChange | null>;
64
- private demoteModerator;
65
- private promoteStudent;
66
- private asActor;
67
- private memberWrite;
68
- private assertManagesUsers;
69
- private assertNotOwner;
70
- removeMember(ctx: MemberWriteContext, actor: Actor, id: string): Promise<boolean>;
124
+ private toMember;
125
+ private assignmentViews;
126
+ private roleMap;
127
+ private resolveIn;
128
+ private findRole;
129
+ private relockedActor;
130
+ private itemPermissions;
131
+ private assertHolds;
132
+ private assertHoldsOn;
133
+ private assertNotSelf;
134
+ private assertUniqueName;
135
+ private parseLevels;
136
+ private assertFits;
137
+ private assertLevelsNotInUse;
71
138
  }
72
139
  //#endregion
73
140
  export { InviteUrls, OrganizationServiceImpl, OrganizationServiceParams };