@headless-lms/core 0.5.0 → 0.7.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.
- package/dist/assets/events.d.ts +18 -18
- package/dist/assets/file-urls.d.ts +3 -0
- package/dist/assets/file-urls.js +1 -0
- package/dist/assets/file-urls.js.map +1 -1
- package/dist/assets/index.js +1 -1
- package/dist/assets/ports.d.ts +1 -1
- package/dist/assets/service.d.ts +1 -1
- package/dist/assets/service.js +28 -23
- package/dist/assets/service.js.map +1 -1
- package/dist/automations/catalog.js +1 -1
- package/dist/automations/index.d.ts +4 -4
- package/dist/automations/notifications/delivery.d.ts +3 -3
- package/dist/automations/notifications/delivery.js +1 -1
- package/dist/automations/notifications/delivery.js.map +1 -1
- package/dist/automations/notifications/processor.js +2 -2
- package/dist/automations/notifications/service.js +1 -1
- package/dist/automations/ports.d.ts +2 -2
- package/dist/automations/service.d.ts +1 -8
- package/dist/automations/service.js +1 -9
- package/dist/automations/service.js.map +1 -1
- package/dist/content/events.d.ts +97 -61
- package/dist/content/index.d.ts +2 -2
- package/dist/content/model.d.ts +2 -2
- package/dist/content/notification-categories.js +1 -1
- package/dist/content/ports.d.ts +11 -11
- package/dist/content/service.d.ts +16 -12
- package/dist/content/service.js +62 -16
- package/dist/content/service.js.map +1 -1
- package/dist/discussion/chats.js +2 -2
- package/dist/discussion/events.d.ts +8 -8
- package/dist/discussion/posts.d.ts +1 -1
- package/dist/discussion/posts.js +3 -3
- package/dist/discussion/posts.js.map +1 -1
- package/dist/discussion/service.js +2 -2
- package/dist/discussion/subscriptions.js +1 -1
- package/dist/entitlements/events.d.ts +48 -48
- package/dist/entitlements/service.js +1 -1
- package/dist/identity/devices.js +1 -1
- package/dist/identity/events.d.ts +2 -2
- package/dist/identity/notification-settings.js +1 -1
- package/dist/identity/service.d.ts +1 -1
- package/dist/identity/service.js +3 -3
- package/dist/identity/service.js.map +1 -1
- package/dist/integrations/service.js +2 -2
- package/dist/organizations/effective-permissions.d.ts +3 -1
- package/dist/organizations/effective-permissions.js +8 -3
- package/dist/organizations/effective-permissions.js.map +1 -1
- package/dist/organizations/events.d.ts +29 -23
- package/dist/organizations/index.d.ts +2 -2
- package/dist/organizations/model.d.ts +2 -2
- package/dist/organizations/notification-categories.js +1 -1
- package/dist/organizations/ports.d.ts +6 -3
- package/dist/organizations/service.d.ts +1 -1
- package/dist/organizations/service.js +17 -7
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/testing.js +1 -1
- package/dist/organizations/testing.js.map +1 -1
- package/dist/progress/service.js +2 -2
- package/dist/reporting/member/model.d.ts +3 -0
- package/dist/reporting/member/ports.d.ts +2 -1
- package/dist/reporting/member/service.d.ts +2 -1
- package/dist/reporting/member/service.js +17 -1
- package/dist/reporting/member/service.js.map +1 -1
- package/dist/shared/actor.d.ts +1 -0
- package/dist/types/automations.d.ts +5 -2
- package/dist/types/content.d.ts +2 -2
- package/dist/types/index.d.ts +4 -4
- package/dist/types/organizations.d.ts +2 -2
- package/dist/types/schemas/content.d.ts +70 -8
- package/dist/types/schemas/content.js +19 -2
- package/dist/types/schemas/content.js.map +1 -1
- package/dist/types/schemas/discussion.d.ts +14 -14
- package/dist/types/schemas/entitlements.d.ts +8 -8
- package/dist/types/schemas/index.d.ts +3 -3
- package/dist/types/schemas/index.js +3 -3
- package/dist/types/schemas/notifications.d.ts +4 -4
- package/dist/types/schemas/organizations.d.ts +4 -1
- package/dist/types/schemas/organizations.js +3 -1
- package/dist/types/schemas/organizations.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":[],"sources":["../../src/organizations/service.ts"],"sourcesContent":["import type {\n Accounts,\n ApiKeyRole,\n ApiKeys,\n AuthOrganization,\n CallerLimit,\n CreateApiKeyInput,\n GrantReader,\n MembersRepository,\n OrgAdmin,\n OrganizationService,\n OrganizationsRepository,\n OrganizationsUnitOfWork,\n OrganizationsWriteScope,\n PlatformAccount,\n PlatformOrganization,\n PlatformOrganizationInput,\n ResolvedCaller,\n RolesRepository,\n StoredApiKey,\n TeamRow,\n TransferOwnershipInput,\n} from './ports.js';\nimport type { Invite, Organization, OrgUser } from './model.js';\nimport {\n InviteError,\n OrganizationRuleError,\n type AssignmentView,\n type CreateRoleInput,\n type InviteDetails,\n type Member,\n type MembersQuery,\n type Page,\n type RoleView,\n type UpdateRoleInput,\n type ViewerPermissions,\n} from './members.js';\nimport type {\n AcceptInviteInput,\n AddOrgUserInput,\n CreateInviteInput,\n CreateOrganizationInput,\n NewOrganizationInput,\n UpdateOrganizationInput,\n} from './types.js';\nimport { organizationEvents, type OrganizationEvent } from './events.js';\nimport type { Logger, NewDomainEvent } from '../shared/ports.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { Mailer } from '../shared/mailer.js';\nimport { generateInviteToken, hashInviteToken } from '../shared/invite-token.js';\nimport { ForbiddenError, NotFoundError } from '../shared/errors.js';\nimport type { Actor, EffectivePermissions } from '../shared/actor.js';\nimport type { AuthHeaders, IdentityService, SessionAdmin } from '../identity/index.js';\nimport type { AssetFiles } from '../assets/index.js';\nimport { genId, prefixId } from '../shared/id.js';\nimport { levelSchema } from '../types/schemas/organizations.js';\nimport type {\n ApiKeySummary,\n ConnectedApp,\n ContentType,\n CreatedApiKey,\n Level,\n Permission,\n} from '../types/index.js';\nimport {\n DEFAULT_ROLES,\n MEMBER_ROLE_KEY,\n OWNER_ROLE_KEY,\n validateRoleSet,\n type RoleDefinition,\n} from './default-roles.js';\nimport {\n catalogOf,\n isSystemRole,\n resolveOrgRoles,\n resolveRole,\n type OrgRole,\n type RoleCatalog,\n type StoredOrgRole,\n} from './org-roles.js';\nimport {\n ResolvedPermissions,\n resolvePermissions,\n systemPermissions,\n} from './effective-permissions.js';\nimport {\n ALL_PERMISSIONS,\n fitsLevels,\n permissionAbout,\n permissionList,\n withImplied,\n type PermissionListEntry,\n} from './permissions.js';\n\nconst INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst SYSTEM_ID = 'system';\n\ntype NewOrganizationEvent = NewDomainEvent<OrganizationEvent>;\n\nexport interface InviteUrls {\n studentPortalUrl: string;\n adminAppUrl: string;\n}\n\nexport type OrganizationServiceParams = {\n repo: OrganizationsRepository;\n roles: RolesRepository;\n membersRepo: MembersRepository;\n people: IdentityService;\n images: Pick<AssetFiles, 'syncPublicImage'>;\n uow: OrganizationsUnitOfWork;\n orgAdmin: () => OrgAdmin;\n sessions: () => SessionAdmin;\n apiKeys?: () => ApiKeys;\n accounts?: () => Accounts;\n platform?: PlatformAccount;\n grants?: () => GrantReader;\n defaultRoles?: readonly RoleDefinition[];\n logger?: Logger;\n mailer?: Pick<Mailer, 'send'>;\n inviteUrls?: InviteUrls;\n};\n\nfunction snapshot(role: OrgRole) {\n return {\n key: role.key,\n name: role.name,\n description: role.description,\n base: role.base,\n levels: role.levels,\n team: role.team,\n permissions: role.permissions,\n };\n}\n\nfunction lockKeys(orgId: string, roleKeys: string[], orgUserIds: string[]): string[] {\n return [\n ...roleKeys.map((key) => `role:${orgId}:${key}`),\n ...orgUserIds.map((id) => `org-user:${orgId}:${id}`),\n ];\n}\n\nfunction roleView(role: OrgRole, holders: number): RoleView {\n return { ...role, holders, givable: role.key !== OWNER_ROLE_KEY };\n}\n\nfunction keySummary(key: StoredApiKey, roles: ReadonlyMap<string, OrgRole>): ApiKeySummary {\n return {\n id: key.id,\n name: key.name,\n start: key.start,\n role: key.roleKey ? { key: key.roleKey, name: roles.get(key.roleKey)?.name ?? null } : null,\n createdAt: key.createdAt,\n lastUsedAt: key.lastUsedAt,\n expiresAt: key.expiresAt,\n };\n}\n\nfunction limitScopes(\n limit: CallerLimit | undefined,\n roles: ReadonlyMap<string, OrgRole>,\n): readonly Permission[] | undefined {\n if (!limit) {\n return undefined;\n }\n if ('scopes' in limit) {\n return limit.scopes;\n }\n return roles.get(limit.roleKey)?.permissions ?? [];\n}\n\nexport class OrganizationServiceImpl implements OrganizationService {\n private readonly repo: OrganizationsRepository;\n private readonly roles: RolesRepository;\n private readonly membersRepo: MembersRepository;\n private readonly people: IdentityService;\n private readonly images: Pick<AssetFiles, 'syncPublicImage'>;\n private readonly uow: OrganizationsUnitOfWork;\n private readonly orgAdmin: () => OrgAdmin;\n private readonly sessions: () => SessionAdmin;\n private readonly apiKeysPort?: () => ApiKeys;\n private readonly accountsPort?: () => Accounts;\n private readonly platform?: PlatformAccount;\n private readonly grants?: () => GrantReader;\n private readonly catalog: RoleCatalog;\n private readonly logger: Logger;\n private readonly mailer?: Pick<Mailer, 'send'>;\n private readonly inviteUrls?: InviteUrls;\n\n constructor(params: OrganizationServiceParams) {\n this.repo = params.repo;\n this.roles = params.roles;\n this.membersRepo = params.membersRepo;\n this.people = params.people;\n this.images = params.images;\n this.uow = params.uow;\n this.orgAdmin = params.orgAdmin;\n this.sessions = params.sessions;\n this.apiKeysPort = params.apiKeys;\n this.accountsPort = params.accounts;\n this.platform = params.platform && {\n ...params.platform,\n email: params.platform.email.toLowerCase(),\n };\n this.grants = params.grants;\n const defaults = params.defaultRoles ?? DEFAULT_ROLES;\n validateRoleSet(defaults);\n this.catalog = catalogOf(defaults);\n this.logger = params.logger ?? noopLogger;\n this.mailer = params.mailer;\n this.inviteUrls = params.inviteUrls;\n }\n\n createOrganization(input: NewOrganizationInput, headers: AuthHeaders): Promise<AuthOrganization> {\n return this.orgAdmin().createOrganization(headers, input);\n }\n\n async provisionOrganization(input: CreateOrganizationInput): Promise<Organization> {\n const created = await this.uow.run(async ({ organizations, roles, outbox }) => {\n const id = genId('organization');\n const org = await organizations.create({\n id,\n externalId: input.externalId ?? id,\n name: input.name ?? 'My Org',\n slug: input.slug ?? '',\n ownerId: input.ownerId,\n });\n const owner = await organizations.createOrgUser({\n orgId: org.id,\n userId: input.ownerId,\n status: 'active',\n });\n await roles.setOrgRole(org.id, owner.id, OWNER_ROLE_KEY, SYSTEM_ID);\n await outbox.append([\n organizationEvents.organizationCreated.make({ orgId: org.id, data: org }),\n organizationEvents.orgUserLinked.make({\n orgId: org.id,\n data: { ...owner, orgRole: { key: OWNER_ROLE_KEY } },\n }),\n ]);\n return org;\n });\n this.logger.info('organization created', { orgId: created.id, slug: created.slug });\n return created;\n }\n\n async updateOrganization(input: UpdateOrganizationInput, actor: Actor): Promise<Organization> {\n actor.permissions.require('organizations:write');\n const orgId = actor.orgId;\n const org = await this.repo.findById(orgId);\n if (!org) {\n throw new NotFoundError('Organization', orgId);\n }\n if (input.slug !== undefined && input.slug !== org.slug) {\n const taken = await this.repo.findBySlug(input.slug);\n if (taken && taken.id !== orgId) {\n this.logger.warn('organization update refused: slug taken', { orgId, slug: input.slug });\n throw new OrganizationRuleError('That slug is already taken');\n }\n }\n await this.orgAdmin().updateOrganization(org.externalId ?? org.id, input);\n const updated = await this.uow.run(async ({ organizations, outbox }) => {\n const next = await organizations.update(orgId, { name: input.name, slug: input.slug });\n if (!next) {\n throw new NotFoundError('Organization', orgId);\n }\n await outbox.append([\n organizationEvents.organizationUpdated.make({\n orgId,\n data: next,\n metadata: { actorId: actor.id },\n }),\n ]);\n return next;\n });\n this.logger.info('organization updated', { orgId, actorId: actor.id });\n return updated;\n }\n\n async deleteOrganization(id: string): Promise<Organization> {\n const deleted = await this.uow.run(async ({ organizations, outbox }) => {\n const deleted = await organizations.delete(id);\n await outbox.append([\n organizationEvents.organizationDeleted.make({ orgId: deleted.id, data: deleted }),\n ]);\n return deleted;\n });\n this.logger.info('organization deleted', { orgId: deleted.id });\n return deleted;\n }\n\n async addOrgUser({ orgId, userId }: AddOrgUserInput): Promise<OrgUser> {\n const existing = await this.repo.findOrgUser(orgId, userId);\n if (existing) {\n return existing;\n }\n const orgUser = await this.uow.run(async ({ organizations, outbox }) => {\n const created = await organizations.createOrgUser({ orgId, userId, status: 'active' });\n await outbox.append([\n organizationEvents.orgUserLinked.make({\n orgId,\n data: { ...created, orgRole: { key: MEMBER_ROLE_KEY } },\n }),\n ]);\n return created;\n });\n this.logger.info('user added to organization', { orgId, userId, orgUserId: orgUser.id });\n return orgUser;\n }\n\n async removeOrgUser(orgId: string, userId: string): Promise<OrgUser | null> {\n const orgUser = await this.repo.findOrgUser(orgId, userId);\n if (!orgUser) {\n return null;\n }\n return this.deleteOrgUserRow(orgId, orgUser);\n }\n\n getByExternalId(externalId: string): Promise<Organization | null> {\n return this.repo.findByExternalId(externalId);\n }\n\n getBySlug(slug: string): Promise<Organization | null> {\n return this.repo.findBySlug(slug);\n }\n\n getById(id: string): Promise<Organization | null> {\n return this.repo.findById(id);\n }\n\n async portalIdentity(id: string): Promise<Pick<Organization, 'id' | 'name' | 'slug'>> {\n const org = await this.repo.findById(id);\n if (!org) {\n throw new NotFoundError('Organization', id);\n }\n return { id: org.id, name: org.name, slug: org.slug };\n }\n\n getOrgUser(orgId: string, userId: string): Promise<OrgUser | null> {\n return this.repo.findOrgUser(orgId, userId);\n }\n\n getOrgUserById(orgId: string, id: string): Promise<OrgUser | null> {\n return this.repo.findOrgUserById(orgId, id);\n }\n\n async getOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]> {\n const unique = [...new Set(ids)];\n return unique.length > 0 ? this.repo.findOrgUsersByIds(orgId, unique) : [];\n }\n\n getOrgUsersForUser(userId: string): Promise<OrgUser[]> {\n return this.repo.findOrgUsersByUser(userId);\n }\n\n orgIds(): Promise<string[]> {\n return this.repo.listIds();\n }\n\n async actorFor(orgId: string, orgUserId: string, limit?: CallerLimit): Promise<Actor | null> {\n const facts = await this.roles.actorFacts(orgId, orgUserId);\n if (!facts || facts.status !== 'active') {\n return null;\n }\n const roles = this.roleMap(facts.storedRoles);\n const tokenScopes = limitScopes(limit, roles);\n return {\n id: orgUserId,\n orgId,\n permissions: resolvePermissions({\n assignments: facts.assignments,\n roles,\n ...(tokenScopes !== undefined && { tokenScopes }),\n }),\n };\n }\n\n async resolveCaller(\n authOrgId: string,\n authUserId: string,\n limit?: CallerLimit,\n ): Promise<ResolvedCaller | null> {\n const facts = await this.roles.callerFacts(authOrgId, authUserId);\n if (!facts) {\n return null;\n }\n const orgUser = facts.orgUser;\n if (orgUser?.status !== 'active') {\n return {\n orgId: facts.orgId,\n userId: facts.userId,\n orgUserId: orgUser?.orgUserId ?? null,\n actor: null,\n };\n }\n const roles = this.roleMap(orgUser.storedRoles);\n const tokenScopes = limitScopes(limit, roles);\n return {\n orgId: facts.orgId,\n userId: facts.userId,\n orgUserId: orgUser.orgUserId,\n actor: {\n id: orgUser.orgUserId,\n orgId: facts.orgId,\n permissions: resolvePermissions({\n assignments: orgUser.assignments,\n roles,\n ...(tokenScopes !== undefined && { tokenScopes }),\n }),\n },\n };\n }\n\n systemActor(orgId: string): Actor {\n return { id: SYSTEM_ID, orgId, permissions: systemPermissions() };\n }\n\n async permissionsOfMany(\n orgId: string,\n orgUserIds: string[],\n ): Promise<Map<string, EffectivePermissions>> {\n const unique = [...new Set(orgUserIds)];\n const out = new Map<string, EffectivePermissions>();\n if (unique.length === 0) {\n return out;\n }\n const [stored, assignments] = await Promise.all([\n this.roles.storedRoles(orgId),\n this.roles.assignmentsOfMany(orgId, unique),\n ]);\n const roles = this.roleMap(stored);\n for (const id of unique) {\n out.set(id, resolvePermissions({ assignments: assignments.get(id) ?? [], roles }));\n }\n return out;\n }\n\n async holders(orgId: string, permission: Permission, on?: string): Promise<string[]> {\n const stored = await this.roles.storedRoles(orgId);\n const keys = resolveOrgRoles(this.catalog, stored)\n .filter((role) => withImplied(role.permissions).has(permission))\n .map((role) => role.key);\n const candidates = await this.roles.holdersOf(orgId, keys, on);\n if (candidates.length === 0) {\n return [];\n }\n const permissions = await this.permissionsOfMany(orgId, candidates);\n return candidates.filter((id) => permissions.get(id)?.has(permission, on) ?? false);\n }\n\n permissionList(): PermissionListEntry[] {\n return permissionList();\n }\n\n viewerPermissions(actor: Actor): ViewerPermissions {\n const role = actor.permissions.roleOn();\n if (actor.permissions instanceof ResolvedPermissions) {\n return {\n orgRole: { key: role.key, name: role.name },\n isOwner: actor.permissions.isOwner(),\n org: actor.permissions.orgPermissions(),\n content: actor.permissions.contentPermissions(),\n };\n }\n return {\n orgRole: { key: role.key, name: role.name },\n isOwner: actor.permissions.isOwner(),\n org: ALL_PERMISSIONS.filter((p) => actor.permissions.has(p)),\n content: {},\n };\n }\n\n async auditRoleKeys(): Promise<number> {\n const usage = await this.roles.roleKeyUsage();\n const storedByOrg = new Map<string, StoredOrgRole[]>();\n let dangling = 0;\n for (const row of usage) {\n if (!storedByOrg.has(row.orgId)) {\n storedByOrg.set(row.orgId, await this.roles.storedRoles(row.orgId));\n }\n const role = this.resolveIn(storedByOrg.get(row.orgId)!, row.roleKey);\n if (!role) {\n dangling += row.count;\n this.logger.warn('assignments name a role the set no longer has', {\n orgId: row.orgId,\n roleKey: row.roleKey,\n level: row.level,\n count: row.count,\n });\n } else if (!role.levels.includes(row.level as Level)) {\n dangling += row.count;\n this.logger.warn('assignments sit at a level their role no longer lists', {\n orgId: row.orgId,\n roleKey: row.roleKey,\n level: row.level,\n count: row.count,\n });\n }\n }\n return dangling;\n }\n\n async listRoles(actor: Actor): Promise<RoleView[]> {\n actor.permissions.require('roles:read');\n const [stored, counts] = await Promise.all([\n this.roles.storedRoles(actor.orgId),\n this.roles.holderCounts(actor.orgId),\n ]);\n return resolveOrgRoles(this.catalog, stored).map((role) =>\n roleView(role, counts[role.key] ?? 0),\n );\n }\n\n async getRole(key: string, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:read');\n const role = await this.findRole(actor.orgId, key);\n const holders = await this.roles.countHolders(actor.orgId, key);\n return roleView(role, holders);\n }\n\n async updateRole(key: string, input: UpdateRoleInput, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n const changesAccess =\n input.levels !== undefined || input.team !== undefined || input.permissions !== undefined;\n const result = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n const current = stored.find((row) => row.key === key);\n const before = this.resolveIn(stored, key);\n if (!before) {\n throw new NotFoundError('Role', key);\n }\n if (changesAccess && isSystemRole(key)) {\n throw new OrganizationRuleError(`${before.name} can only be renamed`);\n }\n if (input.name !== undefined) {\n this.assertUniqueName(stored, key, input.name);\n }\n const next: StoredOrgRole = {\n key,\n name: input.name ?? current?.name ?? null,\n description: input.description ?? current?.description ?? null,\n base: current?.base ?? before.base,\n levels: input.levels ? this.parseLevels(input.levels) : (current?.levels ?? null),\n permissions: { ...(current?.permissions ?? {}), ...(input.permissions ?? {}) },\n team: input.team ?? current?.team ?? null,\n };\n const after = resolveRole(key, this.catalog, next);\n if (!after) {\n throw new NotFoundError('Role', key);\n }\n if (changesAccess) {\n this.assertFits(next);\n this.assertHolds(editor, [...before.permissions, ...after.permissions]);\n await this.assertLevelsNotInUse(roles, orgId, before, after);\n }\n await roles.saveStoredRole(orgId, next);\n await outbox.append([\n organizationEvents.roleUpdated.make({\n orgId,\n data: { key, before: snapshot(before), after: snapshot(after) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return after;\n });\n this.logger.info('role updated', { orgId, roleKey: key, actorId: actor.id });\n return roleView(result, await this.roles.countHolders(orgId, key));\n }\n\n async createRole(input: CreateRoleInput, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n const base = this.catalog.get(input.base);\n if (!base || isSystemRole(input.base)) {\n throw new OrganizationRuleError('A role is added from one of the deployment roles');\n }\n const key = prefixId('role');\n const created = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [key, `name:${input.name.trim().toLowerCase()}`], [actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n this.assertUniqueName(stored, key, input.name);\n const row: StoredOrgRole = {\n key,\n name: input.name,\n description: input.description ?? null,\n base: input.base,\n levels: input.levels ? this.parseLevels(input.levels) : null,\n permissions: input.permissions ?? {},\n team: input.team ?? null,\n };\n this.assertFits(row);\n const role = resolveRole(key, this.catalog, row)!;\n this.assertHolds(editor, role.permissions);\n await roles.saveStoredRole(orgId, row);\n await outbox.append([\n organizationEvents.roleCreated.make({\n orgId,\n data: { role: snapshot(role) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return role;\n });\n this.logger.info('role created', { orgId, roleKey: key, actorId: actor.id });\n return roleView(created, 0);\n }\n\n async resetRole(key: string, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n if (!this.catalog.has(key)) {\n throw new OrganizationRuleError('Only a deployment role can be reset');\n }\n const result = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n const before = this.resolveIn(stored, key);\n const after = resolveRole(key, this.catalog, undefined);\n if (!before || !after) {\n throw new NotFoundError('Role', key);\n }\n this.assertUniqueName(\n stored.filter((row) => row.key !== key),\n key,\n after.name,\n );\n this.assertHolds(editor, [...before.permissions, ...after.permissions]);\n await this.assertLevelsNotInUse(roles, orgId, before, after);\n await roles.deleteStoredRole(orgId, key);\n await outbox.append([\n organizationEvents.roleUpdated.make({\n orgId,\n data: { key, before: snapshot(before), after: snapshot(after) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return after;\n });\n this.logger.info('role reset', { orgId, roleKey: key, actorId: actor.id });\n return roleView(result, await this.roles.countHolders(orgId, key));\n }\n\n async deleteRole(key: string, actor: Actor): Promise<void> {\n actor.permissions.require('roles:delete');\n const orgId = actor.orgId;\n if (this.catalog.has(key)) {\n throw new OrganizationRuleError('A deployment role can be renamed and reset, not deleted');\n }\n const keys = await this.keysWithRole(orgId, key);\n if (keys > 0) {\n this.logger.warn('role deletion refused: role is on api keys', { orgId, roleKey: key, keys });\n throw new OrganizationRuleError(\n `This role is on ${keys} API ${keys === 1 ? 'key' : 'keys'}; revoke ${keys === 1 ? 'it' : 'them'} first`,\n );\n }\n await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n (await this.relockedActor(scope, actor)).permissions.require('roles:delete');\n const holders = await roles.countHolders(orgId, key);\n if (holders > 0) {\n this.logger.warn('role deletion refused: role is held', { orgId, roleKey: key, holders });\n throw new OrganizationRuleError(\n `This role is held by ${holders} ${holders === 1 ? 'person' : 'people'}`,\n );\n }\n const deleted = await roles.deleteStoredRole(orgId, key);\n if (!deleted) {\n throw new NotFoundError('Role', key);\n }\n await outbox.append([\n organizationEvents.roleDeleted.make({\n orgId,\n data: { key },\n metadata: { actorId: actor.id },\n }),\n ]);\n });\n this.logger.info('role deleted', { orgId, roleKey: key, actorId: actor.id });\n }\n\n async listTeam(query: MembersQuery, actor: Actor): Promise<Page<Member>> {\n actor.permissions.require('people:read');\n const orgId = actor.orgId;\n const [rows, stored] = await Promise.all([\n this.membersRepo.teamRows(orgId, MEMBER_ROLE_KEY),\n this.roles.storedRoles(orgId),\n ]);\n const roles = this.roleMap(stored);\n const nameOf = (key: string): string => roles.get(key)?.name ?? key;\n let members = rows.map((row) => this.toMember(row, nameOf));\n if (query.roleKey) {\n members = members.filter(\n (m) => m.orgRole.key === query.roleKey || m.items.some((i) => i.roleKey === query.roleKey),\n );\n }\n if (query.status) {\n members = members.filter((m) => m.status === query.status);\n }\n const q = query.search?.trim().toLowerCase();\n if (q) {\n members = members.filter((m) =>\n [m.firstName, m.lastName, m.email].some((v) => v?.toLowerCase().includes(q)),\n );\n }\n const sort = query.sort;\n const desc = sort?.startsWith('-') ?? false;\n const key = desc ? sort!.slice(1) : sort;\n const byName = (a: string | null, b: string | null): number =>\n a === b ? 0 : a === null ? 1 : b === null ? -1 : a.localeCompare(b);\n members.sort((a, b) => {\n const cmp =\n key === 'email'\n ? a.email.localeCompare(b.email)\n : key === 'role'\n ? a.orgRole.name.localeCompare(b.orgRole.name)\n : key === 'lastName'\n ? byName(a.lastName, b.lastName) || byName(a.firstName, b.firstName)\n : byName(a.firstName, b.firstName) || byName(a.lastName, b.lastName);\n return desc ? -cmp : cmp;\n });\n const start = (query.page - 1) * query.pageSize;\n return {\n rows: members.slice(start, start + query.pageSize),\n total: members.length,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n async listAssignments(orgUserId: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:read');\n return this.assignmentViews(actor.orgId, orgUserId);\n }\n\n async listAssignmentsOn(contentId: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:read');\n const [rows, stored] = await Promise.all([\n this.roles.assignmentsOn(actor.orgId, contentId),\n this.roles.storedRoles(actor.orgId),\n ]);\n const roles = this.roleMap(stored);\n return rows.map((row) => ({\n orgUserId: row.orgUserId,\n roleKey: row.roleKey,\n roleName: roles.get(row.roleKey)?.name ?? row.roleKey,\n contentId: row.contentId,\n contentType: row.contentType,\n }));\n }\n\n async setOrgRole(orgUserId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === null,\n );\n const target = await this.repo.findOrgUserById(orgId, orgUserId);\n const invitee =\n target?.status === 'invited' ? await this.people.getUserById(target.userId) : null;\n await this.uow.run(async (scope) => {\n const { roles, organizations, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [roleKey, seen?.roleKey ?? MEMBER_ROLE_KEY], [orgUserId, actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const orgUser = await organizations.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const stored = await roles.storedRoles(orgId);\n const next = this.resolveIn(stored, roleKey);\n if (!next) {\n throw new NotFoundError('Role', roleKey);\n }\n if (roleKey === OWNER_ROLE_KEY) {\n throw new OrganizationRuleError('Ownership moves only by transfer');\n }\n if (!next.levels.includes('org')) {\n throw new OrganizationRuleError(`${next.name} can't be given on the organization`);\n }\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === null,\n );\n if (current?.roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('org role change refused: target is the owner', { orgId, orgUserId });\n throw new OrganizationRuleError(\"The owner's role changes only by transfer\");\n }\n if (orgUser.status === 'invited') {\n const person = invitee?.id === orgUser.userId ? invitee : null;\n const pending = person ? await organizations.findPendingInvite(orgId, person.email) : null;\n if (!pending) {\n throw new NotFoundError('Invite', orgUserId);\n }\n const invited = this.resolveIn(stored, pending.roleKey);\n this.assertHolds(editor, [...(invited?.permissions ?? []), ...next.permissions]);\n const editorUser = await organizations.findOrgUserById(orgId, actor.id);\n if (!editorUser) {\n throw new ForbiddenError('You are no longer an active member of this organization');\n }\n await organizations.setInviteRole(orgId, pending.id, roleKey, editorUser.userId);\n this.logger.info('pending invite role changed', {\n orgId,\n orgUserId,\n inviteId: pending.id,\n roleKey,\n actorId: actor.id,\n });\n return;\n }\n const previousKey = current?.roleKey ?? MEMBER_ROLE_KEY;\n const previous = this.resolveIn(stored, previousKey);\n this.assertHolds(editor, [...(previous?.permissions ?? []), ...next.permissions]);\n await roles.setOrgRole(\n orgId,\n orgUserId,\n roleKey === MEMBER_ROLE_KEY ? null : roleKey,\n actor.id,\n );\n if (previousKey !== roleKey) {\n await outbox.append([\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey,\n contentId: null,\n contentType: null,\n previousRoleKey: previousKey,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n this.logger.info('org role set', { orgId, orgUserId, roleKey, actorId: actor.id });\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async assignRole(\n orgUserId: string,\n contentId: string,\n roleKey: string,\n actor: Actor,\n ): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n await this.uow.run(async (scope) => {\n const { roles, organizations, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [roleKey, ...(seen ? [seen.roleKey] : [])], [orgUserId, actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const orgUser = await organizations.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const contentType = await roles.contentTypeOf(orgId, contentId);\n if (!contentType) {\n throw new NotFoundError('Content', contentId);\n }\n const stored = await roles.storedRoles(orgId);\n const next = this.resolveIn(stored, roleKey);\n if (!next) {\n throw new NotFoundError('Role', roleKey);\n }\n if (isSystemRole(roleKey) || !next.levels.includes(contentType)) {\n this.logger.warn('role assignment refused: level not listed', {\n orgId,\n roleKey,\n contentType,\n });\n throw new OrganizationRuleError(`${next.name} can't be given on a ${contentType}`);\n }\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n const previous = current ? this.resolveIn(stored, current.roleKey) : null;\n this.assertHoldsOn(\n editor,\n [\n ...this.itemPermissions(previous, contentType),\n ...this.itemPermissions(next, contentType),\n ],\n contentId,\n );\n await roles.setItemRole(orgId, orgUserId, contentId, contentType, roleKey, actor.id);\n if (current?.roleKey !== roleKey) {\n await outbox.append([\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey,\n contentId,\n contentType,\n previousRoleKey: current?.roleKey ?? null,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n });\n this.logger.info('item role given', {\n orgId,\n orgUserId,\n contentId,\n roleKey,\n actorId: actor.id,\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async unassignRole(\n orgUserId: string,\n contentId: string,\n actor: Actor,\n ): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, seen ? [seen.roleKey] : [], [orgUserId, actor.id]));\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n if (!current || !current.contentType) {\n throw new NotFoundError('Role assignment', contentId);\n }\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const stored = await roles.storedRoles(orgId);\n const role = this.resolveIn(stored, current.roleKey);\n this.assertHoldsOn(editor, this.itemPermissions(role, current.contentType), contentId);\n const removed = await roles.removeItemRole(orgId, orgUserId, contentId);\n if (removed) {\n await outbox.append([\n organizationEvents.roleUnassigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey: removed.roleKey,\n contentId,\n contentType: current.contentType,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n });\n this.logger.info('item role removed', {\n orgId,\n orgUserId,\n contentId,\n actorId: actor.id,\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async removePerson(orgUserId: string, actor: Actor): Promise<void> {\n actor.permissions.require('people:delete');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const orgUser = await this.repo.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const person = await this.people.getUserById(orgUser.userId);\n await this.uow.run(async (scope) => {\n const { roles } = scope;\n await roles.lock(lockKeys(orgId, [], [orgUserId, actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:delete');\n const held = await roles.assignmentsOf(orgId, orgUserId);\n if (held.some((row) => row.roleKey === OWNER_ROLE_KEY)) {\n this.logger.warn('removal refused: target is the owner', { orgId, orgUserId });\n throw new OrganizationRuleError('The owner cannot be removed');\n }\n const stored = await roles.storedRoles(orgId);\n for (const row of held) {\n const role = this.resolveIn(stored, row.roleKey);\n if (!role) {\n continue;\n }\n if (row.contentId === null) {\n this.assertHolds(editor, role.permissions);\n } else if (row.contentType) {\n this.assertHoldsOn(editor, this.itemPermissions(role, row.contentType), row.contentId);\n }\n }\n await this.deleteOrgUserIn(scope, orgId, orgUser, held, actor.id);\n });\n this.logger.info('person removed', { orgId, orgUserId, actorId: actor.id });\n await this.cleanUpAfterRemoval(orgId, orgUserId, person);\n }\n\n async transferOwnership(input: TransferOwnershipInput, actor: Actor): Promise<void> {\n if (!actor.permissions.isOwner()) {\n this.logger.warn('ownership transfer refused: caller is not the owner', {\n orgId: actor.orgId,\n actorId: actor.id,\n });\n throw new ForbiddenError('Only the owner can transfer ownership');\n }\n const orgId = actor.orgId;\n const previousRoleKey = input.previousOwnerRoleKey ?? MEMBER_ROLE_KEY;\n if (input.newOwnerOrgUserId === actor.id) {\n throw new OrganizationRuleError('You already own this organization');\n }\n const stored = await this.roles.storedRoles(orgId);\n const previousRole = this.resolveIn(stored, previousRoleKey);\n if (\n !previousRole ||\n previousRoleKey === OWNER_ROLE_KEY ||\n !previousRole.levels.includes('org')\n ) {\n throw new OrganizationRuleError('The previous owner needs a role given on the organization');\n }\n const [org, newOwner, previousOwner] = await Promise.all([\n this.repo.findById(orgId),\n this.repo.findOrgUserById(orgId, input.newOwnerOrgUserId),\n this.repo.findOrgUserById(orgId, actor.id),\n ]);\n if (!org || !previousOwner) {\n throw new NotFoundError('Organization', orgId);\n }\n if (!newOwner || newOwner.status !== 'active') {\n throw new OrganizationRuleError('The new owner must be an active member of the organization');\n }\n const [newPerson, previousPerson] = await Promise.all([\n this.people.getUserById(newOwner.userId),\n this.people.getUserById(previousOwner.userId),\n ]);\n if (!newPerson?.externalId || !previousPerson?.externalId) {\n throw new OrganizationRuleError('Both people need an account');\n }\n const orgExternalId = org.externalId ?? org.id;\n await this.orgAdmin().setMembershipOwner(orgExternalId, newPerson.externalId, true);\n await this.orgAdmin().setMembershipOwner(orgExternalId, previousPerson.externalId, false);\n await this.uow.run(async ({ roles, outbox }) => {\n await roles.lock(\n lockKeys(orgId, [OWNER_ROLE_KEY, previousRoleKey], [newOwner.id, previousOwner.id]),\n );\n const owner = await roles.ownerOrgUserId(orgId);\n if (owner !== previousOwner.id) {\n throw new ForbiddenError('Only the owner can transfer ownership');\n }\n await roles.setOrgRole(orgId, newOwner.id, null, actor.id);\n await roles.setOrgRole(\n orgId,\n previousOwner.id,\n previousRoleKey === MEMBER_ROLE_KEY ? null : previousRoleKey,\n actor.id,\n );\n await roles.setOrgRole(orgId, newOwner.id, OWNER_ROLE_KEY, actor.id);\n await outbox.append([\n organizationEvents.ownershipTransferred.make({\n orgId,\n data: { previousOwnerOrgUserId: previousOwner.id, newOwnerOrgUserId: newOwner.id },\n metadata: { actorId: actor.id },\n }),\n ]);\n });\n this.logger.info('ownership transferred', {\n orgId,\n previousOwnerOrgUserId: previousOwner.id,\n newOwnerOrgUserId: newOwner.id,\n });\n }\n\n async createInvite(\n input: CreateInviteInput,\n actor: Actor,\n inviterUserId: string,\n ): Promise<Invite> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const roleKey = input.roleKey ?? MEMBER_ROLE_KEY;\n const email = input.email;\n if (roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('invite refused: ownership cannot be granted', { orgId });\n throw new OrganizationRuleError('Ownership moves only by transfer');\n }\n const stored = await this.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, roleKey);\n if (!role) {\n throw new NotFoundError('Role', roleKey);\n }\n if (!role.levels.includes('org')) {\n throw new OrganizationRuleError(`${role.name} can't be given on the organization`);\n }\n this.assertHolds(actor, role.permissions);\n const known = await this.people.getUserByEmail(email);\n const existing = known ? await this.repo.findOrgUser(orgId, known.id) : null;\n if (existing?.id === actor.id) {\n this.logger.warn('invite refused: inviting yourself', { orgId, actorId: actor.id });\n throw new ForbiddenError(\"You can't change your own roles\");\n }\n let contributed = role.permissions;\n if (existing) {\n const held = await this.roles.assignmentsOf(orgId, existing.id);\n const current = held.find((row) => row.contentId === null);\n if (current?.roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('invite refused: target is the owner', { orgId });\n throw new OrganizationRuleError('The owner cannot be invited');\n }\n const currentRole = this.resolveIn(stored, current?.roleKey ?? MEMBER_ROLE_KEY);\n contributed = [...contributed, ...(currentRole?.permissions ?? [])];\n }\n this.assertHolds(actor, contributed);\n const person =\n known ??\n (await this.people.createUser({\n email,\n ...(input.firstName !== undefined && { firstName: input.firstName }),\n ...(input.lastName !== undefined && { lastName: input.lastName }),\n }));\n const sendEmail = input.sendEmail ?? true;\n const { token, tokenHash } = generateInviteToken();\n const expiresAt = new Date(Date.now() + INVITE_TTL_MS);\n const invite = await this.uow.run(async ({ organizations, outbox }) => {\n const events: NewOrganizationEvent[] = [];\n if (!existing) {\n const orgUser = await organizations.createOrgUser({\n orgId,\n userId: person.id,\n status: 'invited',\n });\n events.push(\n roleKey === MEMBER_ROLE_KEY\n ? organizationEvents.studentCreated.make({ orgId, data: orgUser })\n : organizationEvents.orgUserLinked.make({\n orgId,\n data: { ...orgUser, orgRole: { key: MEMBER_ROLE_KEY } },\n }),\n );\n }\n const row = await organizations.upsertPendingInvite(orgId, {\n email,\n roleKey,\n invitedBy: inviterUserId,\n tokenHash,\n expiresAt,\n });\n events.push(\n organizationEvents.inviteCreated.make({\n orgId,\n data: row,\n metadata: { actorId: actor.id },\n }),\n );\n await outbox.append(events);\n return row;\n });\n if (sendEmail) {\n try {\n await this.sendInviteEmail(invite, token, role);\n } catch (err) {\n this.logger.error('failed to send invite email', {\n orgId,\n inviteId: invite.id,\n roleKey,\n err: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }\n this.logger.info('invite created', {\n orgId,\n inviteId: invite.id,\n roleKey,\n sendEmail,\n actorId: actor.id,\n });\n return invite;\n }\n\n async resendInvite(orgUserId: string, actor: Actor, inviterUserId: string): Promise<void> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const { invite, role } = await this.pendingInviteOf(orgId, orgUserId);\n this.assertHolds(actor, role.permissions);\n const { token, tokenHash } = generateInviteToken();\n const expiresAt = new Date(Date.now() + INVITE_TTL_MS);\n const refreshed = await this.repo.setInviteToken(\n orgId,\n invite.id,\n tokenHash,\n expiresAt,\n inviterUserId,\n );\n if (!refreshed) {\n throw new NotFoundError('Invite', invite.id);\n }\n await this.sendInviteEmail(refreshed, token, role);\n this.logger.info('invite resent', {\n orgId,\n orgUserId,\n inviteId: invite.id,\n actorId: actor.id,\n });\n }\n\n async cancelInvite(orgUserId: string, actor: Actor): Promise<void> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const { invite, role, orgUser } = await this.pendingInviteOf(orgId, orgUserId);\n this.assertHolds(actor, role.permissions);\n const held = await this.roles.assignmentsOf(orgId, orgUserId);\n const holdsGrant = this.grants ? await this.grants().holdsAnyGrant(orgId, orgUserId) : true;\n await this.uow.run(async (scope) => {\n const canceled = await scope.organizations.setInviteStatus(orgId, invite.id, 'canceled');\n if (!canceled) {\n throw new NotFoundError('Invite', invite.id);\n }\n await scope.outbox.append([\n organizationEvents.inviteCanceled.make({\n orgId,\n data: canceled,\n metadata: { actorId: actor.id },\n }),\n ]);\n if (orgUser.status === 'invited' && held.length === 0 && !holdsGrant) {\n await this.deleteOrgUserIn(scope, orgId, orgUser, held, actor.id);\n }\n });\n this.logger.info('invite canceled', {\n orgId,\n orgUserId,\n inviteId: invite.id,\n actorId: actor.id,\n });\n }\n\n async peekInvite(token: string): Promise<Invite | null> {\n const invite = await this.repo.findInviteByTokenHash(hashInviteToken(token));\n if (!invite || invite.status !== 'pending') {\n return null;\n }\n if (invite.expiresAt && invite.expiresAt < new Date()) {\n return null;\n }\n return invite;\n }\n\n async describeInvite(token: string): Promise<InviteDetails> {\n const invite = await this.peekInvite(token);\n if (!invite) {\n throw new NotFoundError('Invite', 'token');\n }\n const person = await this.people.getUserByEmail(invite.email);\n return {\n email: invite.email,\n firstName: person?.firstName ?? null,\n lastName: person?.lastName ?? null,\n };\n }\n\n async acceptInvite(input: AcceptInviteInput, headers: AuthHeaders): Promise<OrgUser> {\n const invite = await this.peekInvite(input.token);\n if (!invite) {\n this.logger.warn('invite accept refused: token invalid or expired');\n throw new InviteError('invalid invite');\n }\n if (invite.email.toLowerCase() !== input.email.toLowerCase()) {\n this.logger.warn('invite accept refused: email mismatch', {\n orgId: invite.orgId,\n inviteId: invite.id,\n });\n throw new InviteError('emails must match');\n }\n const orgId = invite.orgId;\n const org = await this.repo.findById(orgId);\n if (!org) {\n throw new InviteError('Org not found');\n }\n const person = await this.people.getUserByExternalId(input.authUserId);\n if (!person?.externalId) {\n throw new NotFoundError('User', input.authUserId);\n }\n const orgUser = await this.repo.findOrgUser(orgId, person.id);\n if (!orgUser) {\n throw new NotFoundError('Person', person.id);\n }\n const inviter = await this.repo.findOrgUser(orgId, invite.invitedBy);\n if (!inviter) {\n this.logger.warn('invite accept refused: inviter left', { orgId, inviteId: invite.id });\n throw new InviteError('This invitation is no longer valid; ask for a new one');\n }\n await this.uow.run((scope) => this.checkAcceptance(scope, invite, orgUser, inviter.id));\n await this.orgAdmin().grantMembership(org.externalId ?? org.id, person.externalId);\n const accepted = await this.uow.run(async (scope) => {\n const { organizations, roles, outbox } = scope;\n const seen = (await roles.assignmentsOf(orgId, orgUser.id)).find(\n (row) => row.contentId === null,\n );\n await roles.lock(\n lockKeys(\n orgId,\n [invite.roleKey, seen?.roleKey ?? MEMBER_ROLE_KEY],\n [orgUser.id, inviter.id],\n ),\n );\n const previousKey = await this.checkAcceptance(scope, invite, orgUser, inviter.id);\n const activated =\n orgUser.status === 'active'\n ? orgUser\n : await organizations.updateOrgUser(orgId, orgUser.id, { status: 'active' });\n if (!activated) {\n throw new NotFoundError('Person', orgUser.id);\n }\n const acceptedInvite = await organizations.setInviteStatus(orgId, invite.id, 'accepted');\n if (!acceptedInvite) {\n throw new NotFoundError('Invite', invite.id);\n }\n await roles.setOrgRole(\n orgId,\n orgUser.id,\n invite.roleKey === MEMBER_ROLE_KEY ? null : invite.roleKey,\n inviter.id,\n );\n const events: NewOrganizationEvent[] = [\n organizationEvents.inviteAccepted.make({ orgId, data: acceptedInvite }),\n ];\n if (orgUser.status !== 'active') {\n events.push(\n organizationEvents.orgUserUpdated.make({\n orgId,\n data: { ...activated, orgRole: { key: invite.roleKey } },\n }),\n );\n if (invite.roleKey === MEMBER_ROLE_KEY) {\n events.push(organizationEvents.studentLinked.make({ orgId, data: activated }));\n }\n }\n if (previousKey !== invite.roleKey) {\n events.push(\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId: orgUser.id,\n roleKey: invite.roleKey,\n contentId: null,\n contentType: null,\n previousRoleKey: previousKey,\n },\n metadata: { actorId: inviter.id },\n }),\n );\n }\n await outbox.append(events);\n return activated;\n });\n await this.sessions().stampActiveOrganization(headers, orgId);\n this.logger.info('invite accepted', { orgId, inviteId: invite.id, orgUserId: orgUser.id });\n return accepted;\n }\n\n private async checkAcceptance(\n scope: OrganizationsWriteScope,\n invite: Invite,\n orgUser: OrgUser,\n inviterOrgUserId: string,\n ): Promise<string> {\n const orgId = invite.orgId;\n const stored = await scope.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, invite.roleKey);\n if (!role || invite.roleKey === OWNER_ROLE_KEY) {\n throw new InviteError('The invited role no longer exists');\n }\n const current = (await scope.roles.assignmentsOf(orgId, orgUser.id)).find(\n (row) => row.contentId === null,\n );\n if (current?.roleKey === OWNER_ROLE_KEY) {\n throw new InviteError(\"The owner's role changes only by transfer\");\n }\n const currentRole = this.resolveIn(stored, current?.roleKey ?? MEMBER_ROLE_KEY);\n const facts = await scope.roles.actorFacts(orgId, inviterOrgUserId);\n const inviter =\n facts && facts.status === 'active'\n ? resolvePermissions({\n assignments: facts.assignments,\n roles: this.roleMap(facts.storedRoles),\n })\n : null;\n const needed: Permission[] = [\n 'people:write',\n ...role.permissions,\n ...(currentRole?.permissions ?? []),\n ];\n const missing = inviter ? needed.filter((p) => !inviter.has(p)) : needed;\n if (missing.length > 0) {\n this.logger.warn('invite accept refused: inviter no longer holds the role', {\n orgId,\n inviteId: invite.id,\n inviterOrgUserId,\n missing,\n });\n throw new InviteError('This invitation is no longer valid; ask for a new one');\n }\n return current?.roleKey ?? MEMBER_ROLE_KEY;\n }\n\n async listApiKeys(actor: Actor): Promise<ApiKeySummary[]> {\n actor.permissions.require('api_keys:read');\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n const [keys, stored] = await Promise.all([\n this.apiKeys().list(orgExternalId, userExternalId),\n this.roles.storedRoles(actor.orgId),\n ]);\n const roles = this.roleMap(stored);\n return keys.map((key) => keySummary(key, roles));\n }\n\n async listApiKeyRoles(actor: Actor): Promise<ApiKeyRole[]> {\n actor.permissions.require('api_keys:write');\n const stored = await this.roles.storedRoles(actor.orgId);\n return resolveOrgRoles(this.catalog, stored)\n .filter((role) =>\n role.permissions.every((permission) => actor.permissions.anywhere(permission)),\n )\n .map((role) => ({ key: role.key, name: role.name, description: role.description }));\n }\n\n async createApiKey(input: CreateApiKeyInput, actor: Actor): Promise<CreatedApiKey> {\n actor.permissions.require('api_keys:write');\n const roles = this.roleMap(await this.roles.storedRoles(actor.orgId));\n const role = roles.get(input.role);\n if (!role) {\n throw new NotFoundError('Role', input.role);\n }\n const missing = role.permissions.filter(\n (permission) => !actor.permissions.anywhere(permission),\n );\n if (missing.length > 0) {\n this.logger.warn('api key refused: role permissions not held', {\n orgId: actor.orgId,\n actorId: actor.id,\n roleKey: role.key,\n missing,\n });\n throw new ForbiddenError(`You don't hold ${missing.join(', ')}`);\n }\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n const created = await this.apiKeys().create(orgExternalId, userExternalId, {\n name: input.name,\n roleKey: role.key,\n expiresInDays: input.expiresInDays,\n });\n this.logger.info('api key created', {\n orgId: actor.orgId,\n actorId: actor.id,\n keyId: created.id,\n roleKey: role.key,\n });\n return { ...keySummary(created, roles), key: created.key };\n }\n\n async deleteApiKey(keyId: string, actor: Actor): Promise<void> {\n actor.permissions.require('api_keys:delete');\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n await this.apiKeys().revoke(orgExternalId, userExternalId, keyId);\n this.logger.info('api key revoked', { orgId: actor.orgId, actorId: actor.id, keyId });\n }\n\n async listConnectedApps(actor: Actor): Promise<ConnectedApp[]> {\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n return this.apiKeys().listApps(orgExternalId, userExternalId);\n }\n\n async revokeConnectedApp(clientId: string, actor: Actor): Promise<void> {\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n await this.apiKeys().revokeApp(orgExternalId, userExternalId, clientId);\n this.logger.info('connected app revoked', {\n orgId: actor.orgId,\n actorId: actor.id,\n clientId,\n });\n }\n\n async createPlatformOrganization(\n input: PlatformOrganizationInput,\n ): Promise<PlatformOrganization> {\n const ownerExternalId = await this.platformAccountId();\n const created = await this.orgAdmin().createOrganizationFor(ownerExternalId, {\n name: input.name,\n slug: input.slug,\n });\n const org = await this.repo.findByExternalId(created.id);\n if (!org) {\n throw new NotFoundError('Organization', created.id);\n }\n const apiKey = await this.platformKey(org, ownerExternalId, input.keyName ?? 'Platform');\n this.logger.info('platform organization created', { orgId: org.id, slug: org.slug });\n return {\n organization: { id: org.id, name: org.name, slug: org.slug, createdAt: org.createdAt },\n apiKey,\n };\n }\n\n async createPlatformApiKey(orgId: string, name: string): Promise<CreatedApiKey> {\n const account = this.platformAccount();\n const [org, person] = await Promise.all([\n this.repo.findById(orgId),\n this.people.getUserByEmail(account.email),\n ]);\n const orgUser = org && person ? await this.repo.findOrgUser(org.id, person.id) : null;\n if (!org || !person?.externalId || orgUser?.status !== 'active') {\n throw new NotFoundError('Organization', orgId);\n }\n const apiKey = await this.platformKey(org, person.externalId, name);\n this.logger.info('platform api key created', { orgId: org.id, keyId: apiKey.id });\n return apiKey;\n }\n\n isPlatformAccount(email: string): boolean {\n return this.platform !== undefined && email.toLowerCase() === this.platform.email;\n }\n\n private async platformKey(\n org: Organization,\n ownerExternalId: string,\n name: string,\n ): Promise<CreatedApiKey> {\n const [created, stored] = await Promise.all([\n this.apiKeys().create(org.externalId ?? org.id, ownerExternalId, {\n name,\n roleKey: OWNER_ROLE_KEY,\n }),\n this.roles.storedRoles(org.id),\n ]);\n return { ...keySummary(created, this.roleMap(stored)), key: created.key };\n }\n\n private async platformAccountId(): Promise<string> {\n const account = this.platformAccount();\n const person = await this.people.getUserByEmail(account.email);\n if (person?.externalId) {\n return person.externalId;\n }\n const { externalId } = await this.accounts().createAccount(account);\n this.logger.info('platform account created', { userId: externalId });\n return externalId;\n }\n\n private platformAccount(): PlatformAccount {\n if (!this.platform) {\n throw new Error('the platform account is not configured');\n }\n return this.platform;\n }\n\n private accounts(): Accounts {\n if (!this.accountsPort) {\n throw new Error('accounts are not configured');\n }\n return this.accountsPort();\n }\n\n private async keysWithRole(orgId: string, roleKey: string): Promise<number> {\n if (!this.apiKeysPort) {\n return 0;\n }\n const org = await this.repo.findById(orgId);\n return org ? this.apiKeysPort().countWithRole(org.externalId ?? org.id, roleKey) : 0;\n }\n\n private async cleanUpAfterRemoval(\n orgId: string,\n orgUserId: string,\n person: { email: string; externalId: string | null } | null,\n ): Promise<void> {\n const steps: Array<[string, () => Promise<unknown>]> = [];\n const org = await this.repo.findById(orgId);\n if (person?.externalId && org) {\n const orgExternalId = org.externalId ?? org.id;\n const userExternalId = person.externalId;\n steps.push([\n 'membership',\n () => this.orgAdmin().removeMembership(orgExternalId, userExternalId),\n ]);\n steps.push([\n 'api keys and tokens',\n () => this.apiKeys().revokeAllFor(orgExternalId, userExternalId),\n ]);\n }\n steps.push(['profile photo', () => this.images.syncPublicImage(orgId, orgUserId, null)]);\n if (person) {\n steps.push([\n 'pending invite',\n async () => {\n const pending = await this.repo.findPendingInvite(orgId, person.email);\n if (pending) {\n await this.repo.setInviteStatus(orgId, pending.id, 'canceled');\n }\n },\n ]);\n }\n for (const [step, run] of steps) {\n for (let attempt = 1; attempt <= 3; attempt++) {\n try {\n await run();\n break;\n } catch (err) {\n this.logger.error('cleanup after removal failed', {\n orgId,\n orgUserId,\n step,\n attempt,\n err: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }\n }\n }\n\n private apiKeys(): ApiKeys {\n if (!this.apiKeysPort) {\n throw new Error('api keys are not configured');\n }\n return this.apiKeysPort();\n }\n\n private async externalIdsOf(\n actor: Actor,\n ): Promise<{ orgExternalId: string; userExternalId: string }> {\n const [org, orgUser] = await Promise.all([\n this.repo.findById(actor.orgId),\n this.repo.findOrgUserById(actor.orgId, actor.id),\n ]);\n if (!org || !orgUser) {\n throw new NotFoundError('Person', actor.id);\n }\n const person = await this.people.getUserById(orgUser.userId);\n if (!person?.externalId) {\n throw new NotFoundError('User', orgUser.userId);\n }\n return { orgExternalId: org.externalId ?? org.id, userExternalId: person.externalId };\n }\n\n private async pendingInviteOf(\n orgId: string,\n orgUserId: string,\n ): Promise<{ invite: Invite; role: OrgRole; orgUser: OrgUser }> {\n const orgUser = await this.repo.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const person = await this.people.getUserById(orgUser.userId);\n const invite = person ? await this.repo.findPendingInvite(orgId, person.email) : null;\n if (!invite) {\n throw new NotFoundError('Invite', orgUserId);\n }\n const stored = await this.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, invite.roleKey);\n if (!role) {\n throw new NotFoundError('Role', invite.roleKey);\n }\n return { invite, role, orgUser };\n }\n\n private async deleteOrgUserRow(orgId: string, orgUser: OrgUser): Promise<OrgUser | null> {\n const held = await this.roles.assignmentsOf(orgId, orgUser.id);\n return this.uow.run((scope) => this.deleteOrgUserIn(scope, orgId, orgUser, held, SYSTEM_ID));\n }\n\n private async deleteOrgUserIn(\n scope: OrganizationsWriteScope,\n orgId: string,\n orgUser: OrgUser,\n held: { roleKey: string; contentId: string | null }[],\n actorId: string,\n ): Promise<OrgUser | null> {\n const orgRoleKey = held.find((row) => row.contentId === null)?.roleKey ?? MEMBER_ROLE_KEY;\n const deleted = await scope.organizations.deleteOrgUser(orgId, orgUser.id);\n if (!deleted) {\n return null;\n }\n const events: NewOrganizationEvent[] = [\n organizationEvents.orgUserDeleted.make({\n orgId,\n data: { ...deleted, orgRole: { key: orgRoleKey } },\n metadata: { actorId },\n }),\n ];\n if (orgRoleKey === MEMBER_ROLE_KEY) {\n events.push(organizationEvents.studentDeleted.make({ orgId, data: deleted }));\n }\n await scope.outbox.append(events);\n return deleted;\n }\n\n private async sendInviteEmail(invite: Invite, token: string, role: OrgRole): Promise<void> {\n if (!this.mailer || !this.inviteUrls) {\n throw new Error('invite delivery is not configured (mailer / invite urls missing)');\n }\n const learner = role.permissions.length === 0;\n const base = learner\n ? `${this.inviteUrls.studentPortalUrl}/welcome`\n : `${this.inviteUrls.adminAppUrl}/invite`;\n const query = learner\n ? new URLSearchParams({ token })\n : new URLSearchParams({ token, email: invite.email });\n const inviteUrl = `${base}?${query.toString()}`;\n if (learner) {\n await this.mailer.send(invite.email, 'studentInvite', {\n inviteUrl,\n studentName: invite.email,\n });\n } else {\n await this.mailer.send(invite.email, 'memberInvite', {\n inviteUrl,\n inviterName: 'Your team',\n role: role.name,\n });\n }\n }\n\n private toMember(row: TeamRow, nameOf: (key: string) => string): Member {\n const orgRoleKey =\n row.status === 'invited' && row.inviteRoleKey\n ? row.inviteRoleKey\n : (row.orgRoleKey ?? MEMBER_ROLE_KEY);\n return {\n id: row.id,\n firstName: row.firstName,\n lastName: row.lastName,\n email: row.email,\n image: row.image,\n orgRole: { key: orgRoleKey, name: nameOf(orgRoleKey) },\n isOwner: row.orgRoleKey === OWNER_ROLE_KEY,\n items: row.items.map((item) => ({ ...item, roleName: nameOf(item.roleKey) })),\n status: row.status,\n joinedAt: row.status === 'active' ? row.joinedAt.toISOString() : null,\n invitedAt: row.invitedAt ? row.invitedAt.toISOString() : null,\n };\n }\n\n private async assignmentViews(orgId: string, orgUserId: string): Promise<AssignmentView[]> {\n const [rows, stored] = await Promise.all([\n this.roles.assignmentsOf(orgId, orgUserId),\n this.roles.storedRoles(orgId),\n ]);\n const roles = this.roleMap(stored);\n const views: AssignmentView[] = rows.map((row) => ({\n orgUserId,\n roleKey: row.roleKey,\n roleName: roles.get(row.roleKey)?.name ?? row.roleKey,\n contentId: row.contentId,\n contentType: row.contentType,\n }));\n if (!rows.some((row) => row.contentId === null)) {\n views.unshift({\n orgUserId,\n roleKey: MEMBER_ROLE_KEY,\n roleName: roles.get(MEMBER_ROLE_KEY)?.name ?? 'Member',\n contentId: null,\n contentType: null,\n });\n }\n return views;\n }\n\n private roleMap(stored: readonly StoredOrgRole[]): Map<string, OrgRole> {\n return new Map(resolveOrgRoles(this.catalog, stored).map((role) => [role.key, role]));\n }\n\n private resolveIn(stored: readonly StoredOrgRole[], key: string): OrgRole | null {\n return resolveRole(\n key,\n this.catalog,\n stored.find((row) => row.key === key),\n );\n }\n\n private async findRole(orgId: string, key: string): Promise<OrgRole> {\n const role = this.resolveIn(await this.roles.storedRoles(orgId), key);\n if (!role) {\n throw new NotFoundError('Role', key);\n }\n return role;\n }\n\n private async relockedActor(scope: OrganizationsWriteScope, actor: Actor): Promise<Actor> {\n if (actor.id === SYSTEM_ID) {\n return actor;\n }\n const facts = await scope.roles.actorFacts(actor.orgId, actor.id);\n if (!facts || facts.status !== 'active') {\n throw new ForbiddenError('You are no longer an active member of this organization');\n }\n const fresh = resolvePermissions({\n assignments: facts.assignments,\n roles: this.roleMap(facts.storedRoles),\n });\n return {\n ...actor,\n permissions: {\n has: (p, on) => fresh.has(p, on) && actor.permissions.has(p, on),\n require: (p, on) => {\n if (!(fresh.has(p, on) && actor.permissions.has(p, on))) {\n throw new ForbiddenError(`You need ${p}`);\n }\n },\n anywhere: (p) => fresh.anywhere(p) && actor.permissions.anywhere(p),\n where: (p) => actor.permissions.where(p),\n roleOn: (on) => fresh.roleOn(on),\n isOwner: () => fresh.isOwner() && actor.permissions.isOwner(),\n },\n };\n }\n\n private itemPermissions(role: OrgRole | null, type: ContentType): Permission[] {\n if (!role || !role.levels.includes(type)) {\n return [];\n }\n return role.permissions.filter((p) => permissionAbout(p) === type);\n }\n\n private assertHolds(actor: Actor, permissions: readonly Permission[]): void {\n const missing = [...new Set(permissions)].filter((p) => !actor.permissions.has(p));\n if (missing.length > 0) {\n this.logger.warn('refused: editor lacks permissions', {\n orgId: actor.orgId,\n actorId: actor.id,\n missing,\n });\n throw new ForbiddenError(`You need ${missing.join(', ')}`);\n }\n }\n\n private assertHoldsOn(actor: Actor, permissions: readonly Permission[], contentId: string): void {\n const missing = [...new Set(permissions)].filter((p) => !actor.permissions.has(p, contentId));\n if (missing.length > 0) {\n this.logger.warn('refused: editor lacks permissions on the item', {\n orgId: actor.orgId,\n actorId: actor.id,\n contentId,\n missing,\n });\n throw new ForbiddenError(`You need ${missing.join(', ')} there`);\n }\n }\n\n private assertNotSelf(actor: Actor, orgUserId: string): void {\n if (actor.id === orgUserId) {\n this.logger.warn('refused: changing own roles', { orgId: actor.orgId, orgUserId });\n throw new ForbiddenError(\"You can't change your own roles\");\n }\n }\n\n private assertUniqueName(stored: readonly StoredOrgRole[], key: string, name: string): void {\n const wanted = name.trim().toLowerCase();\n if (wanted.length === 0) {\n throw new OrganizationRuleError('A role needs a name');\n }\n const taken = resolveOrgRoles(this.catalog, stored).some(\n (role) => role.key !== key && role.name.trim().toLowerCase() === wanted,\n );\n if (taken) {\n throw new OrganizationRuleError(`A role named ${name} already exists`);\n }\n }\n\n private parseLevels(levels: Level[]): Level[] {\n if (levels.length === 0) {\n throw new OrganizationRuleError('A role needs at least one level');\n }\n for (const level of levels) {\n if (!levelSchema.safeParse(level).success) {\n throw new OrganizationRuleError(`Unknown level ${String(level)}`);\n }\n }\n return [...new Set(levels)];\n }\n\n private assertFits(row: StoredOrgRole): void {\n const base = this.catalog.get(row.base);\n const levels = row.levels ?? base?.levels ?? [];\n const misfits = Object.entries(row.permissions)\n .filter(([, held]) => held)\n .map(([p]) => p as Permission)\n .filter((p) => !fitsLevels(p, levels));\n if (misfits.length > 0) {\n throw new OrganizationRuleError(\n `${misfits.join(', ')} ${misfits.length === 1 ? \"doesn't\" : \"don't\"} fit the role's levels`,\n );\n }\n }\n\n private async assertLevelsNotInUse(\n roles: RolesRepository,\n orgId: string,\n before: OrgRole,\n after: OrgRole,\n ): Promise<void> {\n const removed = before.levels.filter((level) => !after.levels.includes(level));\n for (const level of removed) {\n const count = await roles.countHolders(orgId, before.key, level);\n if (count > 0) {\n throw new OrganizationRuleError(\n `${before.name} is given on ${level === 'org' ? 'the organization' : `a ${level}`}; remove those first`,\n );\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../src/organizations/service.ts"],"sourcesContent":["import type {\n Accounts,\n ApiKeyRole,\n ApiKeys,\n AuthOrganization,\n CallerLimit,\n CreateApiKeyInput,\n GrantReader,\n MembersRepository,\n OrgAdmin,\n OrganizationService,\n OrganizationsRepository,\n OrganizationsUnitOfWork,\n OrganizationsWriteScope,\n PlatformAccount,\n PlatformOrganization,\n PlatformOrganizationInput,\n ResolvedCaller,\n RolesRepository,\n StoredApiKey,\n TeamRow,\n TransferOwnershipInput,\n} from './ports.js';\nimport type { Invite, Organization, OrgUser } from './model.js';\nimport {\n InviteError,\n OrganizationRuleError,\n type AssignmentView,\n type CreateRoleInput,\n type InviteDetails,\n type Member,\n type MembersQuery,\n type Page,\n type RoleView,\n type UpdateRoleInput,\n type ViewerPermissions,\n} from './members.js';\nimport type {\n AcceptInviteInput,\n AddOrgUserInput,\n CreateInviteInput,\n CreateOrganizationInput,\n NewOrganizationInput,\n UpdateOrganizationInput,\n} from './types.js';\nimport { organizationEvents, type OrganizationEvent } from './events.js';\nimport type { Logger, NewDomainEvent } from '../shared/ports.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { Mailer } from '../shared/mailer.js';\nimport { generateInviteToken, hashInviteToken } from '../shared/invite-token.js';\nimport { ForbiddenError, NotFoundError } from '../shared/errors.js';\nimport type { Actor, EffectivePermissions } from '../shared/actor.js';\nimport type { AuthHeaders, IdentityService, SessionAdmin } from '../identity/index.js';\nimport type { AssetFiles } from '../assets/index.js';\nimport { genId, prefixId } from '../shared/id.js';\nimport { levelSchema } from '../types/schemas/organizations.js';\nimport type {\n ApiKeySummary,\n ConnectedApp,\n ContentType,\n CreatedApiKey,\n Level,\n Permission,\n} from '../types/index.js';\nimport {\n DEFAULT_ROLES,\n MEMBER_ROLE_KEY,\n OWNER_ROLE_KEY,\n validateRoleSet,\n type RoleDefinition,\n} from './default-roles.js';\nimport {\n catalogOf,\n isSystemRole,\n resolveOrgRoles,\n resolveRole,\n type OrgRole,\n type RoleCatalog,\n type StoredOrgRole,\n} from './org-roles.js';\nimport {\n ResolvedPermissions,\n resolvePermissions,\n systemPermissions,\n} from './effective-permissions.js';\nimport {\n ALL_PERMISSIONS,\n fitsLevels,\n permissionAbout,\n permissionList,\n withImplied,\n type PermissionListEntry,\n} from './permissions.js';\n\nconst INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst SYSTEM_ID = 'system';\n\ntype NewOrganizationEvent = NewDomainEvent<OrganizationEvent>;\n\nexport interface InviteUrls {\n studentPortalUrl: string;\n adminAppUrl: string;\n}\n\nexport type OrganizationServiceParams = {\n repo: OrganizationsRepository;\n roles: RolesRepository;\n membersRepo: MembersRepository;\n people: IdentityService;\n images: Pick<AssetFiles, 'syncPublicImages'>;\n uow: OrganizationsUnitOfWork;\n orgAdmin: () => OrgAdmin;\n sessions: () => SessionAdmin;\n apiKeys?: () => ApiKeys;\n accounts?: () => Accounts;\n platform?: PlatformAccount;\n grants?: () => GrantReader;\n defaultRoles?: readonly RoleDefinition[];\n logger?: Logger;\n mailer?: Pick<Mailer, 'send'>;\n inviteUrls?: InviteUrls;\n};\n\nfunction snapshot(role: OrgRole) {\n return {\n key: role.key,\n name: role.name,\n description: role.description,\n base: role.base,\n levels: role.levels,\n team: role.team,\n permissions: role.permissions,\n };\n}\n\nfunction lockKeys(orgId: string, roleKeys: string[], orgUserIds: string[]): string[] {\n return [\n ...roleKeys.map((key) => `role:${orgId}:${key}`),\n ...orgUserIds.map((id) => `org-user:${orgId}:${id}`),\n ];\n}\n\nfunction roleView(role: OrgRole, holders: number): RoleView {\n return { ...role, holders, givable: role.key !== OWNER_ROLE_KEY };\n}\n\nfunction keySummary(key: StoredApiKey, roles: ReadonlyMap<string, OrgRole>): ApiKeySummary {\n return {\n id: key.id,\n name: key.name,\n start: key.start,\n role: key.roleKey ? { key: key.roleKey, name: roles.get(key.roleKey)?.name ?? null } : null,\n createdAt: key.createdAt,\n lastUsedAt: key.lastUsedAt,\n expiresAt: key.expiresAt,\n };\n}\n\nfunction limitScopes(\n limit: CallerLimit | undefined,\n roles: ReadonlyMap<string, OrgRole>,\n): readonly Permission[] | undefined {\n if (!limit) {\n return undefined;\n }\n if ('scopes' in limit) {\n return limit.scopes;\n }\n return roles.get(limit.roleKey)?.permissions ?? [];\n}\n\nexport class OrganizationServiceImpl implements OrganizationService {\n private readonly repo: OrganizationsRepository;\n private readonly roles: RolesRepository;\n private readonly membersRepo: MembersRepository;\n private readonly people: IdentityService;\n private readonly images: Pick<AssetFiles, 'syncPublicImages'>;\n private readonly uow: OrganizationsUnitOfWork;\n private readonly orgAdmin: () => OrgAdmin;\n private readonly sessions: () => SessionAdmin;\n private readonly apiKeysPort?: () => ApiKeys;\n private readonly accountsPort?: () => Accounts;\n private readonly platform?: PlatformAccount;\n private readonly grants?: () => GrantReader;\n private readonly catalog: RoleCatalog;\n private readonly logger: Logger;\n private readonly mailer?: Pick<Mailer, 'send'>;\n private readonly inviteUrls?: InviteUrls;\n\n constructor(params: OrganizationServiceParams) {\n this.repo = params.repo;\n this.roles = params.roles;\n this.membersRepo = params.membersRepo;\n this.people = params.people;\n this.images = params.images;\n this.uow = params.uow;\n this.orgAdmin = params.orgAdmin;\n this.sessions = params.sessions;\n this.apiKeysPort = params.apiKeys;\n this.accountsPort = params.accounts;\n this.platform = params.platform && {\n ...params.platform,\n email: params.platform.email.toLowerCase(),\n };\n this.grants = params.grants;\n const defaults = params.defaultRoles ?? DEFAULT_ROLES;\n validateRoleSet(defaults);\n this.catalog = catalogOf(defaults);\n this.logger = params.logger ?? noopLogger;\n this.mailer = params.mailer;\n this.inviteUrls = params.inviteUrls;\n }\n\n createOrganization(input: NewOrganizationInput, headers: AuthHeaders): Promise<AuthOrganization> {\n return this.orgAdmin().createOrganization(headers, input);\n }\n\n async provisionOrganization(input: CreateOrganizationInput): Promise<Organization> {\n const created = await this.uow.run(async ({ organizations, roles, outbox }) => {\n const id = genId('organization');\n const org = await organizations.create({\n id,\n externalId: input.externalId ?? id,\n name: input.name ?? 'My Org',\n slug: input.slug ?? '',\n ownerId: input.ownerId,\n });\n const owner = await organizations.createOrgUser({\n orgId: org.id,\n userId: input.ownerId,\n status: 'active',\n });\n await roles.setOrgRole(org.id, owner.id, OWNER_ROLE_KEY, SYSTEM_ID);\n await outbox.append([\n organizationEvents.organizationCreated.make({ orgId: org.id, data: org }),\n organizationEvents.orgUserLinked.make({\n orgId: org.id,\n data: { ...owner, orgRole: { key: OWNER_ROLE_KEY } },\n }),\n ]);\n return org;\n });\n this.logger.info('organization created', { orgId: created.id, slug: created.slug });\n return created;\n }\n\n async updateOrganization(input: UpdateOrganizationInput, actor: Actor): Promise<Organization> {\n actor.permissions.require('organizations:write');\n const orgId = actor.orgId;\n const org = await this.repo.findById(orgId);\n if (!org) {\n throw new NotFoundError('Organization', orgId);\n }\n if (input.slug !== undefined && input.slug !== org.slug) {\n const taken = await this.repo.findBySlug(input.slug);\n if (taken && taken.id !== orgId) {\n this.logger.warn('organization update refused: slug taken', { orgId, slug: input.slug });\n throw new OrganizationRuleError('That slug is already taken');\n }\n }\n await this.orgAdmin().updateOrganization(org.externalId ?? org.id, input);\n const updated = await this.uow.run(async ({ organizations, outbox }) => {\n const next = await organizations.update(orgId, { name: input.name, slug: input.slug });\n if (!next) {\n throw new NotFoundError('Organization', orgId);\n }\n await outbox.append([\n organizationEvents.organizationUpdated.make({\n orgId,\n data: next,\n metadata: { actorId: actor.id },\n }),\n ]);\n return next;\n });\n this.logger.info('organization updated', { orgId, actorId: actor.id });\n return updated;\n }\n\n async deleteOrganization(id: string): Promise<Organization> {\n const deleted = await this.uow.run(async ({ organizations, outbox }) => {\n const deleted = await organizations.delete(id);\n await outbox.append([\n organizationEvents.organizationDeleted.make({ orgId: deleted.id, data: deleted }),\n ]);\n return deleted;\n });\n this.logger.info('organization deleted', { orgId: deleted.id });\n return deleted;\n }\n\n async addOrgUser({ orgId, userId }: AddOrgUserInput): Promise<OrgUser> {\n const existing = await this.repo.findOrgUser(orgId, userId);\n if (existing) {\n return existing;\n }\n const orgUser = await this.uow.run(async ({ organizations, outbox }) => {\n const created = await organizations.createOrgUser({ orgId, userId, status: 'active' });\n await outbox.append([\n organizationEvents.orgUserLinked.make({\n orgId,\n data: { ...created, orgRole: { key: MEMBER_ROLE_KEY } },\n }),\n ]);\n return created;\n });\n this.logger.info('user added to organization', { orgId, userId, orgUserId: orgUser.id });\n return orgUser;\n }\n\n async removeOrgUser(orgId: string, userId: string): Promise<OrgUser | null> {\n const orgUser = await this.repo.findOrgUser(orgId, userId);\n if (!orgUser) {\n return null;\n }\n return this.deleteOrgUserRow(orgId, orgUser);\n }\n\n getByExternalId(externalId: string): Promise<Organization | null> {\n return this.repo.findByExternalId(externalId);\n }\n\n getBySlug(slug: string): Promise<Organization | null> {\n return this.repo.findBySlug(slug);\n }\n\n getById(id: string): Promise<Organization | null> {\n return this.repo.findById(id);\n }\n\n async portalIdentity(id: string): Promise<Pick<Organization, 'id' | 'name' | 'slug'>> {\n const org = await this.repo.findById(id);\n if (!org) {\n throw new NotFoundError('Organization', id);\n }\n return { id: org.id, name: org.name, slug: org.slug };\n }\n\n getOrgUser(orgId: string, userId: string): Promise<OrgUser | null> {\n return this.repo.findOrgUser(orgId, userId);\n }\n\n getOrgUserById(orgId: string, id: string): Promise<OrgUser | null> {\n return this.repo.findOrgUserById(orgId, id);\n }\n\n async getOrgUsersByIds(orgId: string, ids: string[]): Promise<OrgUser[]> {\n const unique = [...new Set(ids)];\n return unique.length > 0 ? this.repo.findOrgUsersByIds(orgId, unique) : [];\n }\n\n getOrgUsersForUser(userId: string): Promise<OrgUser[]> {\n return this.repo.findOrgUsersByUser(userId);\n }\n\n orgIds(): Promise<string[]> {\n return this.repo.listIds();\n }\n\n async actorFor(orgId: string, orgUserId: string, limit?: CallerLimit): Promise<Actor | null> {\n const facts = await this.roles.actorFacts(orgId, orgUserId);\n if (!facts || facts.status !== 'active') {\n return null;\n }\n const roles = this.roleMap(facts.storedRoles);\n const tokenScopes = limitScopes(limit, roles);\n return {\n id: orgUserId,\n orgId,\n permissions: resolvePermissions({\n assignments: facts.assignments,\n roles,\n ...(tokenScopes !== undefined && { tokenScopes }),\n }),\n };\n }\n\n async resolveCaller(\n authOrgId: string,\n authUserId: string,\n limit?: CallerLimit,\n ): Promise<ResolvedCaller | null> {\n const facts = await this.roles.callerFacts(authOrgId, authUserId);\n if (!facts) {\n return null;\n }\n const orgUser = facts.orgUser;\n if (orgUser?.status !== 'active') {\n return {\n orgId: facts.orgId,\n userId: facts.userId,\n orgUserId: orgUser?.orgUserId ?? null,\n actor: null,\n };\n }\n const roles = this.roleMap(orgUser.storedRoles);\n const tokenScopes = limitScopes(limit, roles);\n return {\n orgId: facts.orgId,\n userId: facts.userId,\n orgUserId: orgUser.orgUserId,\n actor: {\n id: orgUser.orgUserId,\n orgId: facts.orgId,\n permissions: resolvePermissions({\n assignments: orgUser.assignments,\n roles,\n ...(tokenScopes !== undefined && { tokenScopes }),\n }),\n },\n };\n }\n\n systemActor(orgId: string): Actor {\n return { id: SYSTEM_ID, orgId, permissions: systemPermissions() };\n }\n\n async permissionsOfMany(\n orgId: string,\n orgUserIds: string[],\n ): Promise<Map<string, EffectivePermissions>> {\n const unique = [...new Set(orgUserIds)];\n const out = new Map<string, EffectivePermissions>();\n if (unique.length === 0) {\n return out;\n }\n const [stored, assignments] = await Promise.all([\n this.roles.storedRoles(orgId),\n this.roles.assignmentsOfMany(orgId, unique),\n ]);\n const roles = this.roleMap(stored);\n for (const id of unique) {\n out.set(id, resolvePermissions({ assignments: assignments.get(id) ?? [], roles }));\n }\n return out;\n }\n\n async holders(orgId: string, permission: Permission, on?: string): Promise<string[]> {\n const stored = await this.roles.storedRoles(orgId);\n const keys = resolveOrgRoles(this.catalog, stored)\n .filter((role) => withImplied(role.permissions).has(permission))\n .map((role) => role.key);\n const candidates = await this.roles.holdersOf(orgId, keys, on);\n if (candidates.length === 0) {\n return [];\n }\n const permissions = await this.permissionsOfMany(orgId, candidates);\n return candidates.filter((id) => permissions.get(id)?.has(permission, on) ?? false);\n }\n\n permissionList(): PermissionListEntry[] {\n return permissionList();\n }\n\n viewerPermissions(actor: Actor): ViewerPermissions {\n const role = actor.permissions.roleOn();\n if (actor.permissions instanceof ResolvedPermissions) {\n return {\n orgRole: { key: role.key, name: role.name },\n isOwner: actor.permissions.isOwner(),\n org: actor.permissions.orgPermissions(),\n content: actor.permissions.contentPermissions(),\n };\n }\n return {\n orgRole: { key: role.key, name: role.name },\n isOwner: actor.permissions.isOwner(),\n org: ALL_PERMISSIONS.filter((p) => actor.permissions.has(p)),\n content: {},\n };\n }\n\n async auditRoleKeys(): Promise<number> {\n const usage = await this.roles.roleKeyUsage();\n const storedByOrg = new Map<string, StoredOrgRole[]>();\n let dangling = 0;\n for (const row of usage) {\n if (!storedByOrg.has(row.orgId)) {\n storedByOrg.set(row.orgId, await this.roles.storedRoles(row.orgId));\n }\n const role = this.resolveIn(storedByOrg.get(row.orgId)!, row.roleKey);\n if (!role) {\n dangling += row.count;\n this.logger.warn('assignments name a role the set no longer has', {\n orgId: row.orgId,\n roleKey: row.roleKey,\n level: row.level,\n count: row.count,\n });\n } else if (!role.levels.includes(row.level as Level)) {\n dangling += row.count;\n this.logger.warn('assignments sit at a level their role no longer lists', {\n orgId: row.orgId,\n roleKey: row.roleKey,\n level: row.level,\n count: row.count,\n });\n }\n }\n return dangling;\n }\n\n async listRoles(actor: Actor): Promise<RoleView[]> {\n actor.permissions.require('roles:read');\n const [stored, counts] = await Promise.all([\n this.roles.storedRoles(actor.orgId),\n this.roles.holderCounts(actor.orgId),\n ]);\n return resolveOrgRoles(this.catalog, stored).map((role) =>\n roleView(role, counts[role.key] ?? 0),\n );\n }\n\n async getRole(key: string, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:read');\n const role = await this.findRole(actor.orgId, key);\n const holders = await this.roles.countHolders(actor.orgId, key);\n return roleView(role, holders);\n }\n\n async updateRole(key: string, input: UpdateRoleInput, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n const changesAccess =\n input.levels !== undefined || input.team !== undefined || input.permissions !== undefined;\n const result = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n const current = stored.find((row) => row.key === key);\n const before = this.resolveIn(stored, key);\n if (!before) {\n throw new NotFoundError('Role', key);\n }\n if (changesAccess && isSystemRole(key)) {\n throw new OrganizationRuleError(`${before.name} can only be renamed`);\n }\n if (input.name !== undefined) {\n this.assertUniqueName(stored, key, input.name);\n }\n const next: StoredOrgRole = {\n key,\n name: input.name ?? current?.name ?? null,\n description: input.description ?? current?.description ?? null,\n base: current?.base ?? before.base,\n levels: input.levels ? this.parseLevels(input.levels) : (current?.levels ?? null),\n permissions: { ...(current?.permissions ?? {}), ...(input.permissions ?? {}) },\n team: input.team ?? current?.team ?? null,\n };\n const after = resolveRole(key, this.catalog, next);\n if (!after) {\n throw new NotFoundError('Role', key);\n }\n if (changesAccess) {\n this.assertFits(next);\n this.assertHolds(editor, [...before.permissions, ...after.permissions]);\n await this.assertLevelsNotInUse(roles, orgId, before, after);\n }\n await roles.saveStoredRole(orgId, next);\n await outbox.append([\n organizationEvents.roleUpdated.make({\n orgId,\n data: { key, before: snapshot(before), after: snapshot(after) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return after;\n });\n this.logger.info('role updated', { orgId, roleKey: key, actorId: actor.id });\n return roleView(result, await this.roles.countHolders(orgId, key));\n }\n\n async createRole(input: CreateRoleInput, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n const base = this.catalog.get(input.base);\n if (!base || isSystemRole(input.base)) {\n throw new OrganizationRuleError('A role is added from one of the deployment roles');\n }\n const key = prefixId('role');\n const created = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [key, `name:${input.name.trim().toLowerCase()}`], [actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n this.assertUniqueName(stored, key, input.name);\n const row: StoredOrgRole = {\n key,\n name: input.name,\n description: input.description ?? null,\n base: input.base,\n levels: input.levels ? this.parseLevels(input.levels) : null,\n permissions: input.permissions ?? {},\n team: input.team ?? null,\n };\n this.assertFits(row);\n const role = resolveRole(key, this.catalog, row)!;\n this.assertHolds(editor, role.permissions);\n await roles.saveStoredRole(orgId, row);\n await outbox.append([\n organizationEvents.roleCreated.make({\n orgId,\n data: { role: snapshot(role) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return role;\n });\n this.logger.info('role created', { orgId, roleKey: key, actorId: actor.id });\n return roleView(created, 0);\n }\n\n async resetRole(key: string, actor: Actor): Promise<RoleView> {\n actor.permissions.require('roles:write');\n const orgId = actor.orgId;\n if (!this.catalog.has(key)) {\n throw new OrganizationRuleError('Only a deployment role can be reset');\n }\n const result = await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('roles:write');\n const stored = await roles.storedRoles(orgId);\n const before = this.resolveIn(stored, key);\n const after = resolveRole(key, this.catalog, undefined);\n if (!before || !after) {\n throw new NotFoundError('Role', key);\n }\n this.assertUniqueName(\n stored.filter((row) => row.key !== key),\n key,\n after.name,\n );\n this.assertHolds(editor, [...before.permissions, ...after.permissions]);\n await this.assertLevelsNotInUse(roles, orgId, before, after);\n await roles.deleteStoredRole(orgId, key);\n await outbox.append([\n organizationEvents.roleUpdated.make({\n orgId,\n data: { key, before: snapshot(before), after: snapshot(after) },\n metadata: { actorId: actor.id },\n }),\n ]);\n return after;\n });\n this.logger.info('role reset', { orgId, roleKey: key, actorId: actor.id });\n return roleView(result, await this.roles.countHolders(orgId, key));\n }\n\n async deleteRole(key: string, actor: Actor): Promise<void> {\n actor.permissions.require('roles:delete');\n const orgId = actor.orgId;\n if (this.catalog.has(key)) {\n throw new OrganizationRuleError('A deployment role can be renamed and reset, not deleted');\n }\n const keys = await this.keysWithRole(orgId, key);\n if (keys > 0) {\n this.logger.warn('role deletion refused: role is on api keys', { orgId, roleKey: key, keys });\n throw new OrganizationRuleError(\n `This role is on ${keys} API ${keys === 1 ? 'key' : 'keys'}; revoke ${keys === 1 ? 'it' : 'them'} first`,\n );\n }\n await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, [key], [actor.id]));\n (await this.relockedActor(scope, actor)).permissions.require('roles:delete');\n const holders = await roles.countHolders(orgId, key);\n if (holders > 0) {\n this.logger.warn('role deletion refused: role is held', { orgId, roleKey: key, holders });\n throw new OrganizationRuleError(\n `This role is held by ${holders} ${holders === 1 ? 'person' : 'people'}`,\n );\n }\n const deleted = await roles.deleteStoredRole(orgId, key);\n if (!deleted) {\n throw new NotFoundError('Role', key);\n }\n await outbox.append([\n organizationEvents.roleDeleted.make({\n orgId,\n data: { key },\n metadata: { actorId: actor.id },\n }),\n ]);\n });\n this.logger.info('role deleted', { orgId, roleKey: key, actorId: actor.id });\n }\n\n async listTeam(query: MembersQuery, actor: Actor): Promise<Page<Member>> {\n actor.permissions.require('people:read');\n const orgId = actor.orgId;\n const [rows, stored] = await Promise.all([\n this.membersRepo.teamRows(orgId, MEMBER_ROLE_KEY),\n this.roles.storedRoles(orgId),\n ]);\n const roles = this.roleMap(stored);\n const nameOf = (key: string): string => roles.get(key)?.name ?? key;\n let members = rows.map((row) => this.toMember(row, nameOf));\n if (query.roleKey) {\n members = members.filter(\n (m) => m.orgRole.key === query.roleKey || m.items.some((i) => i.roleKey === query.roleKey),\n );\n }\n if (query.status) {\n members = members.filter((m) => m.status === query.status);\n }\n const q = query.search?.trim().toLowerCase();\n if (q) {\n members = members.filter((m) =>\n [m.firstName, m.lastName, m.email].some((v) => v?.toLowerCase().includes(q)),\n );\n }\n const sort = query.sort;\n const desc = sort?.startsWith('-') ?? false;\n const key = desc ? sort!.slice(1) : sort;\n const byName = (a: string | null, b: string | null): number =>\n a === b ? 0 : a === null ? 1 : b === null ? -1 : a.localeCompare(b);\n members.sort((a, b) => {\n const cmp =\n key === 'email'\n ? a.email.localeCompare(b.email)\n : key === 'role'\n ? a.orgRole.name.localeCompare(b.orgRole.name)\n : key === 'lastName'\n ? byName(a.lastName, b.lastName) || byName(a.firstName, b.firstName)\n : byName(a.firstName, b.firstName) || byName(a.lastName, b.lastName);\n return desc ? -cmp : cmp;\n });\n const start = (query.page - 1) * query.pageSize;\n return {\n rows: members.slice(start, start + query.pageSize),\n total: members.length,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n async listAssignments(orgUserId: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:read');\n return this.assignmentViews(actor.orgId, orgUserId);\n }\n\n async listAssignmentsOn(contentId: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:read');\n const [rows, stored] = await Promise.all([\n this.roles.assignmentsOn(actor.orgId, contentId),\n this.roles.storedRoles(actor.orgId),\n ]);\n const roles = this.roleMap(stored);\n return rows.map((row) => ({\n orgUserId: row.orgUserId,\n roleKey: row.roleKey,\n roleName: roles.get(row.roleKey)?.name ?? row.roleKey,\n contentId: row.contentId,\n contentType: row.contentType,\n }));\n }\n\n async setOrgRole(orgUserId: string, roleKey: string, actor: Actor): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === null,\n );\n const target = await this.repo.findOrgUserById(orgId, orgUserId);\n const invitee =\n target?.status === 'invited' ? await this.people.getUserById(target.userId) : null;\n await this.uow.run(async (scope) => {\n const { roles, organizations, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [roleKey, seen?.roleKey ?? MEMBER_ROLE_KEY], [orgUserId, actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const orgUser = await organizations.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const stored = await roles.storedRoles(orgId);\n const next = this.resolveIn(stored, roleKey);\n if (!next) {\n throw new NotFoundError('Role', roleKey);\n }\n if (roleKey === OWNER_ROLE_KEY) {\n throw new OrganizationRuleError('Ownership moves only by transfer');\n }\n if (!next.levels.includes('org')) {\n throw new OrganizationRuleError(`${next.name} can't be given on the organization`);\n }\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === null,\n );\n if (current?.roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('org role change refused: target is the owner', { orgId, orgUserId });\n throw new OrganizationRuleError(\"The owner's role changes only by transfer\");\n }\n if (orgUser.status === 'invited') {\n const person = invitee?.id === orgUser.userId ? invitee : null;\n const pending = person ? await organizations.findPendingInvite(orgId, person.email) : null;\n if (!pending) {\n throw new NotFoundError('Invite', orgUserId);\n }\n const invited = this.resolveIn(stored, pending.roleKey);\n this.assertHolds(editor, [...(invited?.permissions ?? []), ...next.permissions]);\n const editorUser = await organizations.findOrgUserById(orgId, actor.id);\n if (!editorUser) {\n throw new ForbiddenError('You are no longer an active member of this organization');\n }\n await organizations.setInviteRole(orgId, pending.id, roleKey, editorUser.userId);\n this.logger.info('pending invite role changed', {\n orgId,\n orgUserId,\n inviteId: pending.id,\n roleKey,\n actorId: actor.id,\n });\n return;\n }\n const previousKey = current?.roleKey ?? MEMBER_ROLE_KEY;\n const previous = this.resolveIn(stored, previousKey);\n this.assertHolds(editor, [...(previous?.permissions ?? []), ...next.permissions]);\n await roles.setOrgRole(\n orgId,\n orgUserId,\n roleKey === MEMBER_ROLE_KEY ? null : roleKey,\n actor.id,\n );\n if (previousKey !== roleKey) {\n await outbox.append([\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey,\n contentId: null,\n contentType: null,\n previousRoleKey: previousKey,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n this.logger.info('org role set', { orgId, orgUserId, roleKey, actorId: actor.id });\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async assignRole(\n orgUserId: string,\n contentId: string,\n roleKey: string,\n actor: Actor,\n ): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n await this.uow.run(async (scope) => {\n const { roles, organizations, outbox } = scope;\n await roles.lock(\n lockKeys(orgId, [roleKey, ...(seen ? [seen.roleKey] : [])], [orgUserId, actor.id]),\n );\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const orgUser = await organizations.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const contentType = await roles.contentTypeOf(orgId, contentId);\n if (!contentType) {\n throw new NotFoundError('Content', contentId);\n }\n const stored = await roles.storedRoles(orgId);\n const next = this.resolveIn(stored, roleKey);\n if (!next) {\n throw new NotFoundError('Role', roleKey);\n }\n if (isSystemRole(roleKey) || !next.levels.includes(contentType)) {\n this.logger.warn('role assignment refused: level not listed', {\n orgId,\n roleKey,\n contentType,\n });\n throw new OrganizationRuleError(`${next.name} can't be given on a ${contentType}`);\n }\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n const previous = current ? this.resolveIn(stored, current.roleKey) : null;\n this.assertHoldsOn(\n editor,\n [\n ...this.itemPermissions(previous, contentType),\n ...this.itemPermissions(next, contentType),\n ],\n contentId,\n );\n await roles.setItemRole(orgId, orgUserId, contentId, contentType, roleKey, actor.id);\n if (current?.roleKey !== roleKey) {\n await outbox.append([\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey,\n contentId,\n contentType,\n previousRoleKey: current?.roleKey ?? null,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n });\n this.logger.info('item role given', {\n orgId,\n orgUserId,\n contentId,\n roleKey,\n actorId: actor.id,\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async unassignRole(\n orgUserId: string,\n contentId: string,\n actor: Actor,\n ): Promise<AssignmentView[]> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const seen = (await this.roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n await this.uow.run(async (scope) => {\n const { roles, outbox } = scope;\n await roles.lock(lockKeys(orgId, seen ? [seen.roleKey] : [], [orgUserId, actor.id]));\n const current = (await roles.assignmentsOf(orgId, orgUserId)).find(\n (row) => row.contentId === contentId,\n );\n if (!current || !current.contentType) {\n throw new NotFoundError('Role assignment', contentId);\n }\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:write');\n const stored = await roles.storedRoles(orgId);\n const role = this.resolveIn(stored, current.roleKey);\n this.assertHoldsOn(editor, this.itemPermissions(role, current.contentType), contentId);\n const removed = await roles.removeItemRole(orgId, orgUserId, contentId);\n if (removed) {\n await outbox.append([\n organizationEvents.roleUnassigned.make({\n orgId,\n data: {\n orgUserId,\n roleKey: removed.roleKey,\n contentId,\n contentType: current.contentType,\n },\n metadata: { actorId: actor.id },\n }),\n ]);\n }\n });\n this.logger.info('item role removed', {\n orgId,\n orgUserId,\n contentId,\n actorId: actor.id,\n });\n return this.assignmentViews(orgId, orgUserId);\n }\n\n async removePerson(orgUserId: string, actor: Actor): Promise<void> {\n actor.permissions.require('people:delete');\n const orgId = actor.orgId;\n this.assertNotSelf(actor, orgUserId);\n const orgUser = await this.repo.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const person = await this.people.getUserById(orgUser.userId);\n await this.uow.run(async (scope) => {\n const { roles } = scope;\n await roles.lock(lockKeys(orgId, [], [orgUserId, actor.id]));\n const editor = await this.relockedActor(scope, actor);\n editor.permissions.require('people:delete');\n const held = await roles.assignmentsOf(orgId, orgUserId);\n if (held.some((row) => row.roleKey === OWNER_ROLE_KEY)) {\n this.logger.warn('removal refused: target is the owner', { orgId, orgUserId });\n throw new OrganizationRuleError('The owner cannot be removed');\n }\n const stored = await roles.storedRoles(orgId);\n for (const row of held) {\n const role = this.resolveIn(stored, row.roleKey);\n if (!role) {\n continue;\n }\n if (row.contentId === null) {\n this.assertHolds(editor, role.permissions);\n } else if (row.contentType) {\n this.assertHoldsOn(editor, this.itemPermissions(role, row.contentType), row.contentId);\n }\n }\n await this.deleteOrgUserIn(scope, orgId, orgUser, held, actor.id);\n });\n this.logger.info('person removed', { orgId, orgUserId, actorId: actor.id });\n await this.cleanUpAfterRemoval(orgId, orgUserId, person);\n }\n\n async transferOwnership(input: TransferOwnershipInput, actor: Actor): Promise<void> {\n if (!actor.permissions.isOwner()) {\n this.logger.warn('ownership transfer refused: caller is not the owner', {\n orgId: actor.orgId,\n actorId: actor.id,\n });\n throw new ForbiddenError('Only the owner can transfer ownership');\n }\n const orgId = actor.orgId;\n const previousRoleKey = input.previousOwnerRoleKey ?? MEMBER_ROLE_KEY;\n if (input.newOwnerOrgUserId === actor.id) {\n throw new OrganizationRuleError('You already own this organization');\n }\n const stored = await this.roles.storedRoles(orgId);\n const previousRole = this.resolveIn(stored, previousRoleKey);\n if (\n !previousRole ||\n previousRoleKey === OWNER_ROLE_KEY ||\n !previousRole.levels.includes('org')\n ) {\n throw new OrganizationRuleError('The previous owner needs a role given on the organization');\n }\n const [org, newOwner, previousOwner] = await Promise.all([\n this.repo.findById(orgId),\n this.repo.findOrgUserById(orgId, input.newOwnerOrgUserId),\n this.repo.findOrgUserById(orgId, actor.id),\n ]);\n if (!org || !previousOwner) {\n throw new NotFoundError('Organization', orgId);\n }\n if (!newOwner || newOwner.status !== 'active') {\n throw new OrganizationRuleError('The new owner must be an active member of the organization');\n }\n const [newPerson, previousPerson] = await Promise.all([\n this.people.getUserById(newOwner.userId),\n this.people.getUserById(previousOwner.userId),\n ]);\n if (!newPerson?.externalId || !previousPerson?.externalId) {\n throw new OrganizationRuleError('Both people need an account');\n }\n const orgExternalId = org.externalId ?? org.id;\n await this.orgAdmin().setMembershipOwner(orgExternalId, newPerson.externalId, true);\n await this.orgAdmin().setMembershipOwner(orgExternalId, previousPerson.externalId, false);\n await this.uow.run(async ({ roles, outbox }) => {\n await roles.lock(\n lockKeys(orgId, [OWNER_ROLE_KEY, previousRoleKey], [newOwner.id, previousOwner.id]),\n );\n const owner = await roles.ownerOrgUserId(orgId);\n if (owner !== previousOwner.id) {\n throw new ForbiddenError('Only the owner can transfer ownership');\n }\n await roles.setOrgRole(orgId, newOwner.id, null, actor.id);\n await roles.setOrgRole(\n orgId,\n previousOwner.id,\n previousRoleKey === MEMBER_ROLE_KEY ? null : previousRoleKey,\n actor.id,\n );\n await roles.setOrgRole(orgId, newOwner.id, OWNER_ROLE_KEY, actor.id);\n await outbox.append([\n organizationEvents.ownershipTransferred.make({\n orgId,\n data: { previousOwnerOrgUserId: previousOwner.id, newOwnerOrgUserId: newOwner.id },\n metadata: { actorId: actor.id },\n }),\n ]);\n });\n this.logger.info('ownership transferred', {\n orgId,\n previousOwnerOrgUserId: previousOwner.id,\n newOwnerOrgUserId: newOwner.id,\n });\n }\n\n async createInvite(\n input: CreateInviteInput,\n actor: Actor,\n inviterUserId: string,\n ): Promise<Invite> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const roleKey = input.roleKey ?? MEMBER_ROLE_KEY;\n const email = input.email;\n if (roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('invite refused: ownership cannot be granted', { orgId });\n throw new OrganizationRuleError('Ownership moves only by transfer');\n }\n const stored = await this.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, roleKey);\n if (!role) {\n throw new NotFoundError('Role', roleKey);\n }\n if (!role.levels.includes('org')) {\n throw new OrganizationRuleError(`${role.name} can't be given on the organization`);\n }\n this.assertHolds(actor, role.permissions);\n const known = await this.people.getUserByEmail(email);\n const existing = known ? await this.repo.findOrgUser(orgId, known.id) : null;\n if (existing?.id === actor.id) {\n this.logger.warn('invite refused: inviting yourself', { orgId, actorId: actor.id });\n throw new ForbiddenError(\"You can't change your own roles\");\n }\n let contributed = role.permissions;\n if (existing) {\n const held = await this.roles.assignmentsOf(orgId, existing.id);\n const current = held.find((row) => row.contentId === null);\n if (current?.roleKey === OWNER_ROLE_KEY) {\n this.logger.warn('invite refused: target is the owner', { orgId });\n throw new OrganizationRuleError('The owner cannot be invited');\n }\n const currentRole = this.resolveIn(stored, current?.roleKey ?? MEMBER_ROLE_KEY);\n contributed = [...contributed, ...(currentRole?.permissions ?? [])];\n }\n this.assertHolds(actor, contributed);\n const person =\n known ??\n (await this.people.createUser({\n email,\n ...(input.firstName !== undefined && { firstName: input.firstName }),\n ...(input.lastName !== undefined && { lastName: input.lastName }),\n }));\n const sendEmail = input.sendEmail ?? true;\n const { token, tokenHash } = generateInviteToken();\n const expiresAt = new Date(Date.now() + INVITE_TTL_MS);\n const invite = await this.uow.run(async ({ organizations, outbox }) => {\n const events: NewOrganizationEvent[] = [];\n if (!existing) {\n const orgUser = await organizations.createOrgUser({\n orgId,\n userId: person.id,\n status: 'invited',\n });\n events.push(\n roleKey === MEMBER_ROLE_KEY\n ? organizationEvents.studentCreated.make({ orgId, data: orgUser })\n : organizationEvents.orgUserLinked.make({\n orgId,\n data: { ...orgUser, orgRole: { key: MEMBER_ROLE_KEY } },\n }),\n );\n }\n const row = await organizations.upsertPendingInvite(orgId, {\n email,\n roleKey,\n invitedBy: inviterUserId,\n tokenHash,\n expiresAt,\n });\n events.push(\n organizationEvents.inviteCreated.make({\n orgId,\n data: row,\n metadata: { actorId: actor.id },\n }),\n );\n await outbox.append(events);\n return row;\n });\n if (sendEmail) {\n try {\n await this.sendInviteEmail(invite, token, role);\n } catch (err) {\n this.logger.error('failed to send invite email', {\n orgId,\n inviteId: invite.id,\n roleKey,\n err: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }\n this.logger.info('invite created', {\n orgId,\n inviteId: invite.id,\n roleKey,\n sendEmail,\n actorId: actor.id,\n });\n return invite;\n }\n\n async resendInvite(orgUserId: string, actor: Actor, inviterUserId: string): Promise<void> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const { invite, role } = await this.pendingInviteOf(orgId, orgUserId);\n this.assertHolds(actor, role.permissions);\n const { token, tokenHash } = generateInviteToken();\n const expiresAt = new Date(Date.now() + INVITE_TTL_MS);\n const refreshed = await this.repo.setInviteToken(\n orgId,\n invite.id,\n tokenHash,\n expiresAt,\n inviterUserId,\n );\n if (!refreshed) {\n throw new NotFoundError('Invite', invite.id);\n }\n await this.sendInviteEmail(refreshed, token, role);\n this.logger.info('invite resent', {\n orgId,\n orgUserId,\n inviteId: invite.id,\n actorId: actor.id,\n });\n }\n\n async cancelInvite(orgUserId: string, actor: Actor): Promise<void> {\n actor.permissions.require('people:write');\n const orgId = actor.orgId;\n const { invite, role, orgUser } = await this.pendingInviteOf(orgId, orgUserId);\n this.assertHolds(actor, role.permissions);\n const held = await this.roles.assignmentsOf(orgId, orgUserId);\n const holdsGrant = this.grants ? await this.grants().holdsAnyGrant(orgId, orgUserId) : true;\n await this.uow.run(async (scope) => {\n const canceled = await scope.organizations.setInviteStatus(orgId, invite.id, 'canceled');\n if (!canceled) {\n throw new NotFoundError('Invite', invite.id);\n }\n await scope.outbox.append([\n organizationEvents.inviteCanceled.make({\n orgId,\n data: canceled,\n metadata: { actorId: actor.id },\n }),\n ]);\n if (orgUser.status === 'invited' && held.length === 0 && !holdsGrant) {\n await this.deleteOrgUserIn(scope, orgId, orgUser, held, actor.id);\n }\n });\n this.logger.info('invite canceled', {\n orgId,\n orgUserId,\n inviteId: invite.id,\n actorId: actor.id,\n });\n }\n\n async peekInvite(token: string): Promise<Invite | null> {\n const invite = await this.repo.findInviteByTokenHash(hashInviteToken(token));\n if (!invite || invite.status !== 'pending') {\n return null;\n }\n if (invite.expiresAt && invite.expiresAt < new Date()) {\n return null;\n }\n return invite;\n }\n\n async describeInvite(token: string): Promise<InviteDetails> {\n const invite = await this.peekInvite(token);\n if (!invite) {\n throw new NotFoundError('Invite', 'token');\n }\n const person = await this.people.getUserByEmail(invite.email);\n return {\n email: invite.email,\n firstName: person?.firstName ?? null,\n lastName: person?.lastName ?? null,\n };\n }\n\n async acceptInvite(input: AcceptInviteInput, headers: AuthHeaders): Promise<OrgUser> {\n const invite = await this.peekInvite(input.token);\n if (!invite) {\n this.logger.warn('invite accept refused: token invalid or expired');\n throw new InviteError('invalid invite');\n }\n if (invite.email.toLowerCase() !== input.email.toLowerCase()) {\n this.logger.warn('invite accept refused: email mismatch', {\n orgId: invite.orgId,\n inviteId: invite.id,\n });\n throw new InviteError('emails must match');\n }\n const orgId = invite.orgId;\n const org = await this.repo.findById(orgId);\n if (!org) {\n throw new InviteError('Org not found');\n }\n const person = await this.people.getUserByExternalId(input.authUserId);\n if (!person?.externalId) {\n throw new NotFoundError('User', input.authUserId);\n }\n const orgUser = await this.repo.findOrgUser(orgId, person.id);\n if (!orgUser) {\n throw new NotFoundError('Person', person.id);\n }\n const inviter = await this.repo.findOrgUser(orgId, invite.invitedBy);\n if (!inviter) {\n this.logger.warn('invite accept refused: inviter left', { orgId, inviteId: invite.id });\n throw new InviteError('This invitation is no longer valid; ask for a new one');\n }\n await this.uow.run((scope) => this.checkAcceptance(scope, invite, orgUser, inviter.id));\n await this.orgAdmin().grantMembership(org.externalId ?? org.id, person.externalId);\n const accepted = await this.uow.run(async (scope) => {\n const { organizations, roles, outbox } = scope;\n const seen = (await roles.assignmentsOf(orgId, orgUser.id)).find(\n (row) => row.contentId === null,\n );\n await roles.lock(\n lockKeys(\n orgId,\n [invite.roleKey, seen?.roleKey ?? MEMBER_ROLE_KEY],\n [orgUser.id, inviter.id],\n ),\n );\n const previousKey = await this.checkAcceptance(scope, invite, orgUser, inviter.id);\n const activated =\n orgUser.status === 'active'\n ? orgUser\n : await organizations.updateOrgUser(orgId, orgUser.id, { status: 'active' });\n if (!activated) {\n throw new NotFoundError('Person', orgUser.id);\n }\n const acceptedInvite = await organizations.setInviteStatus(orgId, invite.id, 'accepted');\n if (!acceptedInvite) {\n throw new NotFoundError('Invite', invite.id);\n }\n await roles.setOrgRole(\n orgId,\n orgUser.id,\n invite.roleKey === MEMBER_ROLE_KEY ? null : invite.roleKey,\n inviter.id,\n );\n const events: NewOrganizationEvent[] = [\n organizationEvents.inviteAccepted.make({ orgId, data: acceptedInvite }),\n ];\n if (orgUser.status !== 'active') {\n events.push(\n organizationEvents.orgUserUpdated.make({\n orgId,\n data: { ...activated, orgRole: { key: invite.roleKey } },\n }),\n );\n if (invite.roleKey === MEMBER_ROLE_KEY) {\n events.push(organizationEvents.studentLinked.make({ orgId, data: activated }));\n }\n }\n if (previousKey !== invite.roleKey) {\n events.push(\n organizationEvents.roleAssigned.make({\n orgId,\n data: {\n orgUserId: orgUser.id,\n roleKey: invite.roleKey,\n contentId: null,\n contentType: null,\n previousRoleKey: previousKey,\n },\n metadata: { actorId: inviter.id },\n }),\n );\n }\n await outbox.append(events);\n return activated;\n });\n await this.sessions().stampActiveOrganization(headers, orgId);\n this.logger.info('invite accepted', { orgId, inviteId: invite.id, orgUserId: orgUser.id });\n return accepted;\n }\n\n private async checkAcceptance(\n scope: OrganizationsWriteScope,\n invite: Invite,\n orgUser: OrgUser,\n inviterOrgUserId: string,\n ): Promise<string> {\n const orgId = invite.orgId;\n const stored = await scope.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, invite.roleKey);\n if (!role || invite.roleKey === OWNER_ROLE_KEY) {\n throw new InviteError('The invited role no longer exists');\n }\n const current = (await scope.roles.assignmentsOf(orgId, orgUser.id)).find(\n (row) => row.contentId === null,\n );\n if (current?.roleKey === OWNER_ROLE_KEY) {\n throw new InviteError(\"The owner's role changes only by transfer\");\n }\n const currentRole = this.resolveIn(stored, current?.roleKey ?? MEMBER_ROLE_KEY);\n const facts = await scope.roles.actorFacts(orgId, inviterOrgUserId);\n const inviter =\n facts && facts.status === 'active'\n ? resolvePermissions({\n assignments: facts.assignments,\n roles: this.roleMap(facts.storedRoles),\n })\n : null;\n const needed: Permission[] = [\n 'people:write',\n ...role.permissions,\n ...(currentRole?.permissions ?? []),\n ];\n const missing = inviter ? needed.filter((p) => !inviter.has(p)) : needed;\n if (missing.length > 0) {\n this.logger.warn('invite accept refused: inviter no longer holds the role', {\n orgId,\n inviteId: invite.id,\n inviterOrgUserId,\n missing,\n });\n throw new InviteError('This invitation is no longer valid; ask for a new one');\n }\n return current?.roleKey ?? MEMBER_ROLE_KEY;\n }\n\n async listApiKeys(actor: Actor): Promise<ApiKeySummary[]> {\n actor.permissions.require('api_keys:read');\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n const [keys, stored] = await Promise.all([\n this.apiKeys().list(orgExternalId, userExternalId),\n this.roles.storedRoles(actor.orgId),\n ]);\n const roles = this.roleMap(stored);\n return keys.map((key) => keySummary(key, roles));\n }\n\n async listApiKeyRoles(actor: Actor): Promise<ApiKeyRole[]> {\n actor.permissions.require('api_keys:write');\n const stored = await this.roles.storedRoles(actor.orgId);\n return resolveOrgRoles(this.catalog, stored)\n .filter((role) =>\n role.permissions.every((permission) => actor.permissions.anywhere(permission)),\n )\n .map((role) => ({ key: role.key, name: role.name, description: role.description }));\n }\n\n async createApiKey(input: CreateApiKeyInput, actor: Actor): Promise<CreatedApiKey> {\n actor.permissions.require('api_keys:write');\n if (actor.permissions.isToken()) {\n this.logger.warn('api key refused: caller is a key or an app token', {\n orgId: actor.orgId,\n actorId: actor.id,\n });\n throw new ForbiddenError('Sign in to create an API key');\n }\n const roles = this.roleMap(await this.roles.storedRoles(actor.orgId));\n const role = roles.get(input.role);\n if (!role) {\n throw new NotFoundError('Role', input.role);\n }\n const missing = role.permissions.filter(\n (permission) => !actor.permissions.anywhere(permission),\n );\n if (missing.length > 0) {\n this.logger.warn('api key refused: role permissions not held', {\n orgId: actor.orgId,\n actorId: actor.id,\n roleKey: role.key,\n missing,\n });\n throw new ForbiddenError(`You don't hold ${missing.join(', ')}`);\n }\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n const created = await this.apiKeys().create(orgExternalId, userExternalId, {\n name: input.name,\n roleKey: role.key,\n expiresInDays: input.expiresInDays,\n });\n this.logger.info('api key created', {\n orgId: actor.orgId,\n actorId: actor.id,\n keyId: created.id,\n roleKey: role.key,\n });\n return { ...keySummary(created, roles), key: created.key };\n }\n\n async deleteApiKey(keyId: string, actor: Actor): Promise<void> {\n actor.permissions.require('api_keys:delete');\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n await this.apiKeys().revoke(orgExternalId, userExternalId, keyId);\n this.logger.info('api key revoked', { orgId: actor.orgId, actorId: actor.id, keyId });\n }\n\n async listConnectedApps(actor: Actor): Promise<ConnectedApp[]> {\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n return this.apiKeys().listApps(orgExternalId, userExternalId);\n }\n\n async revokeConnectedApp(clientId: string, actor: Actor): Promise<void> {\n const { orgExternalId, userExternalId } = await this.externalIdsOf(actor);\n await this.apiKeys().revokeApp(orgExternalId, userExternalId, clientId);\n this.logger.info('connected app revoked', {\n orgId: actor.orgId,\n actorId: actor.id,\n clientId,\n });\n }\n\n async createPlatformOrganization(\n input: PlatformOrganizationInput,\n ): Promise<PlatformOrganization> {\n const ownerExternalId = await this.platformAccountId();\n const created = await this.orgAdmin().createOrganizationFor(ownerExternalId, {\n name: input.name,\n slug: input.slug,\n });\n const found = await this.repo.findByExternalId(created.id);\n if (!found) {\n throw new NotFoundError('Organization', created.id);\n }\n const org = await this.repo.setMetadata(found.id, input.metadata ?? {});\n const apiKey = await this.platformKey(org, ownerExternalId, 'Platform');\n this.logger.info('platform organization created', { orgId: org.id, slug: org.slug });\n return {\n organization: {\n id: org.id,\n name: org.name,\n slug: org.slug,\n metadata: org.metadata,\n createdAt: org.createdAt,\n },\n apiKey,\n };\n }\n\n async createPlatformApiKey(orgId: string, name: string): Promise<CreatedApiKey> {\n const account = this.platformAccount();\n const [org, person] = await Promise.all([\n this.repo.findById(orgId),\n this.people.getUserByEmail(account.email),\n ]);\n const orgUser = org && person ? await this.repo.findOrgUser(org.id, person.id) : null;\n if (!org || !person?.externalId || orgUser?.status !== 'active') {\n throw new NotFoundError('Organization', orgId);\n }\n const apiKey = await this.platformKey(org, person.externalId, name);\n this.logger.info('platform api key created', { orgId: org.id, keyId: apiKey.id });\n return apiKey;\n }\n\n isPlatformAccount(email: string): boolean {\n return this.platform !== undefined && email.toLowerCase() === this.platform.email;\n }\n\n private async platformKey(\n org: Organization,\n ownerExternalId: string,\n name: string,\n ): Promise<CreatedApiKey> {\n const [created, stored] = await Promise.all([\n this.apiKeys().create(org.externalId ?? org.id, ownerExternalId, {\n name,\n roleKey: OWNER_ROLE_KEY,\n }),\n this.roles.storedRoles(org.id),\n ]);\n return { ...keySummary(created, this.roleMap(stored)), key: created.key };\n }\n\n private async platformAccountId(): Promise<string> {\n const account = this.platformAccount();\n const person = await this.people.getUserByEmail(account.email);\n if (person?.externalId) {\n return person.externalId;\n }\n const { externalId } = await this.accounts().createAccount(account);\n this.logger.info('platform account created', { userId: externalId });\n return externalId;\n }\n\n private platformAccount(): PlatformAccount {\n if (!this.platform) {\n throw new Error('the platform account is not configured');\n }\n return this.platform;\n }\n\n private accounts(): Accounts {\n if (!this.accountsPort) {\n throw new Error('accounts are not configured');\n }\n return this.accountsPort();\n }\n\n private async keysWithRole(orgId: string, roleKey: string): Promise<number> {\n if (!this.apiKeysPort) {\n return 0;\n }\n const org = await this.repo.findById(orgId);\n return org ? this.apiKeysPort().countWithRole(org.externalId ?? org.id, roleKey) : 0;\n }\n\n private async cleanUpAfterRemoval(\n orgId: string,\n orgUserId: string,\n person: { email: string; externalId: string | null } | null,\n ): Promise<void> {\n const steps: Array<[string, () => Promise<unknown>]> = [];\n const org = await this.repo.findById(orgId);\n if (person?.externalId && org) {\n const orgExternalId = org.externalId ?? org.id;\n const userExternalId = person.externalId;\n steps.push([\n 'membership',\n () => this.orgAdmin().removeMembership(orgExternalId, userExternalId),\n ]);\n steps.push([\n 'api keys and tokens',\n () => this.apiKeys().revokeAllFor(orgExternalId, userExternalId),\n ]);\n }\n steps.push(['profile photo', () => this.images.syncPublicImages(orgId, orgUserId, [])]);\n if (person) {\n steps.push([\n 'pending invite',\n async () => {\n const pending = await this.repo.findPendingInvite(orgId, person.email);\n if (pending) {\n await this.repo.setInviteStatus(orgId, pending.id, 'canceled');\n }\n },\n ]);\n }\n for (const [step, run] of steps) {\n for (let attempt = 1; attempt <= 3; attempt++) {\n try {\n await run();\n break;\n } catch (err) {\n this.logger.error('cleanup after removal failed', {\n orgId,\n orgUserId,\n step,\n attempt,\n err: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }\n }\n }\n\n private apiKeys(): ApiKeys {\n if (!this.apiKeysPort) {\n throw new Error('api keys are not configured');\n }\n return this.apiKeysPort();\n }\n\n private async externalIdsOf(\n actor: Actor,\n ): Promise<{ orgExternalId: string; userExternalId: string }> {\n const [org, orgUser] = await Promise.all([\n this.repo.findById(actor.orgId),\n this.repo.findOrgUserById(actor.orgId, actor.id),\n ]);\n if (!org || !orgUser) {\n throw new NotFoundError('Person', actor.id);\n }\n const person = await this.people.getUserById(orgUser.userId);\n if (!person?.externalId) {\n throw new NotFoundError('User', orgUser.userId);\n }\n return { orgExternalId: org.externalId ?? org.id, userExternalId: person.externalId };\n }\n\n private async pendingInviteOf(\n orgId: string,\n orgUserId: string,\n ): Promise<{ invite: Invite; role: OrgRole; orgUser: OrgUser }> {\n const orgUser = await this.repo.findOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n throw new NotFoundError('Person', orgUserId);\n }\n const person = await this.people.getUserById(orgUser.userId);\n const invite = person ? await this.repo.findPendingInvite(orgId, person.email) : null;\n if (!invite) {\n throw new NotFoundError('Invite', orgUserId);\n }\n const stored = await this.roles.storedRoles(orgId);\n const role = this.resolveIn(stored, invite.roleKey);\n if (!role) {\n throw new NotFoundError('Role', invite.roleKey);\n }\n return { invite, role, orgUser };\n }\n\n private async deleteOrgUserRow(orgId: string, orgUser: OrgUser): Promise<OrgUser | null> {\n const held = await this.roles.assignmentsOf(orgId, orgUser.id);\n return this.uow.run((scope) => this.deleteOrgUserIn(scope, orgId, orgUser, held, SYSTEM_ID));\n }\n\n private async deleteOrgUserIn(\n scope: OrganizationsWriteScope,\n orgId: string,\n orgUser: OrgUser,\n held: { roleKey: string; contentId: string | null }[],\n actorId: string,\n ): Promise<OrgUser | null> {\n const orgRoleKey = held.find((row) => row.contentId === null)?.roleKey ?? MEMBER_ROLE_KEY;\n const deleted = await scope.organizations.deleteOrgUser(orgId, orgUser.id);\n if (!deleted) {\n return null;\n }\n const events: NewOrganizationEvent[] = [\n organizationEvents.orgUserDeleted.make({\n orgId,\n data: { ...deleted, orgRole: { key: orgRoleKey } },\n metadata: { actorId },\n }),\n ];\n if (orgRoleKey === MEMBER_ROLE_KEY) {\n events.push(organizationEvents.studentDeleted.make({ orgId, data: deleted }));\n }\n await scope.outbox.append(events);\n return deleted;\n }\n\n private async sendInviteEmail(invite: Invite, token: string, role: OrgRole): Promise<void> {\n if (!this.mailer || !this.inviteUrls) {\n throw new Error('invite delivery is not configured (mailer / invite urls missing)');\n }\n const learner = role.permissions.length === 0;\n const base = learner\n ? `${this.inviteUrls.studentPortalUrl}/welcome`\n : `${this.inviteUrls.adminAppUrl}/invite`;\n const query = learner\n ? new URLSearchParams({ token })\n : new URLSearchParams({ token, email: invite.email });\n const inviteUrl = `${base}?${query.toString()}`;\n if (learner) {\n await this.mailer.send(invite.email, 'studentInvite', {\n inviteUrl,\n studentName: invite.email,\n });\n } else {\n await this.mailer.send(invite.email, 'memberInvite', {\n inviteUrl,\n inviterName: 'Your team',\n role: role.name,\n });\n }\n }\n\n private toMember(row: TeamRow, nameOf: (key: string) => string): Member {\n const orgRoleKey =\n row.status === 'invited' && row.inviteRoleKey\n ? row.inviteRoleKey\n : (row.orgRoleKey ?? MEMBER_ROLE_KEY);\n return {\n id: row.id,\n firstName: row.firstName,\n lastName: row.lastName,\n email: row.email,\n image: row.image,\n orgRole: { key: orgRoleKey, name: nameOf(orgRoleKey) },\n isOwner: row.orgRoleKey === OWNER_ROLE_KEY,\n items: row.items.map((item) => ({ ...item, roleName: nameOf(item.roleKey) })),\n status: row.status,\n joinedAt: row.status === 'active' ? row.joinedAt.toISOString() : null,\n invitedAt: row.invitedAt ? row.invitedAt.toISOString() : null,\n };\n }\n\n private async assignmentViews(orgId: string, orgUserId: string): Promise<AssignmentView[]> {\n const [rows, stored] = await Promise.all([\n this.roles.assignmentsOf(orgId, orgUserId),\n this.roles.storedRoles(orgId),\n ]);\n const roles = this.roleMap(stored);\n const views: AssignmentView[] = rows.map((row) => ({\n orgUserId,\n roleKey: row.roleKey,\n roleName: roles.get(row.roleKey)?.name ?? row.roleKey,\n contentId: row.contentId,\n contentType: row.contentType,\n }));\n if (!rows.some((row) => row.contentId === null)) {\n views.unshift({\n orgUserId,\n roleKey: MEMBER_ROLE_KEY,\n roleName: roles.get(MEMBER_ROLE_KEY)?.name ?? 'Member',\n contentId: null,\n contentType: null,\n });\n }\n return views;\n }\n\n private roleMap(stored: readonly StoredOrgRole[]): Map<string, OrgRole> {\n return new Map(resolveOrgRoles(this.catalog, stored).map((role) => [role.key, role]));\n }\n\n private resolveIn(stored: readonly StoredOrgRole[], key: string): OrgRole | null {\n return resolveRole(\n key,\n this.catalog,\n stored.find((row) => row.key === key),\n );\n }\n\n private async findRole(orgId: string, key: string): Promise<OrgRole> {\n const role = this.resolveIn(await this.roles.storedRoles(orgId), key);\n if (!role) {\n throw new NotFoundError('Role', key);\n }\n return role;\n }\n\n private async relockedActor(scope: OrganizationsWriteScope, actor: Actor): Promise<Actor> {\n if (actor.id === SYSTEM_ID) {\n return actor;\n }\n const facts = await scope.roles.actorFacts(actor.orgId, actor.id);\n if (!facts || facts.status !== 'active') {\n throw new ForbiddenError('You are no longer an active member of this organization');\n }\n const fresh = resolvePermissions({\n assignments: facts.assignments,\n roles: this.roleMap(facts.storedRoles),\n });\n return {\n ...actor,\n permissions: {\n has: (p, on) => fresh.has(p, on) && actor.permissions.has(p, on),\n require: (p, on) => {\n if (!(fresh.has(p, on) && actor.permissions.has(p, on))) {\n throw new ForbiddenError(`You need ${p}`);\n }\n },\n anywhere: (p) => fresh.anywhere(p) && actor.permissions.anywhere(p),\n where: (p) => actor.permissions.where(p),\n roleOn: (on) => fresh.roleOn(on),\n isOwner: () => fresh.isOwner() && actor.permissions.isOwner(),\n isToken: () => actor.permissions.isToken(),\n },\n };\n }\n\n private itemPermissions(role: OrgRole | null, type: ContentType): Permission[] {\n if (!role || !role.levels.includes(type)) {\n return [];\n }\n return role.permissions.filter((p) => permissionAbout(p) === type);\n }\n\n private assertHolds(actor: Actor, permissions: readonly Permission[]): void {\n const missing = [...new Set(permissions)].filter((p) => !actor.permissions.has(p));\n if (missing.length > 0) {\n this.logger.warn('refused: editor lacks permissions', {\n orgId: actor.orgId,\n actorId: actor.id,\n missing,\n });\n throw new ForbiddenError(`You need ${missing.join(', ')}`);\n }\n }\n\n private assertHoldsOn(actor: Actor, permissions: readonly Permission[], contentId: string): void {\n const missing = [...new Set(permissions)].filter((p) => !actor.permissions.has(p, contentId));\n if (missing.length > 0) {\n this.logger.warn('refused: editor lacks permissions on the item', {\n orgId: actor.orgId,\n actorId: actor.id,\n contentId,\n missing,\n });\n throw new ForbiddenError(`You need ${missing.join(', ')} there`);\n }\n }\n\n private assertNotSelf(actor: Actor, orgUserId: string): void {\n if (actor.id === orgUserId) {\n this.logger.warn('refused: changing own roles', { orgId: actor.orgId, orgUserId });\n throw new ForbiddenError(\"You can't change your own roles\");\n }\n }\n\n private assertUniqueName(stored: readonly StoredOrgRole[], key: string, name: string): void {\n const wanted = name.trim().toLowerCase();\n if (wanted.length === 0) {\n throw new OrganizationRuleError('A role needs a name');\n }\n const taken = resolveOrgRoles(this.catalog, stored).some(\n (role) => role.key !== key && role.name.trim().toLowerCase() === wanted,\n );\n if (taken) {\n throw new OrganizationRuleError(`A role named ${name} already exists`);\n }\n }\n\n private parseLevels(levels: Level[]): Level[] {\n if (levels.length === 0) {\n throw new OrganizationRuleError('A role needs at least one level');\n }\n for (const level of levels) {\n if (!levelSchema.safeParse(level).success) {\n throw new OrganizationRuleError(`Unknown level ${String(level)}`);\n }\n }\n return [...new Set(levels)];\n }\n\n private assertFits(row: StoredOrgRole): void {\n const base = this.catalog.get(row.base);\n const levels = row.levels ?? base?.levels ?? [];\n const misfits = Object.entries(row.permissions)\n .filter(([, held]) => held)\n .map(([p]) => p as Permission)\n .filter((p) => !fitsLevels(p, levels));\n if (misfits.length > 0) {\n throw new OrganizationRuleError(\n `${misfits.join(', ')} ${misfits.length === 1 ? \"doesn't\" : \"don't\"} fit the role's levels`,\n );\n }\n }\n\n private async assertLevelsNotInUse(\n roles: RolesRepository,\n orgId: string,\n before: OrgRole,\n after: OrgRole,\n ): Promise<void> {\n const removed = before.levels.filter((level) => !after.levels.includes(level));\n for (const level of removed) {\n const count = await roles.countHolders(orgId, before.key, level);\n if (count > 0) {\n throw new OrganizationRuleError(\n `${before.name} is given on ${level === 'org' ? 'the organization' : `a ${level}`}; remove those first`,\n );\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -28,7 +28,7 @@ function actorWith(shape = {}) {
|
|
|
28
28
|
return {
|
|
29
29
|
id: shape.id ?? "orm_actor",
|
|
30
30
|
orgId: shape.orgId ?? "org_1",
|
|
31
|
-
permissions: new ResolvedPermissions(org, orgRole, content, shape.owner ?? false)
|
|
31
|
+
permissions: new ResolvedPermissions(org, orgRole, content, shape.owner ?? false, false)
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","names":[],"sources":["../../src/organizations/testing.ts"],"sourcesContent":["import type { ContentId, Permission } from '../types/index.js';\nimport type { Actor, RoleRef } from '../shared/actor.js';\nimport { ALL_PERMISSIONS, withImplied } from './permissions.js';\nimport { ResolvedPermissions } from './effective-permissions.js';\n\nexport interface ActorShape {\n id?: string;\n orgId?: string;\n org?: readonly Permission[];\n content?: Readonly<Record<ContentId, readonly Permission[]>>;\n owner?: boolean;\n orgRole?: RoleRef;\n contentRoles?: Readonly<Record<ContentId, RoleRef>>;\n}\n\nconst MEMBER: RoleRef = { key: 'member', name: 'Member', team: false };\n\nexport function actorWith(shape: ActorShape = {}): Actor {\n const org = shape.owner ? new Set(ALL_PERMISSIONS) : withImplied(shape.org ?? []);\n const content = new Map(\n Object.entries(shape.content ?? {}).map(([id, permissions]) => [\n id,\n {\n permissions: withImplied(permissions),\n role: shape.contentRoles?.[id] ?? { key: 'item_role', name: 'Item role', team: true },\n },\n ]),\n );\n const orgRole =\n shape.orgRole ??\n (shape.owner\n ? { key: 'owner', name: 'Owner', team: true }\n : (shape.org?.length ?? 0) > 0\n ? { key: 'org_role', name: 'Org role', team: true }\n : MEMBER);\n return {\n id: shape.id ?? 'orm_actor',\n orgId: shape.orgId ?? 'org_1',\n permissions: new ResolvedPermissions(org, orgRole, content, shape.owner ?? false),\n };\n}\n"],"mappings":";;;AAeA,MAAM,SAAkB;CAAE,KAAK;CAAU,MAAM;CAAU,MAAM;AAAM;AAErE,SAAgB,UAAU,QAAoB,CAAC,GAAU;CACvD,MAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,eAAe,IAAI,YAAY,MAAM,OAAO,CAAC,CAAC;CAChF,MAAM,UAAU,IAAI,IAClB,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAC7D,IACA;EACE,aAAa,YAAY,WAAW;EACpC,MAAM,MAAM,eAAe,OAAO;GAAE,KAAK;GAAa,MAAM;GAAa,MAAM;EAAK;CACtF,CACF,CAAC,CACH;CACA,MAAM,UACJ,MAAM,YACL,MAAM,QACH;EAAE,KAAK;EAAS,MAAM;EAAS,MAAM;CAAK,KACzC,MAAM,KAAK,UAAU,KAAK,IACzB;EAAE,KAAK;EAAY,MAAM;EAAY,MAAM;CAAK,IAChD;CACR,OAAO;EACL,IAAI,MAAM,MAAM;EAChB,OAAO,MAAM,SAAS;EACtB,aAAa,IAAI,oBAAoB,KAAK,SAAS,SAAS,MAAM,SAAS,KAAK;
|
|
1
|
+
{"version":3,"file":"testing.js","names":[],"sources":["../../src/organizations/testing.ts"],"sourcesContent":["import type { ContentId, Permission } from '../types/index.js';\nimport type { Actor, RoleRef } from '../shared/actor.js';\nimport { ALL_PERMISSIONS, withImplied } from './permissions.js';\nimport { ResolvedPermissions } from './effective-permissions.js';\n\nexport interface ActorShape {\n id?: string;\n orgId?: string;\n org?: readonly Permission[];\n content?: Readonly<Record<ContentId, readonly Permission[]>>;\n owner?: boolean;\n orgRole?: RoleRef;\n contentRoles?: Readonly<Record<ContentId, RoleRef>>;\n}\n\nconst MEMBER: RoleRef = { key: 'member', name: 'Member', team: false };\n\nexport function actorWith(shape: ActorShape = {}): Actor {\n const org = shape.owner ? new Set(ALL_PERMISSIONS) : withImplied(shape.org ?? []);\n const content = new Map(\n Object.entries(shape.content ?? {}).map(([id, permissions]) => [\n id,\n {\n permissions: withImplied(permissions),\n role: shape.contentRoles?.[id] ?? { key: 'item_role', name: 'Item role', team: true },\n },\n ]),\n );\n const orgRole =\n shape.orgRole ??\n (shape.owner\n ? { key: 'owner', name: 'Owner', team: true }\n : (shape.org?.length ?? 0) > 0\n ? { key: 'org_role', name: 'Org role', team: true }\n : MEMBER);\n return {\n id: shape.id ?? 'orm_actor',\n orgId: shape.orgId ?? 'org_1',\n permissions: new ResolvedPermissions(org, orgRole, content, shape.owner ?? false, false),\n };\n}\n"],"mappings":";;;AAeA,MAAM,SAAkB;CAAE,KAAK;CAAU,MAAM;CAAU,MAAM;AAAM;AAErE,SAAgB,UAAU,QAAoB,CAAC,GAAU;CACvD,MAAM,MAAM,MAAM,QAAQ,IAAI,IAAI,eAAe,IAAI,YAAY,MAAM,OAAO,CAAC,CAAC;CAChF,MAAM,UAAU,IAAI,IAClB,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAC7D,IACA;EACE,aAAa,YAAY,WAAW;EACpC,MAAM,MAAM,eAAe,OAAO;GAAE,KAAK;GAAa,MAAM;GAAa,MAAM;EAAK;CACtF,CACF,CAAC,CACH;CACA,MAAM,UACJ,MAAM,YACL,MAAM,QACH;EAAE,KAAK;EAAS,MAAM;EAAS,MAAM;CAAK,KACzC,MAAM,KAAK,UAAU,KAAK,IACzB;EAAE,KAAK;EAAY,MAAM;EAAY,MAAM;CAAK,IAChD;CACR,OAAO;EACL,IAAI,MAAM,MAAM;EAChB,OAAO,MAAM,SAAS;EACtB,aAAa,IAAI,oBAAoB,KAAK,SAAS,SAAS,MAAM,SAAS,OAAO,KAAK;CACzF;AACF"}
|
package/dist/progress/service.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { noopLogger } from "../shared/logger.js";
|
|
2
|
-
import { NotFoundError } from "../shared/errors.js";
|
|
3
1
|
import { genId } from "../shared/id.js";
|
|
2
|
+
import { NotFoundError } from "../shared/errors.js";
|
|
3
|
+
import { noopLogger } from "../shared/logger.js";
|
|
4
4
|
import { progressEvents } from "./events.js";
|
|
5
5
|
//#region src/progress/service.ts
|
|
6
6
|
/** Mirrors reporting/member: `settings.published === false` is the only draft signal. */
|
|
@@ -57,6 +57,9 @@ interface CommunityHomeSpaceBase {
|
|
|
57
57
|
memberCount: number;
|
|
58
58
|
accessRule: 'all_members' | 'by_request' | 'by_invite';
|
|
59
59
|
standing: 'open' | 'member' | 'requested' | 'invited' | 'full' | 'none';
|
|
60
|
+
coverUrl: string | null;
|
|
61
|
+
backgroundUrl: string | null;
|
|
62
|
+
iconUrl: string | null;
|
|
60
63
|
}
|
|
61
64
|
/** A space the viewer can see but not open: enough to request, accept or ask. */
|
|
62
65
|
interface LockedCommunitySpace extends CommunityHomeSpaceBase {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Page } from "../../types/shared.js";
|
|
2
|
-
import { ActivityView, CourseView, DownloadFile, DownloadView, EventAttendee, MemberEvent, MemberEventSummary, MemberEventsQuery, Module } from "../../types/schemas/content.js";
|
|
2
|
+
import { ActivityView, CourseView, DownloadFile, DownloadView, EventAttendee, MemberEvent, MemberEventSummary, MemberEventsQuery, Module, SpaceImage } from "../../types/schemas/content.js";
|
|
3
3
|
import { NotificationFilter } from "../../types/notifications.js";
|
|
4
4
|
import "../../types/index.js";
|
|
5
5
|
import { Actor } from "../../shared/actor.js";
|
|
@@ -24,6 +24,7 @@ interface MemberReportService {
|
|
|
24
24
|
/** Signed URL of a course, download or community thumbnail: published, or the item's read
|
|
25
25
|
* permission. An event's when the caller can read the event. */
|
|
26
26
|
thumbnailFile(owner: 'course' | 'download' | 'community' | 'event', id: string, actor: Actor): Promise<string>;
|
|
27
|
+
spaceImageFile(spaceId: string, image: SpaceImage, actor: Actor): Promise<string>;
|
|
27
28
|
getEvent(eventId: string, actor: Actor): Promise<MemberEvent>;
|
|
28
29
|
listEvents(query: MemberEventsQuery, actor: Actor): Promise<Page<MemberEventSummary>>;
|
|
29
30
|
eventCalendar(eventId: string, actor: Actor): Promise<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Page } from "../../types/shared.js";
|
|
2
|
-
import { ActivityView, CourseView, DownloadFile, DownloadView, EventAttendee, MemberEvent, MemberEventSummary, MemberEventsQuery, Module } from "../../types/schemas/content.js";
|
|
2
|
+
import { ActivityView, CourseView, DownloadFile, DownloadView, EventAttendee, MemberEvent, MemberEventSummary, MemberEventsQuery, Module, SpaceImage } from "../../types/schemas/content.js";
|
|
3
3
|
import { NotificationFilter } from "../../types/notifications.js";
|
|
4
4
|
import "../../types/index.js";
|
|
5
5
|
import { Actor } from "../../shared/actor.js";
|
|
@@ -94,6 +94,7 @@ declare class MemberReportServiceImpl implements MemberReportService {
|
|
|
94
94
|
assets: DownloadFile[];
|
|
95
95
|
}>;
|
|
96
96
|
thumbnailFile(owner: Owner, id: string, actor: Actor): Promise<string>;
|
|
97
|
+
spaceImageFile(spaceId: string, image: SpaceImage, actor: Actor): Promise<string>;
|
|
97
98
|
activityFile(activityId: string, assetId: string, actor: Actor): Promise<string>;
|
|
98
99
|
downloadFile(downloadId: string, assetId: string, actor: Actor): Promise<string>;
|
|
99
100
|
private seeEvents;
|