@headless-lms/core 0.4.0 → 0.6.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 +15 -9
  2. package/dist/assets/file-urls.d.ts +14 -7
  3. package/dist/assets/file-urls.js +15 -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 +233 -54
  10. package/dist/assets/service.js.map +1 -1
  11. package/dist/automations/actions.js.map +1 -1
  12. package/dist/automations/catalog.js +68 -3
  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 +1 -1
  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 +12 -12
  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 +90 -61
  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 +465 -88
  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 +103 -67
  72. package/dist/content/service.js +739 -152
  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 +392 -160
  83. package/dist/discussion/chats.js.map +1 -1
  84. package/dist/discussion/events.d.ts +85 -47
  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 +266 -152
  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 +250 -186
  104. package/dist/discussion/service.js.map +1 -1
  105. package/dist/discussion/subscriptions.d.ts +8 -8
  106. package/dist/discussion/subscriptions.js +28 -12
  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 +58 -58
  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 +369 -162
  121. package/dist/entitlements/service.js.map +1 -1
  122. package/dist/identity/devices.d.ts +3 -3
  123. package/dist/identity/devices.js +6 -4
  124. package/dist/identity/devices.js.map +1 -1
  125. package/dist/identity/index.d.ts +2 -2
  126. package/dist/identity/index.js +2 -2
  127. package/dist/identity/notification-settings.d.ts +1 -1
  128. package/dist/identity/notification-settings.js +2 -1
  129. package/dist/identity/notification-settings.js.map +1 -1
  130. package/dist/identity/ports.d.ts +7 -7
  131. package/dist/identity/service.d.ts +8 -7
  132. package/dist/identity/service.js +16 -12
  133. package/dist/identity/service.js.map +1 -1
  134. package/dist/integrations/events.d.ts +3 -3
  135. package/dist/integrations/ports.d.ts +9 -8
  136. package/dist/integrations/service.d.ts +9 -8
  137. package/dist/integrations/service.js +31 -14
  138. package/dist/integrations/service.js.map +1 -1
  139. package/dist/organizations/default-roles.d.ts +22 -0
  140. package/dist/organizations/default-roles.js +89 -0
  141. package/dist/organizations/default-roles.js.map +1 -0
  142. package/dist/organizations/effective-permissions.d.ts +47 -0
  143. package/dist/organizations/effective-permissions.js +118 -0
  144. package/dist/organizations/effective-permissions.js.map +1 -0
  145. package/dist/organizations/events.d.ts +326 -181
  146. package/dist/organizations/events.js +90 -18
  147. package/dist/organizations/events.js.map +1 -1
  148. package/dist/organizations/index.d.ts +14 -10
  149. package/dist/organizations/index.js +7 -3
  150. package/dist/organizations/members.d.ts +66 -8
  151. package/dist/organizations/members.js.map +1 -1
  152. package/dist/organizations/model.d.ts +2 -2
  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 +187 -65
  166. package/dist/organizations/service.d.ts +102 -35
  167. package/dist/organizations/service.js +1254 -327
  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 +21 -6
  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 +29 -5
  193. package/dist/reporting/member/ports.d.ts +49 -29
  194. package/dist/reporting/member/service.d.ts +57 -29
  195. package/dist/reporting/member/service.js +345 -114
  196. package/dist/reporting/member/service.js.map +1 -1
  197. package/dist/shared/actor.d.ts +23 -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 +599 -13
  224. package/dist/types/schemas/content.js +219 -8
  225. package/dist/types/schemas/content.js.map +1 -1
  226. package/dist/types/schemas/discussion.d.ts +280 -57
  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 +21 -8
  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 +11 -10
  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 +99 -60
  238. package/dist/types/schemas/organizations.js +80 -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,155 @@
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, OrganizationMetadata, 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
+ metadata?: OrganizationMetadata | undefined;
39
+ }
40
+ interface PlatformOrganization {
41
+ organization: AuthOrganization & {
42
+ metadata: OrganizationMetadata;
43
+ };
44
+ apiKey: CreatedApiKey;
45
+ }
46
+ interface PlatformAccount {
47
+ email: string;
48
+ name: string;
49
+ }
11
50
  interface OrganizationService {
12
- createOrganization(input: CreateOrganizationInput): Promise<Organization>;
13
- updateOrganization(id: string, input: UpdateOrganizationInput): Promise<Organization>;
51
+ createOrganization(input: NewOrganizationInput, headers: AuthHeaders): Promise<AuthOrganization>;
52
+ provisionOrganization(input: CreateOrganizationInput): Promise<Organization>;
53
+ updateOrganization(input: UpdateOrganizationInput, actor: Actor): Promise<Organization>;
14
54
  deleteOrganization(id: string): Promise<Organization>;
15
55
  addOrgUser(input: AddOrgUserInput): Promise<OrgUser>;
16
- removeOrgUser(orgId: string, userId: string): Promise<OrgUser>;
17
- updateOrgUser(orgId: string, userId: string, patch: UpdateOrgUserInput): Promise<OrgUser>;
56
+ removeOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
18
57
  getByExternalId(externalId: string): Promise<Organization | null>;
58
+ getBySlug(slug: string): Promise<Organization | null>;
59
+ getById(id: string): Promise<Organization | null>;
60
+ portalIdentity(id: string): Promise<Pick<Organization, 'id' | 'name' | 'slug'>>;
19
61
  getOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
20
62
  getOrgUserById(orgId: string, id: string): Promise<OrgUser | null>;
21
63
  getOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]>;
22
64
  getOrgUsersForUser(userId: string): Promise<OrgUser[]>;
23
- getById(id: string): Promise<Organization | null>;
24
65
  orgIds(): Promise<string[]>;
25
- createInvite(actor: Actor, input: CreateInviteInput): Promise<Invite>;
66
+ actorFor(orgId: string, orgUserId: string, limit?: CallerLimit): Promise<Actor | null>;
67
+ resolveCaller(authOrgId: string, authUserId: string, limit?: CallerLimit): Promise<ResolvedCaller | null>;
68
+ systemActor(orgId: string): Actor;
69
+ permissionsOfMany(orgId: string, orgUserIds: string[]): Promise<Map<string, EffectivePermissions>>;
70
+ holders(orgId: string, permission: Permission, on?: string): Promise<string[]>;
71
+ permissionList(): PermissionListEntry[];
72
+ viewerPermissions(actor: Actor): ViewerPermissions;
73
+ auditRoleKeys(): Promise<number>;
74
+ listRoles(actor: Actor): Promise<RoleView[]>;
75
+ getRole(key: string, actor: Actor): Promise<RoleView>;
76
+ updateRole(key: string, input: UpdateRoleInput, actor: Actor): Promise<RoleView>;
77
+ createRole(input: CreateRoleInput, actor: Actor): Promise<RoleView>;
78
+ resetRole(key: string, actor: Actor): Promise<RoleView>;
79
+ deleteRole(key: string, actor: Actor): Promise<void>;
80
+ listTeam(query: MembersQuery, actor: Actor): Promise<Page<Member>>;
81
+ listAssignments(orgUserId: string, actor: Actor): Promise<AssignmentView[]>;
82
+ listAssignmentsOn(contentId: string, actor: Actor): Promise<AssignmentView[]>;
83
+ setOrgRole(orgUserId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
84
+ assignRole(orgUserId: string, contentId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]>;
85
+ unassignRole(orgUserId: string, contentId: string, actor: Actor): Promise<AssignmentView[]>;
86
+ removePerson(orgUserId: string, actor: Actor): Promise<void>;
87
+ transferOwnership(input: TransferOwnershipInput, actor: Actor): Promise<void>;
88
+ createInvite(input: CreateInviteInput, actor: Actor, inviterUserId: string): Promise<Invite>;
89
+ resendInvite(orgUserId: string, actor: Actor, inviterUserId: string): Promise<void>;
90
+ cancelInvite(orgUserId: string, actor: Actor): Promise<void>;
26
91
  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[]>;
92
+ describeInvite(token: string): Promise<InviteDetails>;
93
+ acceptInvite(input: AcceptInviteInput, headers: AuthHeaders): Promise<OrgUser>;
94
+ listApiKeys(actor: Actor): Promise<ApiKeySummary[]>;
95
+ listApiKeyRoles(actor: Actor): Promise<ApiKeyRole[]>;
96
+ createApiKey(input: CreateApiKeyInput, actor: Actor): Promise<CreatedApiKey>;
97
+ deleteApiKey(keyId: string, actor: Actor): Promise<void>;
98
+ listConnectedApps(actor: Actor): Promise<ConnectedApp[]>;
99
+ revokeConnectedApp(clientId: string, actor: Actor): Promise<void>;
100
+ createPlatformOrganization(input: PlatformOrganizationInput): Promise<PlatformOrganization>;
101
+ createPlatformApiKey(orgId: string, name: string): Promise<CreatedApiKey>;
102
+ isPlatformAccount(email: string): boolean;
103
+ }
104
+ interface ActorFacts {
105
+ orgUserId: string;
106
+ status: OrgUser['status'];
107
+ assignments: AssignmentRow[];
108
+ storedRoles: StoredOrgRole[];
109
+ }
110
+ interface CallerFacts {
111
+ orgId: string;
112
+ userId: string | null;
113
+ orgUser: ActorFacts | null;
114
+ }
115
+ interface ResolvedCaller {
116
+ orgId: string;
117
+ userId: string | null;
118
+ orgUserId: string | null;
119
+ actor: Actor | null;
120
+ }
121
+ interface RolesRepository {
122
+ actorFacts(orgId: string, orgUserId: string): Promise<ActorFacts | null>;
123
+ callerFacts(authOrgId: string, authUserId: string): Promise<CallerFacts | null>;
124
+ storedRoles(orgId: string): Promise<StoredOrgRole[]>;
125
+ saveStoredRole(orgId: string, role: StoredOrgRole): Promise<void>;
126
+ deleteStoredRole(orgId: string, key: string): Promise<boolean>;
127
+ assignmentsOf(orgId: string, orgUserId: string): Promise<RoleAssignment[]>;
128
+ assignmentsOfMany(orgId: string, orgUserIds: string[]): Promise<Map<string, AssignmentRow[]>>;
129
+ assignmentsOn(orgId: string, contentId: string): Promise<RoleAssignment[]>;
130
+ holdersOf(orgId: string, roleKeys: string[], contentId?: string): Promise<string[]>;
131
+ setOrgRole(orgId: string, orgUserId: string, roleKey: string | null, assignedBy: string): Promise<void>;
132
+ setItemRole(orgId: string, orgUserId: string, contentId: string, contentType: ContentType, roleKey: string, assignedBy: string): Promise<void>;
133
+ removeItemRole(orgId: string, orgUserId: string, contentId: string): Promise<RoleAssignment | null>;
134
+ countHolders(orgId: string, roleKey: string, contentType?: ContentType | 'org'): Promise<number>;
135
+ holderCounts(orgId: string): Promise<Record<string, number>>;
136
+ contentTypeOf(orgId: string, contentId: string): Promise<ContentType | null>;
137
+ ownerOrgUserId(orgId: string): Promise<string | null>;
138
+ roleKeyUsage(): Promise<{
139
+ orgId: string;
140
+ roleKey: string;
141
+ level: string;
142
+ count: number;
143
+ stored: boolean;
144
+ }[]>;
145
+ lock(keys: string[]): Promise<void>;
35
146
  }
36
- /** Atomic write scope: tx-bound repo + outbox appender, one transaction. */
37
147
  interface OrganizationsWriteScope {
38
148
  organizations: OrganizationsRepository;
149
+ roles: RolesRepository;
39
150
  outbox: OutboxAppender;
40
151
  }
41
152
  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
153
  interface NewOrganizationRow {
45
154
  id: string;
46
155
  externalId?: string | null;
@@ -48,10 +157,9 @@ interface NewOrganizationRow {
48
157
  slug: string;
49
158
  ownerId: string;
50
159
  }
51
- /** Repo-facing write shape for a freshly minted invite. */
52
160
  interface NewInviteRow {
53
161
  email: string;
54
- role: InviteRole;
162
+ roleKey: string;
55
163
  invitedBy: string;
56
164
  tokenHash: string;
57
165
  expiresAt: Date;
@@ -59,71 +167,85 @@ interface NewInviteRow {
59
167
  interface OrganizationsRepository {
60
168
  create(input: NewOrganizationRow): Promise<Organization>;
61
169
  update(id: string, input: UpdateOrganizationInput): Promise<Organization | null>;
62
- /** Drops the org row and its dependents; null when none matched. */
63
170
  delete(id: string): Promise<Organization>;
64
171
  findById(id: string): Promise<Organization | null>;
65
172
  listIds(): Promise<string[]>;
66
173
  findByExternalId(externalId: string): Promise<Organization | null>;
67
174
  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. */
175
+ setMetadata(id: string, metadata: OrganizationMetadata): Promise<Organization>;
70
176
  upsertPendingInvite(orgId: string, input: NewInviteRow): Promise<Invite>;
71
177
  setInviteStatus(orgId: string, id: string, status: string): Promise<Invite | null>;
178
+ setInviteRole(orgId: string, id: string, roleKey: string, invitedBy: string): Promise<Invite | null>;
72
179
  findInviteByTokenHash(tokenHash: string): Promise<Invite | null>;
73
180
  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. */
181
+ setInviteToken(orgId: string, id: string, tokenHash: string, expiresAt: Date, invitedBy: string): Promise<Invite | null>;
76
182
  findOrgUser(orgId: string, userId: string): Promise<OrgUser | null>;
77
- /** Every org this person belongs to, oldest first. */
78
183
  findOrgUsersByUser(userId: string): Promise<OrgUser[]>;
79
184
  findOrgUserById(orgId: string, id: string): Promise<OrgUser | null>;
80
185
  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
186
  createOrgUser(input: CreateOrgUserInput): Promise<OrgUser>;
85
187
  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
188
  deleteOrgUser(orgId: string, id: string): Promise<OrgUser | null>;
90
189
  }
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>;
190
+ interface GrantReader {
191
+ holdsAnyGrant(orgId: string, orgUserId: string): Promise<boolean>;
101
192
  }
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;
193
+ interface TeamRow extends OrgUserProfile {
194
+ status: OrgUser['status'];
195
+ joinedAt: Date;
196
+ invitedAt: Date | null;
197
+ orgRoleKey: string | null;
198
+ inviteRoleKey: string | null;
199
+ items: {
200
+ contentId: string;
201
+ contentType: ContentType;
202
+ roleKey: string;
203
+ }[];
108
204
  }
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>;
205
+ interface MembersRepository {
206
+ teamRows(orgId: string, memberRoleKey: string): Promise<TeamRow[]>;
114
207
  }
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
208
  type AuthOrganization = Pick<Organization, 'id' | 'name' | 'slug' | 'createdAt'>;
118
209
  interface OrgAdmin {
119
210
  createOrganization(headers: AuthHeaders, input: NewOrganizationInput): Promise<AuthOrganization>;
211
+ createOrganizationFor(ownerExternalId: string, input: NewOrganizationInput): Promise<AuthOrganization>;
120
212
  setActiveOrganization(headers: AuthHeaders, externalId: string): Promise<void>;
121
- updateOrganization(headers: AuthHeaders, id: string, input: UpdateOrganizationInput): Promise<AuthOrganization>;
122
213
  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>;
214
+ updateOrganization(externalId: string, input: UpdateOrganizationInput): Promise<void>;
215
+ grantMembership(orgExternalId: string, userExternalId: string): Promise<void>;
216
+ setMembershipOwner(orgExternalId: string, userExternalId: string, owner: boolean): Promise<void>;
217
+ removeMembership(orgExternalId: string, userExternalId: string): Promise<void>;
218
+ }
219
+ interface Accounts {
220
+ createAccount(input: PlatformAccount): Promise<{
221
+ externalId: string;
222
+ }>;
223
+ }
224
+ interface StoredApiKey {
225
+ id: string;
226
+ name: string | null;
227
+ start: string | null;
228
+ roleKey: string | null;
229
+ createdAt: Date;
230
+ lastUsedAt: Date | null;
231
+ expiresAt: Date | null;
232
+ }
233
+ interface NewApiKey {
234
+ name: string;
235
+ roleKey: string;
236
+ expiresInDays?: number | undefined;
237
+ }
238
+ interface ApiKeys {
239
+ list(orgId: string, userExternalId: string): Promise<StoredApiKey[]>;
240
+ create(orgId: string, userExternalId: string, input: NewApiKey): Promise<StoredApiKey & {
241
+ key: string;
242
+ }>;
243
+ countWithRole(orgId: string, roleKey: string): Promise<number>;
244
+ revoke(orgId: string, userExternalId: string, keyId: string): Promise<void>;
245
+ listApps(orgId: string, userExternalId: string): Promise<ConnectedApp[]>;
246
+ revokeApp(orgId: string, userExternalId: string, clientId: string): Promise<void>;
247
+ revokeAllFor(orgId: string, userExternalId: string): Promise<void>;
126
248
  }
127
249
  //#endregion
128
- export { type AuthHeaders, AuthOrganization, MemberRecord, MemberWriteContext, MembersRepository, NewInviteRow, NewOrganizationRow, OrgAdmin, OrganizationService, OrganizationsRepository, OrganizationsUnitOfWork, OrganizationsWriteScope, PersonRecord };
250
+ 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
251
  //# 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, 'syncPublicImages'>;
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 };