@happyvertical/smrt-users 0.35.4 → 0.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/chunks/{TerminalAuthService-D5VVPG9e.js → TerminalAuthService-bY1oWeAh.js} +18 -33
  2. package/dist/chunks/TerminalAuthService-bY1oWeAh.js.map +1 -0
  3. package/dist/chunks/{index-CitgZk-4.js → index-DBpq-WMK.js} +3 -3
  4. package/dist/chunks/{index-CitgZk-4.js.map → index-DBpq-WMK.js.map} +1 -1
  5. package/dist/collections/GroupMemberCollection.d.ts.map +1 -1
  6. package/dist/collections/TenantCollection.d.ts +5 -4
  7. package/dist/collections/TenantCollection.d.ts.map +1 -1
  8. package/dist/index.js +7 -13
  9. package/dist/index.js.map +1 -1
  10. package/dist/manifest.json +3 -3
  11. package/dist/models/Group.d.ts +10 -2
  12. package/dist/models/Group.d.ts.map +1 -1
  13. package/dist/models/GroupMember.d.ts +9 -2
  14. package/dist/models/GroupMember.d.ts.map +1 -1
  15. package/dist/models/GroupRole.d.ts +9 -2
  16. package/dist/models/GroupRole.d.ts.map +1 -1
  17. package/dist/models/MagicLinkToken.d.ts +12 -2
  18. package/dist/models/MagicLinkToken.d.ts.map +1 -1
  19. package/dist/models/Membership.d.ts +11 -2
  20. package/dist/models/Membership.d.ts.map +1 -1
  21. package/dist/models/MembershipOverride.d.ts +10 -2
  22. package/dist/models/MembershipOverride.d.ts.map +1 -1
  23. package/dist/models/Permission.d.ts +10 -2
  24. package/dist/models/Permission.d.ts.map +1 -1
  25. package/dist/models/Role.d.ts +11 -2
  26. package/dist/models/Role.d.ts.map +1 -1
  27. package/dist/models/RolePermission.d.ts +9 -2
  28. package/dist/models/RolePermission.d.ts.map +1 -1
  29. package/dist/models/Session.d.ts +17 -2
  30. package/dist/models/Session.d.ts.map +1 -1
  31. package/dist/models/Tenant.d.ts +15 -2
  32. package/dist/models/Tenant.d.ts.map +1 -1
  33. package/dist/models/TenantPermissionOverride.d.ts +10 -2
  34. package/dist/models/TenantPermissionOverride.d.ts.map +1 -1
  35. package/dist/models/User.d.ts +11 -2
  36. package/dist/models/User.d.ts.map +1 -1
  37. package/dist/services/MagicLinkService.d.ts.map +1 -1
  38. package/dist/services/PermissionResolver.d.ts +2 -6
  39. package/dist/services/PermissionResolver.d.ts.map +1 -1
  40. package/dist/services/SessionService.d.ts.map +1 -1
  41. package/dist/services/TenantService.d.ts.map +1 -1
  42. package/dist/services/TerminalAuthService.d.ts.map +1 -1
  43. package/dist/smrt-knowledge.json +4 -4
  44. package/dist/sveltekit.js +1 -1
  45. package/package.json +8 -8
  46. package/dist/chunks/TerminalAuthService-D5VVPG9e.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerminalAuthService-bY1oWeAh.js","sources":["../../src/__smrt-register__.ts","../../src/models/CliAuthRequest.ts","../../src/collections/CliAuthRequestCollection.ts","../../src/models/Group.ts","../../src/collections/GroupCollection.ts","../../src/models/GroupMember.ts","../../src/collections/GroupMemberCollection.ts","../../src/models/GroupRole.ts","../../src/collections/GroupRoleCollection.ts","../../src/types/index.ts","../../src/models/Membership.ts","../../src/collections/MembershipCollection.ts","../../src/models/MembershipOverride.ts","../../src/collections/MembershipOverrideCollection.ts","../../src/models/Permission.ts","../../src/collections/PermissionCollection.ts","../../src/models/RolePermission.ts","../../src/collections/RolePermissionCollection.ts","../../src/models/Session.ts","../../src/collections/SessionCollection.ts","../../src/models/Tenant.ts","../../src/collections/TenantCollection.ts","../../src/models/TenantPermissionOverride.ts","../../src/collections/TenantPermissionOverrideCollection.ts","../../src/models/User.ts","../../src/collections/UserCollection.ts","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/buffer_utils.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/base64.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/util/base64url.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/util/errors.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/crypto_key.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/invalid_key_input.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/is_key_like.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/is_disjoint.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/is_object.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/check_key_length.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/jwk_to_key.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/key/import.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/validate_crit.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/validate_algorithms.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/is_jwk.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/normalize_key.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/check_key_type.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/subtle_dsa.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/get_sign_verify_key.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/verify.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jws/flattened/verify.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jws/compact/verify.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/jwt_claims_set.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jwt/verify.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jwks/local.js","../../../../node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jwks/remote.js","../../src/services/OidcLoginService.ts","../../src/services/PermissionResolver.ts","../../src/services/SessionService.ts","../../src/services/SessionPermissionContext.ts","../../src/services/TerminalAuthService.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * UsersCliAuthRequest model — device-code grant for terminal/CLI logins.\n *\n * Backs the \"browser approves a terminal\" flow: a CLI starts a request, the\n * server returns a short user code, the user signs in on a browser and\n * approves the code, then the CLI polls and gets back a session token bound\n * to the approving user. Records are short-lived (TTL is enforced by\n * `expiresAt`) and store only a hash of the device code so the raw device\n * code is never recoverable from the database.\n *\n * @packageDocumentation\n */\n\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\n\n/**\n * CLI auth request lifecycle states.\n */\nexport type CliAuthRequestStatus = 'pending' | 'approved' | 'expired';\n\n@smrt({\n tableName: 'users_cli_auth_requests',\n api: { include: [] },\n cli: { include: [] },\n mcp: { include: [] },\n})\nexport class UsersCliAuthRequest extends SmrtObject {\n /** Short, human-typeable code the user enters in the browser to approve the session. */\n @field({ type: 'text' })\n userCode = '';\n\n /** SHA-256 hash of the long device code the CLI keeps secret. */\n @field({ type: 'text' })\n deviceCodeHash = '';\n\n /** Lifecycle state — `pending` → `approved` | `expired`. */\n @field({ type: 'text' })\n status: CliAuthRequestStatus = 'pending';\n\n /** User id of the human who approved the request (set on approval). */\n @field({ type: 'text' })\n userId = '';\n\n /** Tenant id captured from the approving session (set on approval). */\n @field({ type: 'text' })\n tenantId = '';\n\n /** Session id minted on approval — handed to the CLI as its bearer token. */\n @field({ type: 'text' })\n sessionId = '';\n\n /** When the pending request stops accepting approvals. */\n @field({ type: 'datetime' })\n expiresAt = new Date();\n\n /** When approval happened — null while the request is still pending. */\n @field({ type: 'datetime', nullable: true })\n approvedAt: Date | null = null;\n}\n\nexport { UsersCliAuthRequest as CliAuthRequest };\n","/**\n * UsersCliAuthRequestCollection — lookups for the device-code grant flow.\n *\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { UsersCliAuthRequest } from '../models/CliAuthRequest.js';\n\nexport class UsersCliAuthRequestCollection extends SmrtCollection<UsersCliAuthRequest> {\n static readonly _itemClass = UsersCliAuthRequest;\n\n /**\n * Look up a pending or completed request by the short user code shown in the CLI.\n */\n async findByUserCode(userCode: string): Promise<UsersCliAuthRequest | null> {\n const [request] = await this.list({\n limit: 1,\n where: { userCode: userCode.trim().toUpperCase() },\n });\n return request ?? null;\n }\n\n /**\n * Look up a request by the hash of its device code (the CLI's polling key).\n */\n async findByDeviceCodeHash(\n deviceCodeHash: string,\n ): Promise<UsersCliAuthRequest | null> {\n const [request] = await this.list({\n limit: 1,\n where: { deviceCodeHash },\n });\n return request ?? null;\n }\n\n /**\n * Delete expired pending requests (cleanup job).\n */\n async deleteExpired(): Promise<number> {\n const requests = await this.list({\n where: {\n status: 'pending',\n 'expiresAt <': new Date().toISOString(),\n },\n });\n\n let count = 0;\n for (const request of requests) {\n await request.delete();\n count++;\n }\n return count;\n }\n}\n\nexport { UsersCliAuthRequestCollection as CliAuthRequestCollection };\n","/**\n * Group model - team within a tenant\n * @packageDocumentation\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Constructor options for {@link Group}.\n */\nexport interface GroupOptions extends SmrtObjectOptions {\n tenantId?: string;\n name?: string;\n description?: string;\n}\n\n/**\n * Group represents a team or department within a tenant.\n *\n * Groups can have roles assigned to them via GroupRole.\n * Users in a group inherit permissions from the group's roles.\n *\n * @example\n * ```typescript\n * const editorsGroup = await groups.create({\n * tenantId: tenant.id,\n * name: 'Editorial Team',\n * slug: 'editorial-team',\n * description: 'Content editors and writers'\n * });\n * await editorsGroup.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated surface — RBAC/identity writes go through\n // permission-gated services, not auth-only generated CRUD.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Group extends SmrtObject {\n /**\n * Foreign key to Tenant\n */\n @foreignKey('Tenant', { required: true })\n tenantId?: string;\n\n /**\n * Display name for the group\n */\n name: string = '';\n\n /**\n * Description of the group\n */\n description: string = '';\n\n constructor(options: GroupOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n }\n}\n","/**\n * GroupCollection - Collection manager for Group objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Group } from '../models/Group.js';\n\n/**\n * Collection for managing Group objects\n */\nexport class GroupCollection extends SmrtCollection<Group> {\n static readonly _itemClass = Group;\n\n /**\n * Find all groups in a tenant\n */\n async findByTenant(tenantId: string): Promise<Group[]> {\n return await this.list({\n where: { tenantId },\n orderBy: 'name ASC',\n });\n }\n\n /**\n * Find group by slug within a tenant\n */\n async findBySlug(slug: string, tenantId: string): Promise<Group | null> {\n const results = await this.list({\n where: { slug, tenantId },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n}\n","/**\n * GroupMember model - User belongs to Group (join table)\n * @packageDocumentation\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Constructor options for {@link GroupMember}.\n */\nexport interface GroupMemberOptions extends SmrtObjectOptions {\n groupId?: string;\n userId?: string;\n}\n\n/**\n * GroupMember is a join table linking Users to Groups.\n *\n * A user can belong to multiple groups within a tenant.\n * Group membership grants additional permissions via GroupRole.\n *\n * @example\n * ```typescript\n * // Add user to a group\n * const groupMember = await groupMembers.create({\n * groupId: editorsGroup.id,\n * userId: user.id\n * });\n * await groupMember.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated REST + MCP surface — RBAC/identity writes go\n // through permission-gated services, not auth-only generated CRUD. mcp must\n // be explicit: an omitted mcp config generates the FULL tool surface.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class GroupMember extends SmrtObject {\n /**\n * Foreign key to Group\n */\n @foreignKey('Group', { required: true })\n groupId?: string;\n\n /**\n * Foreign key to User\n */\n @foreignKey('User', { required: true })\n userId?: string;\n\n constructor(options: GroupMemberOptions = {}) {\n super(options);\n if (options.groupId !== undefined) this.groupId = options.groupId;\n if (options.userId !== undefined) this.userId = options.userId;\n }\n}\n","/**\n * GroupMemberCollection - Collection manager for GroupMember objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { GroupMember } from '../models/GroupMember.js';\nimport { GroupCollection } from './GroupCollection.js';\n\n/**\n * Collection for managing GroupMember objects\n */\nexport class GroupMemberCollection extends SmrtCollection<GroupMember> {\n static readonly _itemClass = GroupMember;\n\n /** Memoized Group collection, used to resolve the Group table name. */\n private groupCollection?: GroupCollection;\n\n /**\n * Resolve the database table name for the `Group` model from the registry\n * (via a shared-connection GroupCollection) rather than hardcoding `groups`.\n * A `@smrt({ tableName })` override or table prefix on Group would otherwise\n * make raw joins reference a non-existent or foreign table.\n */\n private async getGroupTableName(): Promise<string> {\n if (!this.groupCollection) {\n this.groupCollection = await GroupCollection.create({\n db: this.options.db,\n });\n }\n return this.groupCollection.tableName;\n }\n\n /**\n * Find all members of a group\n */\n async findByGroup(groupId: string): Promise<GroupMember[]> {\n return await this.list({\n where: { groupId },\n });\n }\n\n /**\n * Find all groups a user belongs to\n */\n async findByUser(userId: string): Promise<GroupMember[]> {\n return await this.list({\n where: { userId },\n });\n }\n\n /**\n * Check if a user is in a group\n */\n async isMember(groupId: string, userId: string): Promise<boolean> {\n const results = await this.list({\n where: { groupId, userId },\n limit: 1,\n });\n return results.length > 0;\n }\n\n /**\n * Add user to a group\n */\n async addMember(groupId: string, userId: string): Promise<GroupMember> {\n // Check if already a member\n const existing = await this.list({\n where: { groupId, userId },\n limit: 1,\n });\n if (existing.length > 0) {\n return existing[0];\n }\n\n const member = await this.create({ groupId, userId });\n await member.save();\n return member;\n }\n\n /**\n * Remove user from a group\n */\n async removeMember(groupId: string, userId: string): Promise<boolean> {\n const existing = await this.list({\n where: { groupId, userId },\n limit: 1,\n });\n if (existing.length === 0) {\n return false;\n }\n\n await existing[0].delete();\n return true;\n }\n\n /**\n * Get group IDs for a user\n * @deprecated Use getGroupIdsForTenant to prevent cross-tenant leakage\n */\n async getGroupIds(userId: string): Promise<string[]> {\n const memberships = await this.findByUser(userId);\n return memberships.map((m) => m.groupId as string);\n }\n\n /**\n * Get group IDs for a user within a specific tenant\n * This prevents cross-tenant permission leakage by filtering groups by tenant\n */\n async getGroupIdsForTenant(\n userId: string,\n tenantId: string,\n ): Promise<string[]> {\n // Query group_members joined with the Group table to filter by tenant.\n // Use raw database query to get unhydrated results. Both table names are\n // trusted registry-resolved identifiers, not user input.\n const groupTable = await this.getGroupTableName();\n const sql = `\n SELECT gm.group_id\n FROM ${this.tableName} gm\n INNER JOIN ${groupTable} g ON g.id = gm.group_id\n WHERE gm.user_id = ? AND g.tenant_id = ?\n `;\n const result = await this.db.query(sql, userId, tenantId);\n return result.rows.map(\n (r: Record<string, unknown>) => r.group_id as string,\n );\n }\n\n /**\n * Get user IDs in a group\n */\n async getUserIds(groupId: string): Promise<string[]> {\n const members = await this.findByGroup(groupId);\n return members.map((m) => m.userId as string);\n }\n}\n","/**\n * GroupRole model - Group has Role (join table)\n * @packageDocumentation\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Constructor options for {@link GroupRole}.\n */\nexport interface GroupRoleOptions extends SmrtObjectOptions {\n groupId?: string;\n roleId?: string;\n}\n\n/**\n * GroupRole is a join table linking Groups to Roles.\n *\n * Groups can have multiple roles assigned, and members of the group\n * inherit the permissions from all assigned roles.\n *\n * @example\n * ```typescript\n * // Assign a role to a group\n * const groupRole = await groupRoles.create({\n * groupId: editorsGroup.id,\n * roleId: editorRole.id\n * });\n * await groupRole.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated REST + MCP surface — RBAC/identity writes go\n // through permission-gated services, not auth-only generated CRUD. mcp must\n // be explicit: an omitted mcp config generates the FULL tool surface.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class GroupRole extends SmrtObject {\n /**\n * Foreign key to Group\n */\n @foreignKey('Group', { required: true })\n groupId?: string;\n\n /**\n * Foreign key to Role\n */\n @foreignKey('Role', { required: true })\n roleId?: string;\n\n constructor(options: GroupRoleOptions = {}) {\n super(options);\n if (options.groupId !== undefined) this.groupId = options.groupId;\n if (options.roleId !== undefined) this.roleId = options.roleId;\n }\n}\n","/**\n * GroupRoleCollection - Collection manager for GroupRole objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { GroupRole } from '../models/GroupRole.js';\n\n/**\n * Collection for managing GroupRole objects\n */\nexport class GroupRoleCollection extends SmrtCollection<GroupRole> {\n static readonly _itemClass = GroupRole;\n\n /**\n * Find all roles for a group\n */\n async findByGroup(groupId: string): Promise<GroupRole[]> {\n return await this.list({\n where: { groupId },\n });\n }\n\n /**\n * Find all groups that have a role\n */\n async findByRole(roleId: string): Promise<GroupRole[]> {\n return await this.list({\n where: { roleId },\n });\n }\n\n /**\n * Check if a group has a role\n */\n async hasRole(groupId: string, roleId: string): Promise<boolean> {\n const results = await this.list({\n where: { groupId, roleId },\n limit: 1,\n });\n return results.length > 0;\n }\n\n /**\n * Add role to a group\n */\n async addRole(groupId: string, roleId: string): Promise<GroupRole> {\n // Check if already has role\n const existing = await this.list({\n where: { groupId, roleId },\n limit: 1,\n });\n if (existing.length > 0) {\n return existing[0];\n }\n\n const groupRole = await this.create({ groupId, roleId });\n await groupRole.save();\n return groupRole;\n }\n\n /**\n * Remove role from a group\n */\n async removeRole(groupId: string, roleId: string): Promise<boolean> {\n const existing = await this.list({\n where: { groupId, roleId },\n limit: 1,\n });\n if (existing.length === 0) {\n return false;\n }\n\n await existing[0].delete();\n return true;\n }\n\n /**\n * Get role IDs for a group\n */\n async getRoleIds(groupId: string): Promise<string[]> {\n const groupRoles = await this.findByGroup(groupId);\n return groupRoles.map((gr) => gr.roleId as string);\n }\n}\n","/**\n * Type definitions for smrt-users\n * @packageDocumentation\n */\n\n// Re-export status enums from smrt-types for backwards compatibility\n// These are defined in smrt-types to allow browser-safe packages to import them\nexport {\n MembershipStatus,\n OverrideEffect,\n SessionStatus,\n TenantPermissionEffect,\n TenantStatus,\n UserStatus,\n} from '@happyvertical/smrt-types';\n\n// ============= Default System Roles =============\n\n/**\n * Default system role slugs\n */\nexport const DEFAULT_ROLE_SLUGS = {\n OWNER: 'owner',\n ADMIN: 'admin',\n MEMBER: 'member',\n VIEWER: 'viewer',\n} as const;\n\n/**\n * Default system roles configuration\n */\nexport const DEFAULT_ROLES = [\n {\n slug: DEFAULT_ROLE_SLUGS.OWNER,\n name: 'Owner',\n description: 'Full access to all resources',\n },\n {\n slug: DEFAULT_ROLE_SLUGS.ADMIN,\n name: 'Administrator',\n description: 'Manage users and settings',\n },\n {\n slug: DEFAULT_ROLE_SLUGS.MEMBER,\n name: 'Member',\n description: 'Standard access',\n },\n {\n slug: DEFAULT_ROLE_SLUGS.VIEWER,\n name: 'Viewer',\n description: 'Read-only access',\n },\n] as const;\n\nexport type DefaultRoleSlug =\n (typeof DEFAULT_ROLE_SLUGS)[keyof typeof DEFAULT_ROLE_SLUGS];\n\n// ============= Tenant Policy =============\n\n/**\n * Tenant policy mode\n *\n * - `flexible`: No tenant created on signup, user can have zero tenants\n * - `personal`: Auto-create personal tenant on first login, can delete all\n * - `required`: Auto-create personal tenant, must keep at least one\n */\nexport type TenantPolicyMode = 'flexible' | 'personal' | 'required';\n\n/**\n * Tenant policy configuration\n *\n * Set in smrt.config.js to control tenant creation behavior\n */\nexport interface TenantPolicy {\n /** Policy mode */\n mode: TenantPolicyMode;\n\n /** Maximum tenants per user (0 = unlimited) */\n maxTenants: number;\n\n /** Name for auto-created default tenant */\n defaultName: string;\n}\n\n/**\n * Default tenant policy (flexible, unlimited)\n */\nexport const DEFAULT_TENANT_POLICY: TenantPolicy = {\n mode: 'flexible',\n maxTenants: 0,\n defaultName: 'Default Workspace',\n};\n","/**\n * Membership model - User belongs to Tenant with a Role\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { Membership as MembershipContract } from '@happyvertical/smrt-types';\nimport { MembershipStatus } from '../types/index.js';\n\n/**\n * Constructor options for {@link Membership}.\n */\nexport interface MembershipOptions extends SmrtObjectOptions {\n userId?: string;\n tenantId?: string;\n roleId?: string;\n status?: MembershipStatus;\n}\n\n/**\n * Membership represents a user's membership in a tenant with an assigned role.\n *\n * A user can have only one membership per tenant (UNIQUE userId + tenantId).\n * The role determines the base permissions for the user in that tenant.\n *\n * @example\n * ```typescript\n * const membership = await memberships.create({\n * userId: user.id,\n * tenantId: tenant.id,\n * roleId: role.id,\n * status: MembershipStatus.ACTIVE\n * });\n * await membership.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated surface — RBAC/identity writes go through\n // permission-gated services, not auth-only generated CRUD (requireRouteAuth\n // is authentication-only, so a generated POST/PUT here is privilege escalation).\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Membership extends SmrtObject implements MembershipContract {\n /**\n * Foreign key to User\n */\n @foreignKey('User', { required: true })\n userId?: string;\n\n /**\n * Foreign key to Tenant\n */\n @foreignKey('Tenant', { required: true })\n tenantId?: string;\n\n /**\n * Foreign key to Role - determines base permissions\n */\n @foreignKey('Role', { required: true })\n roleId?: string;\n\n /**\n * Membership status\n */\n @field({ type: 'text' })\n status: MembershipStatus = MembershipStatus.ACTIVE;\n\n constructor(options: MembershipOptions = {}) {\n super(options);\n if (options.userId !== undefined) this.userId = options.userId;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.roleId !== undefined) this.roleId = options.roleId;\n if (options.status !== undefined) this.status = options.status;\n }\n\n /**\n * Check if membership is active\n */\n isActive(): boolean {\n return this.status === MembershipStatus.ACTIVE;\n }\n\n /**\n * Check if membership is pending (invitation not yet accepted)\n */\n isPending(): boolean {\n return this.status === MembershipStatus.PENDING;\n }\n}\n","/**\n * MembershipCollection - Collection manager for Membership objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Membership } from '../models/Membership.js';\nimport { MembershipStatus } from '../types/index.js';\n\n/**\n * Collection for managing Membership objects\n */\nexport class MembershipCollection extends SmrtCollection<Membership> {\n static readonly _itemClass = Membership;\n\n /**\n * Find all memberships for a user\n */\n async findByUser(userId: string): Promise<Membership[]> {\n return await this.list({\n where: { userId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active memberships for a user\n */\n async findActiveByUser(userId: string): Promise<Membership[]> {\n return await this.list({\n where: { userId, status: MembershipStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all memberships in a tenant\n */\n async findByTenant(tenantId: string): Promise<Membership[]> {\n return await this.list({\n where: { tenantId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find active memberships in a tenant\n */\n async findActiveByTenant(tenantId: string): Promise<Membership[]> {\n return await this.list({\n where: { tenantId, status: MembershipStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find a specific user's membership in a tenant\n */\n async findByUserAndTenant(\n userId: string,\n tenantId: string,\n ): Promise<Membership | null> {\n const results = await this.list({\n where: { userId, tenantId },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n\n /**\n * Find memberships by role\n */\n async findByRole(roleId: string): Promise<Membership[]> {\n return await this.list({\n where: { roleId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find memberships by status\n */\n async findByStatus(status: MembershipStatus): Promise<Membership[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n}\n","/**\n * MembershipOverride model - per-user permission grant/deny\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { OverrideEffect } from '../types/index.js';\n\n/**\n * Constructor options for {@link MembershipOverride}.\n */\nexport interface MembershipOverrideOptions extends SmrtObjectOptions {\n membershipId?: string;\n permissionId?: string;\n effect?: OverrideEffect;\n}\n\n/**\n * MembershipOverride allows granting or denying specific permissions\n * to a user beyond what their role and groups provide.\n *\n * Overrides are applied after role and group permissions are resolved.\n * DENY overrides take precedence over GRANT overrides.\n *\n * @example\n * ```typescript\n * // Grant a specific permission to a user\n * const override = await membershipOverrides.create({\n * membershipId: membership.id,\n * permissionId: specialPermission.id,\n * effect: OverrideEffect.GRANT\n * });\n *\n * // Deny a permission (even if role grants it)\n * const deny = await membershipOverrides.create({\n * membershipId: membership.id,\n * permissionId: dangerousPermission.id,\n * effect: OverrideEffect.DENY\n * });\n * ```\n */\n@smrt({\n // #1400: read-only generated REST + MCP surface — RBAC/identity writes go\n // through permission-gated services, not auth-only generated CRUD. mcp must\n // be explicit: an omitted mcp config generates the FULL tool surface.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class MembershipOverride extends SmrtObject {\n /**\n * Foreign key to Membership\n */\n @foreignKey('Membership', { required: true })\n membershipId?: string;\n\n /**\n * Foreign key to Permission\n */\n @foreignKey('Permission', { required: true })\n permissionId?: string;\n\n /**\n * Effect of the override: grant or deny\n */\n @field({ type: 'text' })\n effect: OverrideEffect = OverrideEffect.GRANT;\n\n constructor(options: MembershipOverrideOptions = {}) {\n super(options);\n if (options.membershipId !== undefined)\n this.membershipId = options.membershipId;\n if (options.permissionId !== undefined)\n this.permissionId = options.permissionId;\n if (options.effect !== undefined) this.effect = options.effect;\n }\n\n /**\n * Check if this override grants the permission\n */\n isGrant(): boolean {\n return this.effect === OverrideEffect.GRANT;\n }\n\n /**\n * Check if this override denies the permission\n */\n isDeny(): boolean {\n return this.effect === OverrideEffect.DENY;\n }\n}\n","/**\n * MembershipOverrideCollection - Collection manager for MembershipOverride objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { MembershipOverride } from '../models/MembershipOverride.js';\nimport { OverrideEffect } from '../types/index.js';\n\n/**\n * Collection for managing MembershipOverride objects\n */\nexport class MembershipOverrideCollection extends SmrtCollection<MembershipOverride> {\n static readonly _itemClass = MembershipOverride;\n\n /**\n * Find all overrides for a membership\n */\n async findByMembership(membershipId: string): Promise<MembershipOverride[]> {\n return await this.list({\n where: { membershipId },\n });\n }\n\n /**\n * Find grant overrides for a membership.\n *\n * Filters in memory because the `effect` column is JSON-typed and\n * Postgres rejects bare `json = text` comparisons. A single\n * `findByMembership` call is reused for both grant and deny lookups\n * within the same request (see `_overridesByMembership` cache).\n */\n async findGrants(membershipId: string): Promise<MembershipOverride[]> {\n const all = await this.findByMembership(membershipId);\n return all.filter((o) => o.effect === OverrideEffect.GRANT);\n }\n\n /**\n * Find deny overrides for a membership.\n *\n * See `findGrants` for rationale on in-memory filtering.\n */\n async findDenies(membershipId: string): Promise<MembershipOverride[]> {\n const all = await this.findByMembership(membershipId);\n return all.filter((o) => o.effect === OverrideEffect.DENY);\n }\n\n /**\n * Get grant permission IDs for a membership\n */\n async getGrantedPermissionIds(membershipId: string): Promise<string[]> {\n const grants = await this.findGrants(membershipId);\n return grants.map((o) => o.permissionId as string);\n }\n\n /**\n * Get denied permission IDs for a membership\n */\n async getDeniedPermissionIds(membershipId: string): Promise<string[]> {\n const denies = await this.findDenies(membershipId);\n return denies.map((o) => o.permissionId as string);\n }\n\n /**\n * Set an override for a membership\n */\n async setOverride(\n membershipId: string,\n permissionId: string,\n effect: OverrideEffect,\n ): Promise<MembershipOverride> {\n // Check if override already exists\n const existing = await this.list({\n where: { membershipId, permissionId },\n limit: 1,\n });\n\n if (existing.length > 0) {\n // Update existing override\n existing[0].effect = effect;\n await existing[0].save();\n return existing[0];\n }\n\n // Create new override\n const override = await this.create({ membershipId, permissionId, effect });\n await override.save();\n return override;\n }\n\n /**\n * Remove an override\n */\n async removeOverride(\n membershipId: string,\n permissionId: string,\n ): Promise<boolean> {\n const existing = await this.list({\n where: { membershipId, permissionId },\n limit: 1,\n });\n\n if (existing.length === 0) {\n return false;\n }\n\n await existing[0].delete();\n return true;\n }\n\n /**\n * Grant a permission to a membership\n * Convenience method for setOverride with GRANT effect\n */\n async grantPermission(\n membershipId: string,\n permissionId: string,\n ): Promise<MembershipOverride> {\n return await this.setOverride(\n membershipId,\n permissionId,\n OverrideEffect.GRANT,\n );\n }\n\n /**\n * Deny a permission for a membership\n * Convenience method for setOverride with DENY effect\n */\n async denyPermission(\n membershipId: string,\n permissionId: string,\n ): Promise<MembershipOverride> {\n return await this.setOverride(\n membershipId,\n permissionId,\n OverrideEffect.DENY,\n );\n }\n}\n","/**\n * Permission model - named capability in the system\n * @packageDocumentation\n */\n\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Parsed permission slug components\n */\nexport interface ParsedPermissionSlug {\n /** Resource part (e.g., 'articles' from 'articles.create') */\n resource: string;\n /** Action part (e.g., 'create' from 'articles.create') */\n action: string;\n /** Whether the slug follows the valid 'resource.action' pattern */\n isValid: boolean;\n}\n\n/**\n * Parse a permission slug into its resource and action components.\n * Valid format: 'resource.action' (e.g., 'articles.create')\n *\n * @param slug - The permission slug to parse\n * @returns Parsed components with validation status\n */\nexport function parsePermissionSlug(slug: string): ParsedPermissionSlug {\n const parts = slug.split('.');\n if (parts.length === 2 && parts[0] && parts[1]) {\n return {\n resource: parts[0],\n action: parts[1],\n isValid: true,\n };\n }\n return {\n resource: slug,\n action: '',\n isValid: false,\n };\n}\n\n/**\n * Validate that a permission slug follows the 'resource.action' pattern.\n *\n * @param slug - The slug to validate\n * @returns true if valid, false otherwise\n */\nexport function isValidPermissionSlug(slug: string): boolean {\n return parsePermissionSlug(slug).isValid;\n}\n\n/**\n * Constructor options for {@link Permission}.\n */\nexport interface PermissionOptions extends SmrtObjectOptions {\n name?: string;\n description?: string;\n category?: string;\n}\n\n/**\n * Permission represents a named capability in the system.\n *\n * Permissions are defined by the application and assigned to roles.\n * Permission slugs follow the pattern: resource.action (e.g., 'articles.create')\n *\n * @example\n * ```typescript\n * const permission = await permissions.create({\n * slug: 'articles.create',\n * name: 'Create Articles',\n * description: 'Allows creating new articles',\n * category: 'articles'\n * });\n * await permission.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated surface — RBAC/identity writes go through\n // permission-gated services, not auth-only generated CRUD.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Permission extends SmrtObject {\n /**\n * Display name for the permission\n */\n name: string = '';\n\n /**\n * Description of what this permission allows\n */\n description: string = '';\n\n /**\n * Category for grouping in UI (e.g., 'articles', 'users', 'settings')\n */\n category: string = '';\n\n constructor(options: PermissionOptions = {}) {\n super(options);\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.category !== undefined) this.category = options.category;\n }\n\n /**\n * Parse the permission slug into resource and action components.\n * @returns Parsed slug with resource, action, and validation status\n */\n parseSlug(): ParsedPermissionSlug {\n return parsePermissionSlug(this.slug ?? '');\n }\n\n /**\n * Get the resource part of the permission slug\n * e.g., 'articles.create' -> 'articles'\n */\n getResource(): string {\n return this.parseSlug().resource;\n }\n\n /**\n * Get the action part of the permission slug\n * e.g., 'articles.create' -> 'create'\n */\n getAction(): string {\n return this.parseSlug().action;\n }\n\n /**\n * Check if the permission slug is valid (follows 'resource.action' pattern)\n */\n isValidSlug(): boolean {\n return this.parseSlug().isValid;\n }\n}\n","/**\n * PermissionCollection - Collection manager for Permission objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Permission } from '../models/Permission.js';\n\n/**\n * Collection for managing Permission objects\n */\nexport class PermissionCollection extends SmrtCollection<Permission> {\n static readonly _itemClass = Permission;\n\n /**\n * Find permissions by category\n */\n async findByCategory(category: string): Promise<Permission[]> {\n return await this.list({\n where: { category },\n orderBy: 'slug ASC',\n });\n }\n\n /**\n * Find permission by slug\n */\n async findBySlug(slug: string): Promise<Permission | null> {\n const results = await this.list({\n where: { slug },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n\n /**\n * Batch fetch permissions by IDs\n * Returns a Map of id -> Permission for efficient lookup\n */\n async findByIds(ids: string[]): Promise<Map<string, Permission>> {\n if (ids.length === 0) {\n return new Map();\n }\n\n // Remove duplicates\n const uniqueIds = [...new Set(ids)];\n\n // Build placeholders for SQL IN clause\n const placeholders = uniqueIds.map(() => '?').join(', ');\n const results = await this.query(\n `SELECT * FROM ${this.tableName} WHERE id IN (${placeholders})`,\n uniqueIds,\n );\n\n const map = new Map<string, Permission>();\n for (const perm of results) {\n if (perm.id) {\n map.set(perm.id, perm);\n }\n }\n return map;\n }\n\n /**\n * Get all unique categories\n */\n async getCategories(): Promise<string[]> {\n const results = await this.query(\n `SELECT DISTINCT category FROM ${this.tableName} WHERE category != '' ORDER BY category ASC`,\n );\n return results.map((r) => r.category);\n }\n\n /**\n * Find or create a permission by slug\n */\n async findOrCreate(\n slug: string,\n defaults: Partial<{\n name: string;\n description: string;\n category: string;\n }> = {},\n ): Promise<Permission> {\n const existing = await this.findBySlug(slug);\n if (existing) {\n return existing;\n }\n\n const permission = await this.create({\n slug,\n name: defaults.name ?? slug,\n description: defaults.description ?? '',\n category: defaults.category ?? slug.split('.')[0],\n });\n await permission.save();\n return permission;\n }\n}\n","/**\n * RolePermission model - Role has Permission (join table)\n * @packageDocumentation\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Constructor options for {@link RolePermission}.\n */\nexport interface RolePermissionOptions extends SmrtObjectOptions {\n roleId?: string;\n permissionId?: string;\n}\n\n/**\n * RolePermission is a join table linking Roles to Permissions.\n *\n * This enables many-to-many relationship between roles and permissions.\n * A role can have multiple permissions, and a permission can belong to multiple roles.\n *\n * @example\n * ```typescript\n * // Assign a permission to a role\n * const rolePermission = await rolePermissions.create({\n * roleId: adminRole.id,\n * permissionId: createArticlePermission.id\n * });\n * await rolePermission.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated REST + MCP surface — RBAC/identity writes go\n // through permission-gated services, not auth-only generated CRUD. mcp must\n // be explicit: an omitted mcp config generates the FULL tool surface.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class RolePermission extends SmrtObject {\n /**\n * Foreign key to Role\n */\n @foreignKey('Role', { required: true })\n roleId?: string;\n\n /**\n * Foreign key to Permission\n */\n @foreignKey('Permission', { required: true })\n permissionId?: string;\n\n constructor(options: RolePermissionOptions = {}) {\n super(options);\n if (options.roleId !== undefined) this.roleId = options.roleId;\n if (options.permissionId !== undefined)\n this.permissionId = options.permissionId;\n }\n}\n","/**\n * RolePermissionCollection - Collection manager for RolePermission objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { RolePermission } from '../models/RolePermission.js';\n\n/**\n * Collection for managing RolePermission objects\n */\nexport class RolePermissionCollection extends SmrtCollection<RolePermission> {\n static readonly _itemClass = RolePermission;\n\n /**\n * Find all permissions for a role\n */\n async findByRole(roleId: string): Promise<RolePermission[]> {\n return await this.list({\n where: { roleId },\n });\n }\n\n /**\n * Find all roles that have a permission\n */\n async findByPermission(permissionId: string): Promise<RolePermission[]> {\n return await this.list({\n where: { permissionId },\n });\n }\n\n /**\n * Check if a role has a specific permission\n */\n async hasPermission(roleId: string, permissionId: string): Promise<boolean> {\n const results = await this.list({\n where: { roleId, permissionId },\n limit: 1,\n });\n return results.length > 0;\n }\n\n /**\n * Add a permission to a role\n */\n async addPermission(\n roleId: string,\n permissionId: string,\n ): Promise<RolePermission> {\n // Check if already exists\n const existing = await this.list({\n where: { roleId, permissionId },\n limit: 1,\n });\n if (existing.length > 0) {\n return existing[0];\n }\n\n const rolePermission = await this.create({ roleId, permissionId });\n await rolePermission.save();\n return rolePermission;\n }\n\n /**\n * Remove a permission from a role\n */\n async removePermission(\n roleId: string,\n permissionId: string,\n ): Promise<boolean> {\n const existing = await this.list({\n where: { roleId, permissionId },\n limit: 1,\n });\n if (existing.length === 0) {\n return false;\n }\n\n await existing[0].delete();\n return true;\n }\n\n /**\n * Get permission IDs for a role\n */\n async getPermissionIds(roleId: string): Promise<string[]> {\n const rolePermissions = await this.findByRole(roleId);\n return rolePermissions.map((rp) => rp.permissionId as string);\n }\n}\n","/**\n * Session model - Server-side session management for authenticated users\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { SessionStatus } from '../types/index.js';\n\n/**\n * Constructor options for {@link Session}.\n */\nexport interface SessionOptions extends SmrtObjectOptions {\n userId?: string;\n tenantId?: string | null;\n status?: SessionStatus;\n /** Accepts a Date or any value the Date constructor can coerce. */\n expiresAt?: Date | string | number;\n userAgent?: string;\n ipAddress?: string;\n /** Accepts a Date or any value the Date constructor can coerce. */\n lastAccessedAt?: Date | string | number;\n data?: Record<string, unknown>;\n}\n\n/**\n * Default session TTL: 7 days in seconds\n */\nexport const DEFAULT_SESSION_TTL = 7 * 24 * 60 * 60;\n\n/**\n * Generate a cryptographically secure session ID\n */\nexport function generateSessionId(): string {\n // Use crypto.randomUUID for secure, unique session IDs\n return crypto.randomUUID();\n}\n\n/**\n * Session represents an authenticated user session.\n *\n * Sessions are stored server-side and linked to users.\n * A session ID is stored in a cookie and used to look up the session.\n *\n * @example\n * ```typescript\n * const session = await sessions.create({\n * userId: user.id,\n * tenantId: tenant.id,\n * expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),\n * userAgent: request.headers.get('user-agent'),\n * ipAddress: getClientAddress(event)\n * });\n * await session.save();\n * ```\n */\n@smrt({\n // Sessions should not be exposed via public API for security\n api: { include: ['get', 'delete'] },\n mcp: { include: [] },\n cli: true,\n})\nexport class Session extends SmrtObject {\n /**\n * User who owns this session\n */\n @foreignKey('User')\n userId: string = '';\n\n /**\n * Tenant context for this session (for multi-tenant apps)\n * Null means no tenant context selected\n */\n @foreignKey('Tenant', { nullable: true })\n tenantId: string | null = null;\n\n /**\n * Session status\n */\n @field({ type: 'text' })\n status: SessionStatus = SessionStatus.ACTIVE;\n\n /**\n * Session expiration time\n */\n expiresAt: Date = new Date();\n\n /**\n * User agent string from the browser\n */\n userAgent: string = '';\n\n /**\n * IP address of the client\n */\n ipAddress: string = '';\n\n /**\n * Last activity timestamp (updated on each request)\n */\n lastAccessedAt: Date = new Date();\n\n /**\n * Custom session data (JSON serializable)\n */\n data: Record<string, unknown> = {};\n\n constructor(options: SessionOptions = {}) {\n super(options);\n if (options.userId !== undefined) this.userId = options.userId;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.status !== undefined) this.status = options.status;\n if (options.expiresAt !== undefined) {\n this.expiresAt =\n options.expiresAt instanceof Date\n ? options.expiresAt\n : new Date(options.expiresAt);\n }\n if (options.userAgent !== undefined) this.userAgent = options.userAgent;\n if (options.ipAddress !== undefined) this.ipAddress = options.ipAddress;\n if (options.lastAccessedAt !== undefined) {\n this.lastAccessedAt =\n options.lastAccessedAt instanceof Date\n ? options.lastAccessedAt\n : new Date(options.lastAccessedAt);\n }\n if (options.data !== undefined) this.data = options.data;\n }\n\n /**\n * Check if the session is currently valid (active and not expired)\n */\n isValid(): boolean {\n return this.status === SessionStatus.ACTIVE && new Date() < this.expiresAt;\n }\n\n /**\n * Check if the session has expired\n */\n isExpired(): boolean {\n return new Date() >= this.expiresAt;\n }\n\n /**\n * Check if the session was revoked\n */\n isRevoked(): boolean {\n return this.status === SessionStatus.REVOKED;\n }\n\n /**\n * Update the last accessed timestamp\n */\n touch(): void {\n this.lastAccessedAt = new Date();\n }\n\n /**\n * Extend the session expiration by the given TTL (in seconds)\n */\n extend(ttlSeconds: number = DEFAULT_SESSION_TTL): void {\n this.expiresAt = new Date(Date.now() + ttlSeconds * 1000);\n this.touch();\n }\n\n /**\n * Revoke the session\n */\n revoke(): void {\n this.status = SessionStatus.REVOKED;\n }\n\n /**\n * Set the tenant context for this session\n */\n setTenant(tenantId: string | null): void {\n this.tenantId = tenantId;\n }\n\n /**\n * Get or set custom session data\n */\n getData<T>(key: string): T | undefined {\n return this.data[key] as T | undefined;\n }\n\n /**\n * Set custom session data\n */\n setData(key: string, value: unknown): void {\n this.data[key] = value;\n }\n\n /**\n * Remove custom session data\n */\n removeData(key: string): void {\n delete this.data[key];\n }\n}\n","/**\n * SessionCollection - Collection manager for Session objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n DEFAULT_SESSION_TTL,\n generateSessionId,\n Session,\n} from '../models/Session.js';\nimport { SessionStatus } from '../types/index.js';\n\n/**\n * Options for creating a new session\n */\nexport interface CreateSessionOptions {\n /** User ID for the session */\n userId: string;\n /** Optional tenant ID for multi-tenant context */\n tenantId?: string;\n /** Session TTL in seconds (default: 7 days) */\n ttl?: number;\n /** User agent string */\n userAgent?: string;\n /** Client IP address */\n ipAddress?: string;\n /** Custom session data */\n data?: Record<string, unknown>;\n}\n\n/**\n * Collection for managing Session objects\n */\nexport class SessionCollection extends SmrtCollection<Session> {\n static readonly _itemClass = Session;\n\n /**\n * Create a new session with a secure ID\n */\n async createSession(options: CreateSessionOptions): Promise<Session> {\n const ttl = options.ttl ?? DEFAULT_SESSION_TTL;\n const expiresAt = new Date(Date.now() + ttl * 1000);\n\n const session = await this.create({\n id: generateSessionId(),\n userId: options.userId,\n tenantId: options.tenantId ?? null,\n status: SessionStatus.ACTIVE,\n expiresAt,\n userAgent: options.userAgent ?? '',\n ipAddress: options.ipAddress ?? '',\n lastAccessedAt: new Date(),\n data: options.data ?? {},\n });\n\n await session.save();\n return session;\n }\n\n /**\n * Find a valid session by ID\n * Returns null if session doesn't exist, is expired, or is revoked\n */\n async findValidSession(sessionId: string): Promise<Session | null> {\n const session = await this.get(sessionId);\n if (!session) return null;\n\n // Check if session is still valid\n if (!session.isValid()) {\n // If expired but still marked active, flip the status with an atomic\n // guarded UPDATE rather than a read-then-save(). A non-atomic save()\n // rewrites the whole row and could clobber a concurrent revoke/extend on\n // a lock-less backend; the WHERE clause makes the EXPIRED transition a\n // no-op once another writer has already changed the status or expiry.\n if (session.isExpired() && session.status === SessionStatus.ACTIVE) {\n const now = new Date().toISOString();\n await this.db.query(\n `UPDATE ${this.tableName}\n SET status = ?, updated_at = ?\n WHERE id = ? AND status = ? AND expires_at < ?`,\n SessionStatus.EXPIRED,\n now,\n sessionId,\n SessionStatus.ACTIVE,\n now,\n );\n }\n return null;\n }\n\n return session;\n }\n\n /**\n * Update last accessed time and optionally extend session\n */\n async touch(\n sessionId: string,\n extendTtl: boolean = false,\n ttl: number = DEFAULT_SESSION_TTL,\n ): Promise<boolean> {\n const session = await this.findValidSession(sessionId);\n if (!session) return false;\n\n session.touch();\n if (extendTtl) {\n session.extend(ttl);\n }\n await session.save();\n return true;\n }\n\n /**\n * Find all active sessions for a user\n */\n async findByUser(userId: string): Promise<Session[]> {\n const results = await this.list({\n where: {\n userId,\n status: SessionStatus.ACTIVE,\n },\n orderBy: 'last_accessed_at DESC',\n });\n\n // Filter out expired sessions\n return results.filter((session) => session.isValid());\n }\n\n /**\n * Delete all sessions for a user (logout from all devices)\n */\n async deleteUserSessions(userId: string): Promise<number> {\n const sessions = await this.list({\n where: { userId },\n });\n\n let count = 0;\n for (const session of sessions) {\n await session.delete();\n count++;\n }\n\n return count;\n }\n\n /**\n * Revoke all sessions for a user (soft delete)\n */\n async revokeUserSessions(userId: string): Promise<number> {\n const sessions = await this.list({\n where: {\n userId,\n status: SessionStatus.ACTIVE,\n },\n });\n\n let count = 0;\n for (const session of sessions) {\n session.revoke();\n await session.save();\n count++;\n }\n\n return count;\n }\n\n /**\n * Revoke a specific session\n */\n async revokeSession(sessionId: string): Promise<boolean> {\n const session = await this.get(sessionId);\n if (!session) return false;\n\n session.revoke();\n await session.save();\n return true;\n }\n\n /**\n * Delete expired sessions (cleanup job)\n * Returns the number of deleted sessions\n */\n async deleteExpired(): Promise<number> {\n // #1400: a single atomic DELETE. The previous two-pass version listed\n // expired-by-time and revoked sessions separately, so a session that was\n // both got delete()'d twice — the second delete could throw and abort the\n // cleanup job mid-run, leaving expired sessions un-reaped. One statement\n // also avoids hydrating every row just to delete it.\n const now = new Date().toISOString();\n const { rowCount } = await this.db.query(\n `DELETE FROM ${this.tableName}\n WHERE expires_at < ? OR status = ?`,\n now,\n SessionStatus.REVOKED,\n );\n\n return rowCount ?? 0;\n }\n\n /**\n * Count active sessions for a user\n */\n async countUserSessions(userId: string): Promise<number> {\n const sessions = await this.findByUser(userId);\n return sessions.length;\n }\n\n /**\n * Update tenant context for a session (low-level primitive).\n *\n * SECURITY (#1400): this does NOT verify that the session's user is a member\n * of `tenantId` — it is the unguarded storage primitive. Application/route\n * code must go through {@link SessionService.switchTenant}, which fail-closes\n * on a missing/inactive membership before calling this. Calling it directly\n * with an untrusted `tenantId` reintroduces the cross-tenant access bug.\n */\n async setSessionTenant(\n sessionId: string,\n tenantId: string | null,\n ): Promise<boolean> {\n const session = await this.findValidSession(sessionId);\n if (!session) return false;\n\n session.setTenant(tenantId);\n await session.save();\n return true;\n }\n\n /**\n * Set custom session data\n */\n async setSessionData(\n sessionId: string,\n key: string,\n value: unknown,\n ): Promise<boolean> {\n const session = await this.findValidSession(sessionId);\n if (!session) return false;\n\n session.setData(key, value);\n await session.save();\n return true;\n }\n\n /**\n * Get custom session data\n */\n async getSessionData<T>(\n sessionId: string,\n key: string,\n ): Promise<T | undefined> {\n const session = await this.findValidSession(sessionId);\n if (!session) return undefined;\n\n return session.getData<T>(key);\n }\n}\n","/**\n * Tenant model - organizational boundary for multi-tenancy\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { Tenant as TenantContract } from '@happyvertical/smrt-types';\nimport { TenantStatus } from '../types/index.js';\n\n/**\n * Constructor options for {@link Tenant}.\n */\nexport interface TenantOptions extends SmrtObjectOptions {\n name?: string;\n status?: TenantStatus;\n description?: string;\n parentTenantId?: string | null;\n hierarchyLevel?: number;\n hierarchyPath?: string;\n cascadePermissions?: boolean;\n inheritPermissions?: boolean;\n}\n\n/**\n * Maximum allowed depth for tenant hierarchy.\n * Prevents excessively deep trees that could cause performance issues.\n */\nexport const MAX_TENANT_HIERARCHY_DEPTH = 10;\n\n/**\n * Tenant represents an organizational boundary in the multi-tenant system.\n *\n * Supports hierarchical organization with parent-child relationships.\n * Users can belong to multiple tenants through Memberships.\n * Each tenant can have custom roles in addition to system defaults.\n *\n * ## Hierarchical Tenants\n *\n * Tenants can be organized in a tree structure where child tenants\n * can optionally inherit permissions from their parent tenants.\n *\n * ### Cascade Control\n *\n * Two flags control permission inheritance:\n * - `cascadePermissions`: If true, this tenant pushes its permissions to children\n * - `inheritPermissions`: If true, this tenant accepts permissions from parent\n *\n * Both must be true for inheritance to flow from parent to child.\n *\n * @example\n * ```typescript\n * // Create root tenant\n * const corp = await tenants.create({\n * name: 'Acme Corporation',\n * slug: 'acme-corp',\n * cascadePermissions: true, // Push permissions to children\n * });\n * await corp.save();\n *\n * // Create child tenant that inherits\n * const division = await tenants.create({\n * name: 'Acme West Division',\n * slug: 'acme-west',\n * parentTenantId: corp.id,\n * inheritPermissions: true, // Accept parent permissions\n * });\n * await division.save();\n *\n * // Create independent child (breaks inheritance chain)\n * const independent = await tenants.create({\n * name: 'Acme Labs',\n * slug: 'acme-labs',\n * parentTenantId: corp.id,\n * inheritPermissions: false, // Does NOT inherit from parent\n * });\n * await independent.save();\n * ```\n */\n@smrt({\n tableStrategy: 'sti',\n // #1400: read-only generated surface — tenant create/update (incl. the\n // cascadePermissions/inheritPermissions flags that drive the permission\n // cascade) goes through TenantService, not auth-only generated CRUD.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class Tenant extends SmrtObject implements TenantContract {\n /**\n * Display name for the tenant\n */\n name: string = '';\n\n /**\n * Tenant status\n */\n @field({ type: 'text' })\n status: TenantStatus = TenantStatus.ACTIVE;\n\n /**\n * Optional description\n */\n description: string = '';\n\n // ============= Hierarchy Fields =============\n\n /**\n * Parent tenant ID for hierarchical organization.\n * Null for root-level tenants.\n */\n @foreignKey('Tenant', { nullable: true })\n parentTenantId?: string | null;\n\n /**\n * Depth in the hierarchy tree (0 = root, 1 = first level child, etc.)\n * Automatically managed by TenantCollection methods.\n */\n hierarchyLevel: number = 0;\n\n /**\n * Materialized path for efficient tree traversal.\n * Format: \"ancestor-id/parent-id\" (path to parent; does not include this tenant's id)\n * Empty string for root tenants.\n * Automatically managed by TenantCollection methods.\n */\n hierarchyPath: string = '';\n\n // ============= Permission Cascade Control =============\n\n /**\n * If true, this tenant's permissions cascade DOWN to child tenants.\n * Children can still opt-out by setting inheritPermissions: false.\n * Default: true\n */\n cascadePermissions: boolean = true;\n\n /**\n * If true, this tenant ACCEPTS permissions from its parent tenant.\n * Parent must also have cascadePermissions: true for inheritance to work.\n * Default: true\n */\n inheritPermissions: boolean = true;\n\n constructor(options: TenantOptions = {}) {\n super(options);\n if (options.name !== undefined) this.name = options.name;\n if (options.status !== undefined) this.status = options.status;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.parentTenantId !== undefined)\n this.parentTenantId = options.parentTenantId;\n if (options.hierarchyLevel !== undefined)\n this.hierarchyLevel = options.hierarchyLevel;\n if (options.hierarchyPath !== undefined)\n this.hierarchyPath = options.hierarchyPath;\n if (options.cascadePermissions !== undefined)\n this.cascadePermissions = options.cascadePermissions;\n if (options.inheritPermissions !== undefined)\n this.inheritPermissions = options.inheritPermissions;\n }\n\n /**\n * Check if tenant is active\n */\n isActive(): boolean {\n return this.status === TenantStatus.ACTIVE;\n }\n\n /**\n * Check if tenant is suspended\n */\n isSuspended(): boolean {\n return this.status === TenantStatus.SUSPENDED;\n }\n\n /**\n * Check if this is a root-level tenant (no parent)\n */\n isRoot(): boolean {\n return !this.parentTenantId;\n }\n\n /**\n * Check if this tenant is configured to cascade permissions to children.\n *\n * Note: This does NOT indicate whether any child tenants actually exist.\n * Use TenantCollection.findChildren() for accurate child lookup.\n */\n canCascadeToChildren(): boolean {\n return this.cascadePermissions;\n }\n\n /**\n * Check if permission inheritance is active for this tenant.\n * Inheritance is active if:\n * - This tenant has a parent AND\n * - This tenant has inheritPermissions: true\n *\n * Note: The parent must also have cascadePermissions: true\n * for actual inheritance to occur. Use PermissionResolver\n * for accurate permission calculation.\n */\n acceptsInheritance(): boolean {\n return !!this.parentTenantId && this.inheritPermissions;\n }\n\n /**\n * Get ancestor IDs from the hierarchy path.\n * Returns an array of tenant IDs from root to immediate parent.\n * Empty array for root tenants.\n */\n getAncestorIds(): string[] {\n if (!this.hierarchyPath) return [];\n return this.hierarchyPath.split('/').filter((id) => id.length > 0);\n }\n}\n","/**\n * TenantCollection - Collection manager for Tenant objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection, type SmrtCreateInput } from '@happyvertical/smrt-core';\nimport { MAX_TENANT_HIERARCHY_DEPTH, Tenant } from '../models/Tenant.js';\nimport { TenantStatus } from '../types/index.js';\n\n/**\n * Error thrown when tenant hierarchy operations fail\n */\nexport class TenantHierarchyError extends Error {\n constructor(\n message: string,\n public readonly code:\n | 'CIRCULAR_REFERENCE'\n | 'MAX_DEPTH_EXCEEDED'\n | 'PARENT_NOT_FOUND'\n | 'INVALID_OPERATION',\n ) {\n super(message);\n this.name = 'TenantHierarchyError';\n }\n}\n\n/**\n * Options for creating a child tenant\n */\nexport interface CreateChildTenantOptions {\n name: string;\n slug?: string;\n description?: string;\n status?: TenantStatus;\n /** Override parent's cascade setting for this child. Default: true */\n inheritPermissions?: boolean;\n /** Whether this child cascades permissions to its children. Default: true */\n cascadePermissions?: boolean;\n}\n\n/**\n * Collection for managing Tenant objects with hierarchical support.\n *\n * Provides methods for:\n * - Basic CRUD operations\n * - Hierarchy management (parent/child relationships)\n * - Tree traversal (ancestors, descendants, siblings)\n * - Hierarchy path maintenance\n */\nexport class TenantCollection extends SmrtCollection<Tenant> {\n static readonly _itemClass = Tenant;\n\n // ============= Basic Query Methods =============\n\n /**\n * Find tenants by status\n */\n async findByStatus(status: TenantStatus): Promise<Tenant[]> {\n return await this.list({\n where: { status },\n orderBy: 'name ASC',\n });\n }\n\n /**\n * Find all active tenants\n */\n async findActive(): Promise<Tenant[]> {\n return await this.findByStatus(TenantStatus.ACTIVE);\n }\n\n /**\n * Find tenant by slug\n */\n async findBySlug(slug: string): Promise<Tenant | null> {\n const results = await this.list({\n where: { slug },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n\n // ============= Hierarchy Query Methods =============\n\n /**\n * Find all root tenants (tenants with no parent)\n */\n async findRoots(): Promise<Tenant[]> {\n return await this.list({\n where: { parentTenantId: null },\n orderBy: 'name ASC',\n });\n }\n\n /**\n * Find direct children of a tenant\n */\n async findChildren(parentTenantId: string): Promise<Tenant[]> {\n return await this.list({\n where: { parentTenantId },\n orderBy: 'name ASC',\n });\n }\n\n /**\n * Find the parent tenant of a given tenant\n */\n async findParent(tenantId: string): Promise<Tenant | null> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant || !tenant.parentTenantId) {\n return null;\n }\n return await this.get({ id: tenant.parentTenantId });\n }\n\n /**\n * Get all ancestors of a tenant, from immediate parent to root.\n * Uses the hierarchyPath for efficient lookup.\n */\n async getAncestors(tenantId: string): Promise<Tenant[]> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant) {\n return [];\n }\n\n const ancestorIds = tenant.getAncestorIds();\n if (ancestorIds.length === 0) {\n return [];\n }\n\n // Batch fetch all ancestors\n const ancestorsList = await this.listByIds(ancestorIds);\n const ancestorsMap = new Map(ancestorsList.map((a) => [a.id, a]));\n\n // Return in order from immediate parent to root\n const ancestors: Tenant[] = [];\n for (let i = ancestorIds.length - 1; i >= 0; i--) {\n const ancestor = ancestorsMap.get(ancestorIds[i]);\n if (ancestor) {\n ancestors.push(ancestor);\n }\n }\n\n return ancestors;\n }\n\n /**\n * Get all ancestors in order from root to immediate parent.\n * Reverse of getAncestors.\n */\n async getAncestorsFromRoot(tenantId: string): Promise<Tenant[]> {\n const ancestors = await this.getAncestors(tenantId);\n return ancestors.reverse();\n }\n\n /**\n * Get all descendants of a tenant (all children, grandchildren, etc.)\n * Uses hierarchyPath prefix matching for efficient lookup.\n */\n async getDescendants(tenantId: string): Promise<Tenant[]> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant || !tenant.id) {\n return [];\n }\n\n // Build the path prefix to search for\n const pathPrefix = tenant.hierarchyPath\n ? `${tenant.hierarchyPath}/${tenant.id}`\n : tenant.id;\n\n // Use database-level LIKE query for initial filtering\n // This is much more efficient than loading all tenants for large hierarchies\n const candidates = await this.list({\n where: {\n 'hierarchyPath like': `${pathPrefix}%`,\n },\n });\n\n // Apply boundary check in memory to avoid false positives\n // Without the '/' check, \"ancestor/tenant1\" would incorrectly match \"ancestor/tenant123\"\n return candidates.filter(\n (t) =>\n t.hierarchyPath === pathPrefix ||\n t.hierarchyPath?.startsWith(`${pathPrefix}/`),\n );\n }\n\n /**\n * Get siblings of a tenant (other tenants with the same parent)\n */\n async getSiblings(tenantId: string): Promise<Tenant[]> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant) {\n return [];\n }\n\n const siblings = await this.list({\n where: { parentTenantId: tenant.parentTenantId ?? null },\n orderBy: 'name ASC',\n });\n\n // Exclude self from siblings\n return siblings.filter((s) => s.id !== tenantId);\n }\n\n /**\n * Check if a tenant is an ancestor of another tenant\n */\n async isAncestorOf(\n potentialAncestorId: string,\n tenantId: string,\n ): Promise<boolean> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant) {\n return false;\n }\n\n const ancestorIds = tenant.getAncestorIds();\n return ancestorIds.includes(potentialAncestorId);\n }\n\n /**\n * Check if a tenant is a descendant of another tenant\n */\n async isDescendantOf(\n potentialDescendantId: string,\n tenantId: string,\n ): Promise<boolean> {\n return await this.isAncestorOf(tenantId, potentialDescendantId);\n }\n\n // ============= Hierarchy Management Methods =============\n\n /**\n * Create a child tenant under a parent.\n * Automatically sets hierarchyLevel and hierarchyPath.\n */\n async createChild(\n parentTenantId: string,\n options: CreateChildTenantOptions,\n ): Promise<Tenant> {\n const parent = await this.get({ id: parentTenantId });\n if (!parent?.id) {\n throw new TenantHierarchyError(\n `Parent tenant not found: ${parentTenantId}`,\n 'PARENT_NOT_FOUND',\n );\n }\n\n // Check depth limit\n const newLevel = parent.hierarchyLevel + 1;\n if (newLevel >= MAX_TENANT_HIERARCHY_DEPTH) {\n throw new TenantHierarchyError(\n `Maximum hierarchy depth (${MAX_TENANT_HIERARCHY_DEPTH}) exceeded`,\n 'MAX_DEPTH_EXCEEDED',\n );\n }\n\n // Build hierarchy path\n const newPath = parent.hierarchyPath\n ? `${parent.hierarchyPath}/${parent.id}`\n : parent.id;\n\n const child = await this.create({\n name: options.name,\n slug: options.slug,\n description: options.description ?? '',\n status: options.status ?? TenantStatus.ACTIVE,\n parentTenantId: parentTenantId,\n hierarchyLevel: newLevel,\n hierarchyPath: newPath,\n cascadePermissions: options.cascadePermissions ?? true,\n inheritPermissions: options.inheritPermissions ?? true,\n });\n\n await child.save();\n return child;\n }\n\n /**\n * Move a tenant to a new parent.\n * Updates hierarchyLevel and hierarchyPath for the tenant and all descendants.\n */\n async moveToParent(\n tenantId: string,\n newParentId: string | null,\n ): Promise<Tenant> {\n const tenant = await this.get({ id: tenantId });\n if (!tenant || !tenant.id) {\n throw new TenantHierarchyError(\n `Tenant not found: ${tenantId}`,\n 'INVALID_OPERATION',\n );\n }\n\n // Validate not moving to self\n if (newParentId === tenantId) {\n throw new TenantHierarchyError(\n 'Cannot move tenant to itself',\n 'CIRCULAR_REFERENCE',\n );\n }\n\n // Validate not moving to a descendant\n if (newParentId) {\n const isDescendant = await this.isDescendantOf(newParentId, tenantId);\n if (isDescendant) {\n throw new TenantHierarchyError(\n 'Cannot move tenant to one of its descendants',\n 'CIRCULAR_REFERENCE',\n );\n }\n }\n\n // Fetch descendants BEFORE any changes (uses current hierarchyPath for lookup)\n const descendants = await this.getDescendants(tenantId);\n\n let newLevel: number;\n let newPath: string;\n\n if (newParentId === null) {\n // Moving to root\n newLevel = 0;\n newPath = '';\n } else {\n const newParent = await this.get({ id: newParentId });\n if (!newParent) {\n throw new TenantHierarchyError(\n `New parent tenant not found: ${newParentId}`,\n 'PARENT_NOT_FOUND',\n );\n }\n\n newLevel = newParent.hierarchyLevel + 1;\n\n // Check depth limit (considering descendants)\n const maxDescendantDepth = descendants.reduce(\n (max, d) => Math.max(max, d.hierarchyLevel - tenant.hierarchyLevel),\n 0,\n );\n\n if (newLevel + maxDescendantDepth >= MAX_TENANT_HIERARCHY_DEPTH) {\n throw new TenantHierarchyError(\n `Moving would exceed maximum hierarchy depth (${MAX_TENANT_HIERARCHY_DEPTH})`,\n 'MAX_DEPTH_EXCEEDED',\n );\n }\n\n newPath = newParent.hierarchyPath\n ? `${newParent.hierarchyPath}/${newParent.id}`\n : newParent.id!;\n }\n\n // Calculate the path prefix for descendants\n const oldPath = tenant.hierarchyPath\n ? `${tenant.hierarchyPath}/${tenant.id}`\n : tenant.id;\n const newPathForDescendants = newPath\n ? `${newPath}/${tenant.id}`\n : tenant.id;\n\n // Update the tenant\n const levelDelta = newLevel - tenant.hierarchyLevel;\n tenant.parentTenantId = newParentId;\n tenant.hierarchyLevel = newLevel;\n tenant.hierarchyPath = newPath;\n await tenant.save();\n\n // Update all descendants (using the list fetched before changes)\n for (const descendant of descendants) {\n // Validate descendant has hierarchyPath - missing path indicates data corruption\n if (!descendant.hierarchyPath) {\n throw new TenantHierarchyError(\n `Descendant tenant ${descendant.id} has no hierarchyPath while updating hierarchy from ${oldPath} to ${newPathForDescendants}`,\n 'INVALID_OPERATION',\n );\n }\n\n // Validate descendant path starts with expected prefix\n if (!descendant.hierarchyPath.startsWith(oldPath)) {\n throw new TenantHierarchyError(\n `Descendant tenant ${descendant.id} has hierarchyPath \"${descendant.hierarchyPath}\" which does not start with expected prefix \"${oldPath}\"`,\n 'INVALID_OPERATION',\n );\n }\n\n // Update path by replacing old prefix with new prefix\n descendant.hierarchyPath =\n newPathForDescendants +\n descendant.hierarchyPath.substring(oldPath.length);\n\n // Adjust level by the same delta\n descendant.hierarchyLevel += levelDelta;\n await descendant.save();\n }\n\n return tenant;\n }\n\n /**\n * Make a tenant a root tenant (remove from hierarchy)\n */\n async makeRoot(tenantId: string): Promise<Tenant> {\n return await this.moveToParent(tenantId, null);\n }\n\n /**\n * Validate that a tenant hierarchy is consistent.\n * Returns validation errors if any.\n */\n async validateHierarchy(tenantId: string): Promise<string[]> {\n const errors: string[] = [];\n const tenant = await this.get({ id: tenantId });\n\n if (!tenant) {\n return [`Tenant not found: ${tenantId}`];\n }\n\n // Check parent exists if set\n if (tenant.parentTenantId) {\n const parent = await this.get({ id: tenant.parentTenantId });\n if (!parent) {\n errors.push(`Parent tenant not found: ${tenant.parentTenantId}`);\n } else {\n // Check hierarchy level\n if (tenant.hierarchyLevel !== parent.hierarchyLevel + 1) {\n errors.push(\n `Hierarchy level mismatch: expected ${parent.hierarchyLevel + 1}, got ${tenant.hierarchyLevel}`,\n );\n }\n\n // Check hierarchy path\n const expectedPath = parent.hierarchyPath\n ? `${parent.hierarchyPath}/${parent.id}`\n : parent.id;\n if (tenant.hierarchyPath !== expectedPath) {\n errors.push(\n `Hierarchy path mismatch: expected \"${expectedPath}\", got \"${tenant.hierarchyPath}\"`,\n );\n }\n }\n } else {\n // Root tenant checks\n if (tenant.hierarchyLevel !== 0) {\n errors.push(\n `Root tenant should have hierarchyLevel 0, got ${tenant.hierarchyLevel}`,\n );\n }\n if (tenant.hierarchyPath !== '') {\n errors.push(\n `Root tenant should have empty hierarchyPath, got \"${tenant.hierarchyPath}\"`,\n );\n }\n }\n\n // Check for circular reference (shouldn't be possible with path, but double-check)\n if (tenant.parentTenantId && tenant.id) {\n const ancestorIds = tenant.getAncestorIds();\n if (ancestorIds.includes(tenant.id)) {\n errors.push('Circular reference detected in hierarchy');\n }\n }\n\n return errors;\n }\n\n /**\n * Get the full hierarchy tree starting from a tenant.\n * Returns a nested structure useful for UI rendering.\n */\n async getTree(\n rootTenantId?: string,\n ): Promise<Array<Tenant & { children: Tenant[] }>> {\n const roots = rootTenantId\n ? [await this.get({ id: rootTenantId })]\n : await this.findRoots();\n\n const buildTree = async (\n tenant: Tenant | null,\n ): Promise<(Tenant & { children: Tenant[] }) | null> => {\n if (!tenant) return null;\n\n const children = await this.findChildren(tenant.id!);\n const childTrees = await Promise.all(children.map(buildTree));\n\n // Use Object.assign to preserve Tenant instance methods while adding children\n const tenantWithChildren = Object.assign(tenant, {\n children: childTrees.filter(Boolean) as Array<\n Tenant & { children: Tenant[] }\n >,\n });\n return tenantWithChildren as Tenant & { children: Tenant[] };\n };\n\n const trees = await Promise.all(roots.map(buildTree));\n return trees.filter(Boolean) as Array<Tenant & { children: Tenant[] }>;\n }\n\n // ============= Override create to handle hierarchy =============\n\n /**\n * Override create to automatically set hierarchy fields for new tenants.\n * Only calculates them when the caller hasn't already supplied\n * `hierarchyLevel`/`hierarchyPath` in the create input — an explicitly\n * provided value is preserved as-is.\n */\n async create(options: SmrtCreateInput<Tenant>): Promise<Tenant> {\n // If parentTenantId is provided and hierarchy fields not already set\n if (options.parentTenantId) {\n // Only calculate when the caller didn't already supply them\n // (a provided hierarchyLevel/hierarchyPath is preserved as-is)\n const needsHierarchyCalc =\n options.hierarchyLevel === undefined ||\n options.hierarchyPath === undefined;\n\n if (needsHierarchyCalc) {\n const parent = await this.get({ id: options.parentTenantId });\n if (!parent?.id) {\n throw new TenantHierarchyError(\n `Parent tenant not found: ${options.parentTenantId}`,\n 'PARENT_NOT_FOUND',\n );\n }\n\n const newLevel = parent.hierarchyLevel + 1;\n if (newLevel >= MAX_TENANT_HIERARCHY_DEPTH) {\n throw new TenantHierarchyError(\n `Maximum hierarchy depth (${MAX_TENANT_HIERARCHY_DEPTH}) exceeded`,\n 'MAX_DEPTH_EXCEEDED',\n );\n }\n\n if (options.hierarchyLevel === undefined) {\n options.hierarchyLevel = newLevel;\n }\n if (options.hierarchyPath === undefined) {\n options.hierarchyPath = parent.hierarchyPath\n ? `${parent.hierarchyPath}/${parent.id}`\n : parent.id;\n }\n }\n } else {\n // Root tenant\n options.hierarchyLevel = options.hierarchyLevel ?? 0;\n options.hierarchyPath = options.hierarchyPath ?? '';\n }\n\n return super.create(options);\n }\n}\n","/**\n * TenantPermissionOverride model - tenant-level permission grant/deny/inherit\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantPermissionEffect } from '../types/index.js';\n\n/**\n * Constructor options for {@link TenantPermissionOverride}.\n */\nexport interface TenantPermissionOverrideOptions extends SmrtObjectOptions {\n tenantId?: string;\n permissionId?: string;\n effect?: TenantPermissionEffect;\n}\n\n/**\n * TenantPermissionOverride allows setting explicit permission values at the tenant level.\n *\n * This is used in hierarchical tenant structures to control permission inheritance.\n * Each override specifies whether a permission is:\n * - INHERIT: Use the parent tenant's value (default behavior)\n * - GRANT: Explicitly grant at this tenant level\n * - DENY: Explicitly deny at this tenant level (blocks inheritance)\n *\n * ## Resolution Order\n *\n * When resolving effective tenant permissions:\n * 1. Walk down the tenant hierarchy from root to target, accumulating permissions\n * 2. Apply each tenant's overrides (DENY blocks, GRANT adds)\n * 3. INHERIT means \"use whatever the parent resolved to\"\n *\n * @example\n * ```typescript\n * // Explicitly grant a permission at this tenant level\n * const override = await tenantPermissionOverrides.create({\n * tenantId: tenant.id,\n * permissionId: specialPermission.id,\n * effect: TenantPermissionEffect.GRANT\n * });\n *\n * // Block a permission from being inherited (even if parent grants it)\n * const block = await tenantPermissionOverrides.create({\n * tenantId: tenant.id,\n * permissionId: dangerousPermission.id,\n * effect: TenantPermissionEffect.DENY\n * });\n *\n * // Explicitly inherit (same as not having an override, but documents intent)\n * const inherit = await tenantPermissionOverrides.create({\n * tenantId: tenant.id,\n * permissionId: standardPermission.id,\n * effect: TenantPermissionEffect.INHERIT\n * });\n * ```\n */\n@smrt({\n // #1400: read-only generated REST + MCP surface — RBAC/identity writes go\n // through permission-gated services, not auth-only generated CRUD. mcp must\n // be explicit: an omitted mcp config generates the FULL tool surface.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class TenantPermissionOverride extends SmrtObject {\n /**\n * Foreign key to Tenant\n */\n @foreignKey('Tenant', { required: true })\n tenantId?: string;\n\n /**\n * Foreign key to Permission\n */\n @foreignKey('Permission', { required: true })\n permissionId?: string;\n\n /**\n * Effect of the override: inherit, grant, or deny\n */\n @field({ type: 'text' })\n effect: TenantPermissionEffect = TenantPermissionEffect.INHERIT;\n\n constructor(options: TenantPermissionOverrideOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.permissionId !== undefined)\n this.permissionId = options.permissionId;\n if (options.effect !== undefined) this.effect = options.effect;\n }\n\n /**\n * Check if this override inherits from parent\n */\n isInherit(): boolean {\n return this.effect === TenantPermissionEffect.INHERIT;\n }\n\n /**\n * Check if this override grants the permission\n */\n isGrant(): boolean {\n return this.effect === TenantPermissionEffect.GRANT;\n }\n\n /**\n * Check if this override denies the permission\n */\n isDeny(): boolean {\n return this.effect === TenantPermissionEffect.DENY;\n }\n\n /**\n * Check if this override has an explicit effect (not inherit)\n */\n hasExplicitEffect(): boolean {\n return this.effect !== TenantPermissionEffect.INHERIT;\n }\n}\n","/**\n * TenantPermissionOverrideCollection - Collection manager for TenantPermissionOverride objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { TenantPermissionOverride } from '../models/TenantPermissionOverride.js';\nimport { TenantPermissionEffect } from '../types/index.js';\n\n/**\n * Result of resolving tenant permission overrides\n */\nexport interface TenantPermissionOverrideResult {\n /** Permission IDs explicitly granted at this tenant level */\n grantedPermissionIds: string[];\n /** Permission IDs explicitly denied at this tenant level */\n deniedPermissionIds: string[];\n /** Permission IDs set to inherit from parent */\n inheritedPermissionIds: string[];\n}\n\n/**\n * Collection for managing TenantPermissionOverride objects.\n *\n * Provides methods for setting and querying tenant-level permission overrides\n * used in hierarchical tenant permission inheritance.\n */\nexport class TenantPermissionOverrideCollection extends SmrtCollection<TenantPermissionOverride> {\n static readonly _itemClass = TenantPermissionOverride;\n\n /**\n * Find all overrides for a tenant\n */\n async findByTenant(tenantId: string): Promise<TenantPermissionOverride[]> {\n return await this.list({\n where: { tenantId },\n });\n }\n\n /**\n * Find grant overrides for a tenant.\n *\n * Filters in memory because the `effect` column is JSON-typed and\n * Postgres rejects bare `json = text` comparisons. A single\n * `findByTenant` call is reused for grant, deny, and inherit lookups.\n */\n async findGrants(tenantId: string): Promise<TenantPermissionOverride[]> {\n const all = await this.findByTenant(tenantId);\n return all.filter((o) => o.effect === TenantPermissionEffect.GRANT);\n }\n\n /**\n * Find deny overrides for a tenant.\n *\n * See `findGrants` for rationale on in-memory filtering.\n */\n async findDenies(tenantId: string): Promise<TenantPermissionOverride[]> {\n const all = await this.findByTenant(tenantId);\n return all.filter((o) => o.effect === TenantPermissionEffect.DENY);\n }\n\n /**\n * Find inherit overrides for a tenant.\n *\n * See `findGrants` for rationale on in-memory filtering.\n */\n async findInherits(tenantId: string): Promise<TenantPermissionOverride[]> {\n const all = await this.findByTenant(tenantId);\n return all.filter((o) => o.effect === TenantPermissionEffect.INHERIT);\n }\n\n /**\n * Get granted permission IDs for a tenant\n */\n async getGrantedPermissionIds(tenantId: string): Promise<string[]> {\n const grants = await this.findGrants(tenantId);\n return grants.map((o) => o.permissionId as string);\n }\n\n /**\n * Get denied permission IDs for a tenant\n */\n async getDeniedPermissionIds(tenantId: string): Promise<string[]> {\n const denies = await this.findDenies(tenantId);\n return denies.map((o) => o.permissionId as string);\n }\n\n /**\n * Get all overrides for a tenant, organized by effect\n */\n async getOverridesByEffect(\n tenantId: string,\n ): Promise<TenantPermissionOverrideResult> {\n const overrides = await this.findByTenant(tenantId);\n\n const result: TenantPermissionOverrideResult = {\n grantedPermissionIds: [],\n deniedPermissionIds: [],\n inheritedPermissionIds: [],\n };\n\n for (const override of overrides) {\n const permId = override.permissionId as string;\n switch (override.effect) {\n case TenantPermissionEffect.GRANT:\n result.grantedPermissionIds.push(permId);\n break;\n case TenantPermissionEffect.DENY:\n result.deniedPermissionIds.push(permId);\n break;\n case TenantPermissionEffect.INHERIT:\n result.inheritedPermissionIds.push(permId);\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Batch get all overrides for multiple tenants, organized by effect.\n * Fetches all overrides in a single query to avoid N+1 query problem.\n *\n * @param tenantIds - Array of tenant IDs to fetch overrides for\n * @returns Map of tenant ID to their permission override results\n */\n async getOverridesByEffectBatch(\n tenantIds: string[],\n ): Promise<Map<string, TenantPermissionOverrideResult>> {\n const resultMap = new Map<string, TenantPermissionOverrideResult>();\n\n // Initialize empty results for all tenant IDs\n for (const tenantId of tenantIds) {\n resultMap.set(tenantId, {\n grantedPermissionIds: [],\n deniedPermissionIds: [],\n inheritedPermissionIds: [],\n });\n }\n\n if (tenantIds.length === 0) {\n return resultMap;\n }\n\n // Fetch all overrides for all tenants in a single query\n const allOverrides = await this.list({\n where: { tenantId: tenantIds },\n });\n\n // Organize overrides by tenant and effect\n for (const override of allOverrides) {\n const tenantId = override.tenantId as string;\n const permId = override.permissionId as string;\n const result = resultMap.get(tenantId);\n\n if (result) {\n switch (override.effect) {\n case TenantPermissionEffect.GRANT:\n result.grantedPermissionIds.push(permId);\n break;\n case TenantPermissionEffect.DENY:\n result.deniedPermissionIds.push(permId);\n break;\n case TenantPermissionEffect.INHERIT:\n result.inheritedPermissionIds.push(permId);\n break;\n }\n }\n }\n\n return resultMap;\n }\n\n /**\n * Set an override for a tenant permission\n */\n async setOverride(\n tenantId: string,\n permissionId: string,\n effect: TenantPermissionEffect,\n ): Promise<TenantPermissionOverride> {\n // Check if override already exists\n const existing = await this.list({\n where: { tenantId, permissionId },\n limit: 1,\n });\n\n if (existing.length > 0) {\n // Update existing override\n existing[0].effect = effect;\n await existing[0].save();\n return existing[0];\n }\n\n // Create new override\n const override = await this.create({ tenantId, permissionId, effect });\n await override.save();\n return override;\n }\n\n /**\n * Remove an override (permission will use default behavior)\n */\n async removeOverride(\n tenantId: string,\n permissionId: string,\n ): Promise<boolean> {\n const existing = await this.list({\n where: { tenantId, permissionId },\n limit: 1,\n });\n\n if (existing.length === 0) {\n return false;\n }\n\n await existing[0].delete();\n return true;\n }\n\n /**\n * Remove all overrides for a tenant\n */\n async removeAllOverrides(tenantId: string): Promise<number> {\n const overrides = await this.findByTenant(tenantId);\n await Promise.all(overrides.map((override) => override.delete()));\n return overrides.length;\n }\n\n /**\n * Grant a permission at the tenant level.\n * Convenience method for setOverride with GRANT effect.\n */\n async grantPermission(\n tenantId: string,\n permissionId: string,\n ): Promise<TenantPermissionOverride> {\n return await this.setOverride(\n tenantId,\n permissionId,\n TenantPermissionEffect.GRANT,\n );\n }\n\n /**\n * Deny a permission at the tenant level.\n * Convenience method for setOverride with DENY effect.\n * This blocks inheritance from parent tenants.\n */\n async denyPermission(\n tenantId: string,\n permissionId: string,\n ): Promise<TenantPermissionOverride> {\n return await this.setOverride(\n tenantId,\n permissionId,\n TenantPermissionEffect.DENY,\n );\n }\n\n /**\n * Set a permission to inherit from parent.\n * Convenience method for setOverride with INHERIT effect.\n * This is the default behavior, so mainly useful to document intent\n * or to reset a previous grant/deny.\n */\n async inheritPermission(\n tenantId: string,\n permissionId: string,\n ): Promise<TenantPermissionOverride> {\n return await this.setOverride(\n tenantId,\n permissionId,\n TenantPermissionEffect.INHERIT,\n );\n }\n\n /**\n * Bulk set overrides for a tenant.\n * Useful for importing or copying permission configurations.\n */\n async bulkSetOverrides(\n tenantId: string,\n overrides: Array<{ permissionId: string; effect: TenantPermissionEffect }>,\n ): Promise<TenantPermissionOverride[]> {\n const results: TenantPermissionOverride[] = [];\n for (const { permissionId, effect } of overrides) {\n const override = await this.setOverride(tenantId, permissionId, effect);\n results.push(override);\n }\n return results;\n }\n\n /**\n * Copy overrides from one tenant to another.\n * Useful when creating child tenants or templates.\n */\n async copyOverrides(\n fromTenantId: string,\n toTenantId: string,\n ): Promise<TenantPermissionOverride[]> {\n const sourceOverrides = await this.findByTenant(fromTenantId);\n const results: TenantPermissionOverride[] = [];\n\n for (const source of sourceOverrides) {\n const override = await this.setOverride(\n toTenantId,\n source.permissionId as string,\n source.effect,\n );\n results.push(override);\n }\n\n return results;\n }\n}\n","/**\n * User model - authenticated identity linked to a Profile\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { User as UserContract } from '@happyvertical/smrt-types';\nimport { UserStatus } from '../types/index.js';\n\n/**\n * Constructor options for {@link User}.\n */\nexport interface UserOptions extends SmrtObjectOptions {\n profileId?: string;\n email?: string;\n status?: UserStatus;\n lastLoginAt?: Date | null;\n}\n\n/**\n * Basic email validation regex.\n * Validates format: local@domain.tld\n */\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/**\n * Validate email format.\n * @param email - Email address to validate\n * @returns true if email format is valid\n */\nexport function isValidEmail(email: string): boolean {\n if (!email || typeof email !== 'string') return false;\n return EMAIL_REGEX.test(email.trim());\n}\n\n/**\n * Normalize email address (lowercase and trim).\n * @param email - Email address to normalize\n * @returns Normalized email\n */\nexport function normalizeEmail(email: string): string {\n if (!email || typeof email !== 'string') return '';\n return email.trim().toLowerCase();\n}\n\n/**\n * User represents an authenticated identity in the system.\n *\n * Users are linked to Profiles from smrt-profiles via profileId.\n * A User can have multiple Memberships across different Tenants.\n *\n * @example\n * ```typescript\n * const user = await users.create({\n * profileId: 'profile-uuid',\n * email: 'user@example.com',\n * status: UserStatus.ACTIVE\n * });\n * await user.save();\n * ```\n */\n@smrt({\n // #1400: read-only generated surface — User is auth identity (email/status/\n // profileId), provisioned via OIDC/magic-link, not arbitrary authed POST/PUT.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: true,\n})\nexport class User extends SmrtObject implements UserContract {\n /**\n * Foreign key to smrt-profiles Profile (cross-package)\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile')\n profileId: string = '';\n\n /**\n * User's email address (unique, used for lookup)\n */\n email: string = '';\n\n /**\n * User account status\n */\n @field({ type: 'text' })\n status: UserStatus = UserStatus.ACTIVE;\n\n /**\n * Last login timestamp\n */\n lastLoginAt: Date | null = null;\n\n constructor(options: UserOptions = {}) {\n super(options);\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.email !== undefined) this.email = normalizeEmail(options.email);\n if (options.status !== undefined) this.status = options.status;\n if (options.lastLoginAt !== undefined)\n this.lastLoginAt = options.lastLoginAt;\n }\n\n /**\n * Validate the user's email format.\n * @returns true if email is valid\n */\n hasValidEmail(): boolean {\n return isValidEmail(this.email);\n }\n\n /**\n * Check if user is active\n */\n isActive(): boolean {\n return this.status === UserStatus.ACTIVE;\n }\n\n /**\n * Check if user is suspended\n */\n isSuspended(): boolean {\n return this.status === UserStatus.SUSPENDED;\n }\n\n /**\n * Check if user is pending verification\n */\n isPending(): boolean {\n return this.status === UserStatus.PENDING;\n }\n\n /**\n * Record a login event\n */\n recordLogin(): void {\n this.lastLoginAt = new Date();\n }\n}\n","/**\n * UserCollection - Collection manager for User objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport type { OidcIdentity, Profile } from '@happyvertical/smrt-profiles';\nimport { User } from '../models/User.js';\nimport { UserStatus } from '../types/index.js';\n\n/**\n * OIDC claims used for identity resolution\n */\nexport interface OidcClaims {\n /** Subject identifier from IdP */\n sub: string;\n /** Issuer URL */\n iss: string;\n /** User's email address */\n email?: string;\n /** Whether the IdP verified the email address */\n email_verified?: boolean;\n /** User's display name */\n name?: string;\n /** Preferred username */\n preferred_username?: string;\n}\n\n/**\n * Result of OIDC identity resolution\n */\nexport interface OidcIdentityResult {\n /** The User record */\n user: User;\n /** The linked Profile */\n profile: Profile;\n /** The OidcIdentity linking profile to IdP */\n oidcIdentity: OidcIdentity;\n /** Whether the profile was newly created */\n created: boolean;\n}\n\n/**\n * Options for getOrCreateFromOidc\n */\nexport interface GetOrCreateFromOidcOptions {\n /** If false, skip recording login timestamp (default: true) */\n recordLogin?: boolean;\n /**\n * Provision a user even when the IdP explicitly reported the email as\n * unverified (`email_verified: false`). Default false (#1400): refuse to\n * create/resolve a user from a known-unverified address. Has no effect when\n * the claim is absent — an IdP that omits `email_verified` makes no\n * assertion, so it cannot be enforced.\n */\n allowUnverifiedEmail?: boolean;\n}\n\n/**\n * Collection for managing User objects\n */\nexport class UserCollection extends SmrtCollection<User> {\n static readonly _itemClass = User;\n\n /**\n * Find user by email address\n */\n async findByEmail(email: string): Promise<User | null> {\n const results = await this.list({\n where: { email },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n\n /**\n * Find user by profile ID\n */\n async findByProfile(profileId: string): Promise<User | null> {\n const results = await this.list({\n where: { profileId },\n limit: 1,\n });\n return results.length > 0 ? results[0] : null;\n }\n\n /**\n * Find users by status\n */\n async findByStatus(status: UserStatus): Promise<User[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active users\n */\n async findActive(): Promise<User[]> {\n return await this.findByStatus(UserStatus.ACTIVE);\n }\n\n /**\n * Find all pending users\n */\n async findPending(): Promise<User[]> {\n return await this.findByStatus(UserStatus.PENDING);\n }\n\n /**\n * Get or create user for a profile\n */\n async getOrCreateForProfile(\n profileId: string,\n email: string,\n defaults: Partial<{ status: UserStatus }> = {},\n ): Promise<User> {\n const existing = await this.findByProfile(profileId);\n if (existing) {\n return existing;\n }\n\n const user = await this.create({\n profileId,\n email,\n status: defaults.status ?? UserStatus.ACTIVE,\n });\n await user.save();\n return user;\n }\n\n /**\n * Get or create user from OIDC claims\n *\n * This is the primary method for resolving identity from an OIDC login.\n * It handles the full flow:\n * 1. Find or create Profile from OIDC claims (via smrt-profiles)\n * 2. Link OidcIdentity to the Profile\n * 3. Find or create User linked to the Profile\n *\n * @param claims - OIDC token claims (sub, iss, email, name)\n * @param provider - Provider name (e.g., 'kanidm', 'keycloak', 'google')\n * @param options - Optional settings (recordLogin)\n * @returns User, Profile, OidcIdentity, and whether profile was created\n *\n * @example\n * ```typescript\n * const userCollection = await UserCollection.create({ db: dbConfig });\n *\n * // In your OIDC callback handler:\n * const { user, profile } = await userCollection.getOrCreateFromOidc(\n * {\n * sub: tokenClaims.sub,\n * iss: tokenClaims.iss,\n * email: tokenClaims.email,\n * name: tokenClaims.name,\n * },\n * 'kanidm'\n * );\n *\n * // User and profile are now available\n * // Login was auto-recorded; pass { recordLogin: false } to skip\n * ```\n */\n async getOrCreateFromOidc(\n claims: OidcClaims,\n provider: string,\n options?: GetOrCreateFromOidcOptions,\n ): Promise<OidcIdentityResult> {\n // Validate required OIDC claims at runtime\n const sub = claims?.sub?.trim();\n const iss = claims?.iss?.trim();\n if (!sub || !iss) {\n throw new Error(\n 'Invalid OIDC claims: both \"sub\" and \"iss\" must be non-empty strings.',\n );\n }\n\n // Email is required for user creation\n if (!claims.email) {\n throw new Error(\n 'OIDC claims missing required \"email\" for user creation.',\n );\n }\n\n // #1400: refuse an email the IdP explicitly marked unverified. Only an\n // explicit `email_verified === false` hard-fails; an absent claim makes no\n // assertion and cannot be enforced. Opt out with allowUnverifiedEmail.\n const allowUnverified = options?.allowUnverifiedEmail === true;\n if (claims.email_verified === false && !allowUnverified) {\n throw new Error(\n 'OIDC claims report an unverified email; refusing to provision a user.',\n );\n }\n\n // Dynamic import to avoid circular dependency between smrt-users and smrt-profiles.\n // Both packages need to reference each other's types, so we defer the import.\n const { createProfileFromOidc } = await import(\n '@happyvertical/smrt-profiles'\n );\n\n // Get database options from this collection\n const dbOptions = { db: this.options.db };\n\n // Create or find profile with linked OIDC identity\n const { profile, oidcIdentity, created } = await createProfileFromOidc(\n claims,\n provider,\n dbOptions,\n );\n\n const shouldRecordLogin = options?.recordLogin !== false;\n\n // Get or create user for this profile. SmrtCollection.create() persists, so\n // pass lastLoginAt during creation to avoid an extra first-login write.\n const existingUser = await this.findByProfile(profile.id as string);\n const user =\n existingUser ??\n (await this.create({\n email: claims.email,\n ...(shouldRecordLogin ? { lastLoginAt: new Date() } : {}),\n profileId: profile.id as string,\n status: UserStatus.ACTIVE,\n }));\n\n if (existingUser && shouldRecordLogin) {\n existingUser.recordLogin();\n await existingUser.save();\n }\n\n return {\n user,\n profile,\n oidcIdentity,\n created,\n };\n }\n}\n","export const encoder = new TextEncoder();\nexport const decoder = new TextDecoder();\nconst MAX_INT32 = 2 ** 32;\nexport function concat(...buffers) {\n const size = buffers.reduce((acc, { length }) => acc + length, 0);\n const buf = new Uint8Array(size);\n let i = 0;\n for (const buffer of buffers) {\n buf.set(buffer, i);\n i += buffer.length;\n }\n return buf;\n}\nfunction writeUInt32BE(buf, value, offset) {\n if (value < 0 || value >= MAX_INT32) {\n throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);\n }\n buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset);\n}\nexport function uint64be(value) {\n const high = Math.floor(value / MAX_INT32);\n const low = value % MAX_INT32;\n const buf = new Uint8Array(8);\n writeUInt32BE(buf, high, 0);\n writeUInt32BE(buf, low, 4);\n return buf;\n}\nexport function uint32be(value) {\n const buf = new Uint8Array(4);\n writeUInt32BE(buf, value);\n return buf;\n}\nexport function encode(string) {\n const bytes = new Uint8Array(string.length);\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code > 127) {\n throw new TypeError('non-ASCII string encountered in encode()');\n }\n bytes[i] = code;\n }\n return bytes;\n}\n","export function encodeBase64(input) {\n if (Uint8Array.prototype.toBase64) {\n return input.toBase64();\n }\n const CHUNK_SIZE = 0x8000;\n const arr = [];\n for (let i = 0; i < input.length; i += CHUNK_SIZE) {\n arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(arr.join(''));\n}\nexport function decodeBase64(encoded) {\n if (Uint8Array.fromBase64) {\n return Uint8Array.fromBase64(encoded);\n }\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n","import { encoder, decoder } from '../lib/buffer_utils.js';\nimport { encodeBase64, decodeBase64 } from '../lib/base64.js';\nexport function decode(input) {\n if (Uint8Array.fromBase64) {\n return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {\n alphabet: 'base64url',\n });\n }\n let encoded = input;\n if (encoded instanceof Uint8Array) {\n encoded = decoder.decode(encoded);\n }\n encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');\n try {\n return decodeBase64(encoded);\n }\n catch {\n throw new TypeError('The input to be decoded is not correctly encoded.');\n }\n}\nexport function encode(input) {\n let unencoded = input;\n if (typeof unencoded === 'string') {\n unencoded = encoder.encode(unencoded);\n }\n if (Uint8Array.prototype.toBase64) {\n return unencoded.toBase64({ alphabet: 'base64url', omitPadding: true });\n }\n return encodeBase64(unencoded).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n","export class JOSEError extends Error {\n static code = 'ERR_JOSE_GENERIC';\n code = 'ERR_JOSE_GENERIC';\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class JWTClaimValidationFailed extends JOSEError {\n static code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JWTExpired extends JOSEError {\n static code = 'ERR_JWT_EXPIRED';\n code = 'ERR_JWT_EXPIRED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JOSEAlgNotAllowed extends JOSEError {\n static code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n}\nexport class JOSENotSupported extends JOSEError {\n static code = 'ERR_JOSE_NOT_SUPPORTED';\n code = 'ERR_JOSE_NOT_SUPPORTED';\n}\nexport class JWEDecryptionFailed extends JOSEError {\n static code = 'ERR_JWE_DECRYPTION_FAILED';\n code = 'ERR_JWE_DECRYPTION_FAILED';\n constructor(message = 'decryption operation failed', options) {\n super(message, options);\n }\n}\nexport class JWEInvalid extends JOSEError {\n static code = 'ERR_JWE_INVALID';\n code = 'ERR_JWE_INVALID';\n}\nexport class JWSInvalid extends JOSEError {\n static code = 'ERR_JWS_INVALID';\n code = 'ERR_JWS_INVALID';\n}\nexport class JWTInvalid extends JOSEError {\n static code = 'ERR_JWT_INVALID';\n code = 'ERR_JWT_INVALID';\n}\nexport class JWKInvalid extends JOSEError {\n static code = 'ERR_JWK_INVALID';\n code = 'ERR_JWK_INVALID';\n}\nexport class JWKSInvalid extends JOSEError {\n static code = 'ERR_JWKS_INVALID';\n code = 'ERR_JWKS_INVALID';\n}\nexport class JWKSNoMatchingKey extends JOSEError {\n static code = 'ERR_JWKS_NO_MATCHING_KEY';\n code = 'ERR_JWKS_NO_MATCHING_KEY';\n constructor(message = 'no applicable key found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSMultipleMatchingKeys extends JOSEError {\n [Symbol.asyncIterator];\n static code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n constructor(message = 'multiple matching keys found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSTimeout extends JOSEError {\n static code = 'ERR_JWKS_TIMEOUT';\n code = 'ERR_JWKS_TIMEOUT';\n constructor(message = 'request timed out', options) {\n super(message, options);\n }\n}\nexport class JWSSignatureVerificationFailed extends JOSEError {\n static code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n constructor(message = 'signature verification failed', options) {\n super(message, options);\n }\n}\n","const unusable = (name, prop = 'algorithm.name') => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);\nconst isAlgorithm = (algorithm, name) => algorithm.name === name;\nfunction getHashLength(hash) {\n return parseInt(hash.name.slice(4), 10);\n}\nfunction getNamedCurve(alg) {\n switch (alg) {\n case 'ES256':\n return 'P-256';\n case 'ES384':\n return 'P-384';\n case 'ES512':\n return 'P-521';\n default:\n throw new Error('unreachable');\n }\n}\nfunction checkUsage(key, usage) {\n if (usage && !key.usages.includes(usage)) {\n throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);\n }\n}\nexport function checkSigCryptoKey(key, alg, usage) {\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512': {\n if (!isAlgorithm(key.algorithm, 'HMAC'))\n throw unusable('HMAC');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'RS256':\n case 'RS384':\n case 'RS512': {\n if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))\n throw unusable('RSASSA-PKCS1-v1_5');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'PS256':\n case 'PS384':\n case 'PS512': {\n if (!isAlgorithm(key.algorithm, 'RSA-PSS'))\n throw unusable('RSA-PSS');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'Ed25519':\n case 'EdDSA': {\n if (!isAlgorithm(key.algorithm, 'Ed25519'))\n throw unusable('Ed25519');\n break;\n }\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87': {\n if (!isAlgorithm(key.algorithm, alg))\n throw unusable(alg);\n break;\n }\n case 'ES256':\n case 'ES384':\n case 'ES512': {\n if (!isAlgorithm(key.algorithm, 'ECDSA'))\n throw unusable('ECDSA');\n const expected = getNamedCurve(alg);\n const actual = key.algorithm.namedCurve;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.namedCurve');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usage);\n}\nexport function checkEncCryptoKey(key, alg, usage) {\n switch (alg) {\n case 'A128GCM':\n case 'A192GCM':\n case 'A256GCM': {\n if (!isAlgorithm(key.algorithm, 'AES-GCM'))\n throw unusable('AES-GCM');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'A128KW':\n case 'A192KW':\n case 'A256KW': {\n if (!isAlgorithm(key.algorithm, 'AES-KW'))\n throw unusable('AES-KW');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'ECDH': {\n switch (key.algorithm.name) {\n case 'ECDH':\n case 'X25519':\n break;\n default:\n throw unusable('ECDH or X25519');\n }\n break;\n }\n case 'PBES2-HS256+A128KW':\n case 'PBES2-HS384+A192KW':\n case 'PBES2-HS512+A256KW':\n if (!isAlgorithm(key.algorithm, 'PBKDF2'))\n throw unusable('PBKDF2');\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512': {\n if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))\n throw unusable('RSA-OAEP');\n const expected = parseInt(alg.slice(9), 10) || 1;\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usage);\n}\n","function message(msg, actual, ...types) {\n types = types.filter(Boolean);\n if (types.length > 2) {\n const last = types.pop();\n msg += `one of type ${types.join(', ')}, or ${last}.`;\n }\n else if (types.length === 2) {\n msg += `one of type ${types[0]} or ${types[1]}.`;\n }\n else {\n msg += `of type ${types[0]}.`;\n }\n if (actual == null) {\n msg += ` Received ${actual}`;\n }\n else if (typeof actual === 'function' && actual.name) {\n msg += ` Received function ${actual.name}`;\n }\n else if (typeof actual === 'object' && actual != null) {\n if (actual.constructor?.name) {\n msg += ` Received an instance of ${actual.constructor.name}`;\n }\n }\n return msg;\n}\nexport const invalidKeyInput = (actual, ...types) => message('Key must be ', actual, ...types);\nexport const withAlg = (alg, actual, ...types) => message(`Key for the ${alg} algorithm must be `, actual, ...types);\n","export function assertCryptoKey(key) {\n if (!isCryptoKey(key)) {\n throw new Error('CryptoKey instance expected');\n }\n}\nexport const isCryptoKey = (key) => {\n if (key?.[Symbol.toStringTag] === 'CryptoKey')\n return true;\n try {\n return key instanceof CryptoKey;\n }\n catch {\n return false;\n }\n};\nexport const isKeyObject = (key) => key?.[Symbol.toStringTag] === 'KeyObject';\nexport const isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);\n","export function isDisjoint(...headers) {\n const sources = headers.filter(Boolean);\n if (sources.length === 0 || sources.length === 1) {\n return true;\n }\n let acc;\n for (const header of sources) {\n const parameters = Object.keys(header);\n if (!acc || acc.size === 0) {\n acc = new Set(parameters);\n continue;\n }\n for (const parameter of parameters) {\n if (acc.has(parameter)) {\n return false;\n }\n acc.add(parameter);\n }\n }\n return true;\n}\n","const isObjectLike = (value) => typeof value === 'object' && value !== null;\nexport function isObject(input) {\n if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {\n return false;\n }\n if (Object.getPrototypeOf(input) === null) {\n return true;\n }\n let proto = input;\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n return Object.getPrototypeOf(input) === proto;\n}\n","export function checkKeyLength(alg, key) {\n if (alg.startsWith('RS') || alg.startsWith('PS')) {\n const { modulusLength } = key.algorithm;\n if (typeof modulusLength !== 'number' || modulusLength < 2048) {\n throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);\n }\n }\n}\n","import { JOSENotSupported } from '../util/errors.js';\nfunction subtleMapping(jwk) {\n let algorithm;\n let keyUsages;\n switch (jwk.kty) {\n case 'AKP': {\n switch (jwk.alg) {\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n algorithm = { name: jwk.alg };\n keyUsages = jwk.priv ? ['sign'] : ['verify'];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'RSA': {\n switch (jwk.alg) {\n case 'PS256':\n case 'PS384':\n case 'PS512':\n algorithm = { name: 'RSA-PSS', hash: `SHA-${jwk.alg.slice(-3)}` };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'RS256':\n case 'RS384':\n case 'RS512':\n algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${jwk.alg.slice(-3)}` };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512':\n algorithm = {\n name: 'RSA-OAEP',\n hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`,\n };\n keyUsages = jwk.d ? ['decrypt', 'unwrapKey'] : ['encrypt', 'wrapKey'];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'EC': {\n switch (jwk.alg) {\n case 'ES256':\n algorithm = { name: 'ECDSA', namedCurve: 'P-256' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ES384':\n algorithm = { name: 'ECDSA', namedCurve: 'P-384' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ES512':\n algorithm = { name: 'ECDSA', namedCurve: 'P-521' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n algorithm = { name: 'ECDH', namedCurve: jwk.crv };\n keyUsages = jwk.d ? ['deriveBits'] : [];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n case 'OKP': {\n switch (jwk.alg) {\n case 'Ed25519':\n case 'EdDSA':\n algorithm = { name: 'Ed25519' };\n keyUsages = jwk.d ? ['sign'] : ['verify'];\n break;\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n algorithm = { name: jwk.crv };\n keyUsages = jwk.d ? ['deriveBits'] : [];\n break;\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value');\n }\n break;\n }\n default:\n throw new JOSENotSupported('Invalid or unsupported JWK \"kty\" (Key Type) Parameter value');\n }\n return { algorithm, keyUsages };\n}\nexport async function jwkToKey(jwk) {\n if (!jwk.alg) {\n throw new TypeError('\"alg\" argument is required when \"jwk.alg\" is not present');\n }\n const { algorithm, keyUsages } = subtleMapping(jwk);\n const keyData = { ...jwk };\n if (keyData.kty !== 'AKP') {\n delete keyData.alg;\n }\n delete keyData.use;\n return crypto.subtle.importKey('jwk', keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);\n}\n","import { decode as decodeBase64URL } from '../util/base64url.js';\nimport { fromSPKI, fromPKCS8, fromX509 } from '../lib/asn1.js';\nimport { jwkToKey } from '../lib/jwk_to_key.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport { isObject } from '../lib/is_object.js';\nexport async function importSPKI(spki, alg, options) {\n if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {\n throw new TypeError('\"spki\" must be SPKI formatted string');\n }\n return fromSPKI(spki, alg, options);\n}\nexport async function importX509(x509, alg, options) {\n if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {\n throw new TypeError('\"x509\" must be X.509 formatted string');\n }\n return fromX509(x509, alg, options);\n}\nexport async function importPKCS8(pkcs8, alg, options) {\n if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {\n throw new TypeError('\"pkcs8\" must be PKCS#8 formatted string');\n }\n return fromPKCS8(pkcs8, alg, options);\n}\nexport async function importJWK(jwk, alg, options) {\n if (!isObject(jwk)) {\n throw new TypeError('JWK must be an object');\n }\n let ext;\n alg ??= jwk.alg;\n ext ??= options?.extractable ?? jwk.ext;\n switch (jwk.kty) {\n case 'oct':\n if (typeof jwk.k !== 'string' || !jwk.k) {\n throw new TypeError('missing \"k\" (Key Value) Parameter value');\n }\n return decodeBase64URL(jwk.k);\n case 'RSA':\n if ('oth' in jwk && jwk.oth !== undefined) {\n throw new JOSENotSupported('RSA JWK \"oth\" (Other Primes Info) Parameter value is not supported');\n }\n return jwkToKey({ ...jwk, alg, ext });\n case 'AKP': {\n if (typeof jwk.alg !== 'string' || !jwk.alg) {\n throw new TypeError('missing \"alg\" (Algorithm) Parameter value');\n }\n if (alg !== undefined && alg !== jwk.alg) {\n throw new TypeError('JWK alg and alg option value mismatch');\n }\n return jwkToKey({ ...jwk, ext });\n }\n case 'EC':\n case 'OKP':\n return jwkToKey({ ...jwk, alg, ext });\n default:\n throw new JOSENotSupported('Unsupported \"kty\" (Key Type) Parameter value');\n }\n}\n","import { JOSENotSupported, JWEInvalid, JWSInvalid } from '../util/errors.js';\nexport function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {\n if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be integrity protected');\n }\n if (!protectedHeader || protectedHeader.crit === undefined) {\n return new Set();\n }\n if (!Array.isArray(protectedHeader.crit) ||\n protectedHeader.crit.length === 0 ||\n protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');\n }\n let recognized;\n if (recognizedOption !== undefined) {\n recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);\n }\n else {\n recognized = recognizedDefault;\n }\n for (const parameter of protectedHeader.crit) {\n if (!recognized.has(parameter)) {\n throw new JOSENotSupported(`Extension Header Parameter \"${parameter}\" is not recognized`);\n }\n if (joseHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" is missing`);\n }\n if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" MUST be integrity protected`);\n }\n }\n return new Set(protectedHeader.crit);\n}\n","export function validateAlgorithms(option, algorithms) {\n if (algorithms !== undefined &&\n (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {\n throw new TypeError(`\"${option}\" option must be an array of strings`);\n }\n if (!algorithms) {\n return undefined;\n }\n return new Set(algorithms);\n}\n","import { isObject } from './is_object.js';\nexport const isJWK = (key) => isObject(key) && typeof key.kty === 'string';\nexport const isPrivateJWK = (key) => key.kty !== 'oct' &&\n ((key.kty === 'AKP' && typeof key.priv === 'string') || typeof key.d === 'string');\nexport const isPublicJWK = (key) => key.kty !== 'oct' && key.d === undefined && key.priv === undefined;\nexport const isSecretJWK = (key) => key.kty === 'oct' && typeof key.k === 'string';\n","import { isJWK } from './is_jwk.js';\nimport { decode } from '../util/base64url.js';\nimport { jwkToKey } from './jwk_to_key.js';\nimport { isCryptoKey, isKeyObject } from './is_key_like.js';\nlet cache;\nconst handleJWK = async (key, jwk, alg, freeze = false) => {\n cache ||= new WeakMap();\n let cached = cache.get(key);\n if (cached?.[alg]) {\n return cached[alg];\n }\n const cryptoKey = await jwkToKey({ ...jwk, alg });\n if (freeze)\n Object.freeze(key);\n if (!cached) {\n cache.set(key, { [alg]: cryptoKey });\n }\n else {\n cached[alg] = cryptoKey;\n }\n return cryptoKey;\n};\nconst handleKeyObject = (keyObject, alg) => {\n cache ||= new WeakMap();\n let cached = cache.get(keyObject);\n if (cached?.[alg]) {\n return cached[alg];\n }\n const isPublic = keyObject.type === 'public';\n const extractable = isPublic ? true : false;\n let cryptoKey;\n if (keyObject.asymmetricKeyType === 'x25519') {\n switch (alg) {\n case 'ECDH-ES':\n case 'ECDH-ES+A128KW':\n case 'ECDH-ES+A192KW':\n case 'ECDH-ES+A256KW':\n break;\n default:\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ['deriveBits']);\n }\n if (keyObject.asymmetricKeyType === 'ed25519') {\n if (alg !== 'EdDSA' && alg !== 'Ed25519') {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [\n isPublic ? 'verify' : 'sign',\n ]);\n }\n switch (keyObject.asymmetricKeyType) {\n case 'ml-dsa-44':\n case 'ml-dsa-65':\n case 'ml-dsa-87': {\n if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [\n isPublic ? 'verify' : 'sign',\n ]);\n }\n }\n if (keyObject.asymmetricKeyType === 'rsa') {\n let hash;\n switch (alg) {\n case 'RSA-OAEP':\n hash = 'SHA-1';\n break;\n case 'RS256':\n case 'PS256':\n case 'RSA-OAEP-256':\n hash = 'SHA-256';\n break;\n case 'RS384':\n case 'PS384':\n case 'RSA-OAEP-384':\n hash = 'SHA-384';\n break;\n case 'RS512':\n case 'PS512':\n case 'RSA-OAEP-512':\n hash = 'SHA-512';\n break;\n default:\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (alg.startsWith('RSA-OAEP')) {\n return keyObject.toCryptoKey({\n name: 'RSA-OAEP',\n hash,\n }, extractable, isPublic ? ['encrypt'] : ['decrypt']);\n }\n cryptoKey = keyObject.toCryptoKey({\n name: alg.startsWith('PS') ? 'RSA-PSS' : 'RSASSA-PKCS1-v1_5',\n hash,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (keyObject.asymmetricKeyType === 'ec') {\n const nist = new Map([\n ['prime256v1', 'P-256'],\n ['secp384r1', 'P-384'],\n ['secp521r1', 'P-521'],\n ]);\n const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);\n if (!namedCurve) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (alg === 'ES256' && namedCurve === 'P-256') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg === 'ES384' && namedCurve === 'P-384') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg === 'ES512' && namedCurve === 'P-521') {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDSA',\n namedCurve,\n }, extractable, [isPublic ? 'verify' : 'sign']);\n }\n if (alg.startsWith('ECDH-ES')) {\n cryptoKey = keyObject.toCryptoKey({\n name: 'ECDH',\n namedCurve,\n }, extractable, isPublic ? [] : ['deriveBits']);\n }\n }\n if (!cryptoKey) {\n throw new TypeError('given KeyObject instance cannot be used for this algorithm');\n }\n if (!cached) {\n cache.set(keyObject, { [alg]: cryptoKey });\n }\n else {\n cached[alg] = cryptoKey;\n }\n return cryptoKey;\n};\nexport async function normalizeKey(key, alg) {\n if (key instanceof Uint8Array) {\n return key;\n }\n if (isCryptoKey(key)) {\n return key;\n }\n if (isKeyObject(key)) {\n if (key.type === 'secret') {\n return key.export();\n }\n if ('toCryptoKey' in key && typeof key.toCryptoKey === 'function') {\n try {\n return handleKeyObject(key, alg);\n }\n catch (err) {\n if (err instanceof TypeError) {\n throw err;\n }\n }\n }\n let jwk = key.export({ format: 'jwk' });\n return handleJWK(key, jwk, alg);\n }\n if (isJWK(key)) {\n if (key.k) {\n return decode(key.k);\n }\n return handleJWK(key, key, alg, true);\n }\n throw new Error('unreachable');\n}\n","import { withAlg as invalidKeyInput } from './invalid_key_input.js';\nimport { isKeyLike } from './is_key_like.js';\nimport * as jwk from './is_jwk.js';\nconst tag = (key) => key?.[Symbol.toStringTag];\nconst jwkMatchesOp = (alg, key, usage) => {\n if (key.use !== undefined) {\n let expected;\n switch (usage) {\n case 'sign':\n case 'verify':\n expected = 'sig';\n break;\n case 'encrypt':\n case 'decrypt':\n expected = 'enc';\n break;\n }\n if (key.use !== expected) {\n throw new TypeError(`Invalid key for this operation, its \"use\" must be \"${expected}\" when present`);\n }\n }\n if (key.alg !== undefined && key.alg !== alg) {\n throw new TypeError(`Invalid key for this operation, its \"alg\" must be \"${alg}\" when present`);\n }\n if (Array.isArray(key.key_ops)) {\n let expectedKeyOp;\n switch (true) {\n case usage === 'sign' || usage === 'verify':\n case alg === 'dir':\n case alg.includes('CBC-HS'):\n expectedKeyOp = usage;\n break;\n case alg.startsWith('PBES2'):\n expectedKeyOp = 'deriveBits';\n break;\n case /^A\\d{3}(?:GCM)?(?:KW)?$/.test(alg):\n if (!alg.includes('GCM') && alg.endsWith('KW')) {\n expectedKeyOp = usage === 'encrypt' ? 'wrapKey' : 'unwrapKey';\n }\n else {\n expectedKeyOp = usage;\n }\n break;\n case usage === 'encrypt' && alg.startsWith('RSA'):\n expectedKeyOp = 'wrapKey';\n break;\n case usage === 'decrypt':\n expectedKeyOp = alg.startsWith('RSA') ? 'unwrapKey' : 'deriveBits';\n break;\n }\n if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {\n throw new TypeError(`Invalid key for this operation, its \"key_ops\" must include \"${expectedKeyOp}\" when present`);\n }\n }\n return true;\n};\nconst symmetricTypeCheck = (alg, key, usage) => {\n if (key instanceof Uint8Array)\n return;\n if (jwk.isJWK(key)) {\n if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present`);\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key', 'Uint8Array'));\n }\n if (key.type !== 'secret') {\n throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type \"secret\"`);\n }\n};\nconst asymmetricTypeCheck = (alg, key, usage) => {\n if (jwk.isJWK(key)) {\n switch (usage) {\n case 'decrypt':\n case 'sign':\n if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation must be a private JWK`);\n case 'encrypt':\n case 'verify':\n if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation must be a public JWK`);\n }\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));\n }\n if (key.type === 'secret') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type \"secret\"`);\n }\n if (key.type === 'public') {\n switch (usage) {\n case 'sign':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type \"private\"`);\n case 'decrypt':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type \"private\"`);\n }\n }\n if (key.type === 'private') {\n switch (usage) {\n case 'verify':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type \"public\"`);\n case 'encrypt':\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type \"public\"`);\n }\n }\n};\nexport function checkKeyType(alg, key, usage) {\n switch (alg.substring(0, 2)) {\n case 'A1':\n case 'A2':\n case 'di':\n case 'HS':\n case 'PB':\n symmetricTypeCheck(alg, key, usage);\n break;\n default:\n asymmetricTypeCheck(alg, key, usage);\n }\n}\n","import { JOSENotSupported } from '../util/errors.js';\nexport function subtleAlgorithm(alg, algorithm) {\n const hash = `SHA-${alg.slice(-3)}`;\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512':\n return { hash, name: 'HMAC' };\n case 'PS256':\n case 'PS384':\n case 'PS512':\n return { hash, name: 'RSA-PSS', saltLength: parseInt(alg.slice(-3), 10) >> 3 };\n case 'RS256':\n case 'RS384':\n case 'RS512':\n return { hash, name: 'RSASSA-PKCS1-v1_5' };\n case 'ES256':\n case 'ES384':\n case 'ES512':\n return { hash, name: 'ECDSA', namedCurve: algorithm.namedCurve };\n case 'Ed25519':\n case 'EdDSA':\n return { name: 'Ed25519' };\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return { name: alg };\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n","import { checkSigCryptoKey } from './crypto_key.js';\nimport { invalidKeyInput } from './invalid_key_input.js';\nexport async function getSigKey(alg, key, usage) {\n if (key instanceof Uint8Array) {\n if (!alg.startsWith('HS')) {\n throw new TypeError(invalidKeyInput(key, 'CryptoKey', 'KeyObject', 'JSON Web Key'));\n }\n return crypto.subtle.importKey('raw', key, { hash: `SHA-${alg.slice(-3)}`, name: 'HMAC' }, false, [usage]);\n }\n checkSigCryptoKey(key, alg, usage);\n return key;\n}\n","import { subtleAlgorithm } from './subtle_dsa.js';\nimport { checkKeyLength } from './check_key_length.js';\nimport { getSigKey } from './get_sign_verify_key.js';\nexport async function verify(alg, key, signature, data) {\n const cryptoKey = await getSigKey(alg, key, 'verify');\n checkKeyLength(alg, cryptoKey);\n const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);\n try {\n return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);\n }\n catch {\n return false;\n }\n}\n","import { decode as b64u } from '../../util/base64url.js';\nimport { verify } from '../../lib/verify.js';\nimport { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';\nimport { concat, encoder, decoder, encode } from '../../lib/buffer_utils.js';\nimport { isDisjoint } from '../../lib/is_disjoint.js';\nimport { isObject } from '../../lib/is_object.js';\nimport { checkKeyType } from '../../lib/check_key_type.js';\nimport { validateCrit } from '../../lib/validate_crit.js';\nimport { validateAlgorithms } from '../../lib/validate_algorithms.js';\nimport { normalizeKey } from '../../lib/normalize_key.js';\nexport async function flattenedVerify(jws, key, options) {\n if (!isObject(jws)) {\n throw new JWSInvalid('Flattened JWS must be an object');\n }\n if (jws.protected === undefined && jws.header === undefined) {\n throw new JWSInvalid('Flattened JWS must have either of the \"protected\" or \"header\" members');\n }\n if (jws.protected !== undefined && typeof jws.protected !== 'string') {\n throw new JWSInvalid('JWS Protected Header incorrect type');\n }\n if (jws.payload === undefined) {\n throw new JWSInvalid('JWS Payload missing');\n }\n if (typeof jws.signature !== 'string') {\n throw new JWSInvalid('JWS Signature missing or incorrect type');\n }\n if (jws.header !== undefined && !isObject(jws.header)) {\n throw new JWSInvalid('JWS Unprotected Header incorrect type');\n }\n let parsedProt = {};\n if (jws.protected) {\n try {\n const protectedHeader = b64u(jws.protected);\n parsedProt = JSON.parse(decoder.decode(protectedHeader));\n }\n catch {\n throw new JWSInvalid('JWS Protected Header is invalid');\n }\n }\n if (!isDisjoint(parsedProt, jws.header)) {\n throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');\n }\n const joseHeader = {\n ...parsedProt,\n ...jws.header,\n };\n const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, parsedProt, joseHeader);\n let b64 = true;\n if (extensions.has('b64')) {\n b64 = parsedProt.b64;\n if (typeof b64 !== 'boolean') {\n throw new JWSInvalid('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');\n }\n }\n const { alg } = joseHeader;\n if (typeof alg !== 'string' || !alg) {\n throw new JWSInvalid('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');\n }\n const algorithms = options && validateAlgorithms('algorithms', options.algorithms);\n if (algorithms && !algorithms.has(alg)) {\n throw new JOSEAlgNotAllowed('\"alg\" (Algorithm) Header Parameter value not allowed');\n }\n if (b64) {\n if (typeof jws.payload !== 'string') {\n throw new JWSInvalid('JWS Payload must be a string');\n }\n }\n else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {\n throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');\n }\n let resolvedKey = false;\n if (typeof key === 'function') {\n key = await key(parsedProt, jws);\n resolvedKey = true;\n }\n checkKeyType(alg, key, 'verify');\n const data = concat(jws.protected !== undefined ? encode(jws.protected) : new Uint8Array(), encode('.'), typeof jws.payload === 'string'\n ? b64\n ? encode(jws.payload)\n : encoder.encode(jws.payload)\n : jws.payload);\n let signature;\n try {\n signature = b64u(jws.signature);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the signature');\n }\n const k = await normalizeKey(key, alg);\n const verified = await verify(alg, k, signature, data);\n if (!verified) {\n throw new JWSSignatureVerificationFailed();\n }\n let payload;\n if (b64) {\n try {\n payload = b64u(jws.payload);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the payload');\n }\n }\n else if (typeof jws.payload === 'string') {\n payload = encoder.encode(jws.payload);\n }\n else {\n payload = jws.payload;\n }\n const result = { payload };\n if (jws.protected !== undefined) {\n result.protectedHeader = parsedProt;\n }\n if (jws.header !== undefined) {\n result.unprotectedHeader = jws.header;\n }\n if (resolvedKey) {\n return { ...result, key: k };\n }\n return result;\n}\n","import { flattenedVerify } from '../flattened/verify.js';\nimport { JWSInvalid } from '../../util/errors.js';\nimport { decoder } from '../../lib/buffer_utils.js';\nexport async function compactVerify(jws, key, options) {\n if (jws instanceof Uint8Array) {\n jws = decoder.decode(jws);\n }\n if (typeof jws !== 'string') {\n throw new JWSInvalid('Compact JWS must be a string or Uint8Array');\n }\n const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');\n if (length !== 3) {\n throw new JWSInvalid('Invalid Compact JWS');\n }\n const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);\n const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n","import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';\nimport { encoder, decoder } from './buffer_utils.js';\nimport { isObject } from './is_object.js';\nconst epoch = (date) => Math.floor(date.getTime() / 1000);\nconst minute = 60;\nconst hour = minute * 60;\nconst day = hour * 24;\nconst week = day * 7;\nconst year = day * 365.25;\nconst REGEX = /^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;\nexport function secs(str) {\n const matched = REGEX.exec(str);\n if (!matched || (matched[4] && matched[1])) {\n throw new TypeError('Invalid time period format');\n }\n const value = parseFloat(matched[2]);\n const unit = matched[3].toLowerCase();\n let numericDate;\n switch (unit) {\n case 'sec':\n case 'secs':\n case 'second':\n case 'seconds':\n case 's':\n numericDate = Math.round(value);\n break;\n case 'minute':\n case 'minutes':\n case 'min':\n case 'mins':\n case 'm':\n numericDate = Math.round(value * minute);\n break;\n case 'hour':\n case 'hours':\n case 'hr':\n case 'hrs':\n case 'h':\n numericDate = Math.round(value * hour);\n break;\n case 'day':\n case 'days':\n case 'd':\n numericDate = Math.round(value * day);\n break;\n case 'week':\n case 'weeks':\n case 'w':\n numericDate = Math.round(value * week);\n break;\n default:\n numericDate = Math.round(value * year);\n break;\n }\n if (matched[1] === '-' || matched[4] === 'ago') {\n return -numericDate;\n }\n return numericDate;\n}\nfunction validateInput(label, input) {\n if (!Number.isFinite(input)) {\n throw new TypeError(`Invalid ${label} input`);\n }\n return input;\n}\nconst normalizeTyp = (value) => {\n if (value.includes('/')) {\n return value.toLowerCase();\n }\n return `application/${value.toLowerCase()}`;\n};\nconst checkAudiencePresence = (audPayload, audOption) => {\n if (typeof audPayload === 'string') {\n return audOption.includes(audPayload);\n }\n if (Array.isArray(audPayload)) {\n return audOption.some(Set.prototype.has.bind(new Set(audPayload)));\n }\n return false;\n};\nexport function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {\n let payload;\n try {\n payload = JSON.parse(decoder.decode(encodedPayload));\n }\n catch {\n }\n if (!isObject(payload)) {\n throw new JWTInvalid('JWT Claims Set must be a top-level JSON object');\n }\n const { typ } = options;\n if (typ &&\n (typeof protectedHeader.typ !== 'string' ||\n normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {\n throw new JWTClaimValidationFailed('unexpected \"typ\" JWT header value', payload, 'typ', 'check_failed');\n }\n const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;\n const presenceCheck = [...requiredClaims];\n if (maxTokenAge !== undefined)\n presenceCheck.push('iat');\n if (audience !== undefined)\n presenceCheck.push('aud');\n if (subject !== undefined)\n presenceCheck.push('sub');\n if (issuer !== undefined)\n presenceCheck.push('iss');\n for (const claim of new Set(presenceCheck.reverse())) {\n if (!(claim in payload)) {\n throw new JWTClaimValidationFailed(`missing required \"${claim}\" claim`, payload, claim, 'missing');\n }\n }\n if (issuer &&\n !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {\n throw new JWTClaimValidationFailed('unexpected \"iss\" claim value', payload, 'iss', 'check_failed');\n }\n if (subject && payload.sub !== subject) {\n throw new JWTClaimValidationFailed('unexpected \"sub\" claim value', payload, 'sub', 'check_failed');\n }\n if (audience &&\n !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {\n throw new JWTClaimValidationFailed('unexpected \"aud\" claim value', payload, 'aud', 'check_failed');\n }\n let tolerance;\n switch (typeof options.clockTolerance) {\n case 'string':\n tolerance = secs(options.clockTolerance);\n break;\n case 'number':\n tolerance = options.clockTolerance;\n break;\n case 'undefined':\n tolerance = 0;\n break;\n default:\n throw new TypeError('Invalid clockTolerance option type');\n }\n const { currentDate } = options;\n const now = epoch(currentDate || new Date());\n if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {\n throw new JWTClaimValidationFailed('\"iat\" claim must be a number', payload, 'iat', 'invalid');\n }\n if (payload.nbf !== undefined) {\n if (typeof payload.nbf !== 'number') {\n throw new JWTClaimValidationFailed('\"nbf\" claim must be a number', payload, 'nbf', 'invalid');\n }\n if (payload.nbf > now + tolerance) {\n throw new JWTClaimValidationFailed('\"nbf\" claim timestamp check failed', payload, 'nbf', 'check_failed');\n }\n }\n if (payload.exp !== undefined) {\n if (typeof payload.exp !== 'number') {\n throw new JWTClaimValidationFailed('\"exp\" claim must be a number', payload, 'exp', 'invalid');\n }\n if (payload.exp <= now - tolerance) {\n throw new JWTExpired('\"exp\" claim timestamp check failed', payload, 'exp', 'check_failed');\n }\n }\n if (maxTokenAge) {\n const age = now - payload.iat;\n const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);\n if (age - tolerance > max) {\n throw new JWTExpired('\"iat\" claim timestamp check failed (too far in the past)', payload, 'iat', 'check_failed');\n }\n if (age < 0 - tolerance) {\n throw new JWTClaimValidationFailed('\"iat\" claim timestamp check failed (it should be in the past)', payload, 'iat', 'check_failed');\n }\n }\n return payload;\n}\nexport class JWTClaimsBuilder {\n #payload;\n constructor(payload) {\n if (!isObject(payload)) {\n throw new TypeError('JWT Claims Set MUST be an object');\n }\n this.#payload = structuredClone(payload);\n }\n data() {\n return encoder.encode(JSON.stringify(this.#payload));\n }\n get iss() {\n return this.#payload.iss;\n }\n set iss(value) {\n this.#payload.iss = value;\n }\n get sub() {\n return this.#payload.sub;\n }\n set sub(value) {\n this.#payload.sub = value;\n }\n get aud() {\n return this.#payload.aud;\n }\n set aud(value) {\n this.#payload.aud = value;\n }\n set jti(value) {\n this.#payload.jti = value;\n }\n set nbf(value) {\n if (typeof value === 'number') {\n this.#payload.nbf = validateInput('setNotBefore', value);\n }\n else if (value instanceof Date) {\n this.#payload.nbf = validateInput('setNotBefore', epoch(value));\n }\n else {\n this.#payload.nbf = epoch(new Date()) + secs(value);\n }\n }\n set exp(value) {\n if (typeof value === 'number') {\n this.#payload.exp = validateInput('setExpirationTime', value);\n }\n else if (value instanceof Date) {\n this.#payload.exp = validateInput('setExpirationTime', epoch(value));\n }\n else {\n this.#payload.exp = epoch(new Date()) + secs(value);\n }\n }\n set iat(value) {\n if (value === undefined) {\n this.#payload.iat = epoch(new Date());\n }\n else if (value instanceof Date) {\n this.#payload.iat = validateInput('setIssuedAt', epoch(value));\n }\n else if (typeof value === 'string') {\n this.#payload.iat = validateInput('setIssuedAt', epoch(new Date()) + secs(value));\n }\n else {\n this.#payload.iat = validateInput('setIssuedAt', value);\n }\n }\n}\n","import { compactVerify } from '../jws/compact/verify.js';\nimport { validateClaimsSet } from '../lib/jwt_claims_set.js';\nimport { JWTInvalid } from '../util/errors.js';\nexport async function jwtVerify(jwt, key, options) {\n const verified = await compactVerify(jwt, key, options);\n if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {\n throw new JWTInvalid('JWTs MUST NOT use unencoded payload');\n }\n const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);\n const result = { payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n","import { importJWK } from '../key/import.js';\nimport { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';\nimport { isObject } from '../lib/is_object.js';\nfunction getKtyFromAlg(alg) {\n switch (typeof alg === 'string' && alg.slice(0, 2)) {\n case 'RS':\n case 'PS':\n return 'RSA';\n case 'ES':\n return 'EC';\n case 'Ed':\n return 'OKP';\n case 'ML':\n return 'AKP';\n default:\n throw new JOSENotSupported('Unsupported \"alg\" value for a JSON Web Key Set');\n }\n}\nfunction isJWKSLike(jwks) {\n return (jwks &&\n typeof jwks === 'object' &&\n Array.isArray(jwks.keys) &&\n jwks.keys.every(isJWKLike));\n}\nfunction isJWKLike(key) {\n return isObject(key);\n}\nclass LocalJWKSet {\n #jwks;\n #cached = new WeakMap();\n constructor(jwks) {\n if (!isJWKSLike(jwks)) {\n throw new JWKSInvalid('JSON Web Key Set malformed');\n }\n this.#jwks = structuredClone(jwks);\n }\n jwks() {\n return this.#jwks;\n }\n async getKey(protectedHeader, token) {\n const { alg, kid } = { ...protectedHeader, ...token?.header };\n const kty = getKtyFromAlg(alg);\n const candidates = this.#jwks.keys.filter((jwk) => {\n let candidate = kty === jwk.kty;\n if (candidate && typeof kid === 'string') {\n candidate = kid === jwk.kid;\n }\n if (candidate && (typeof jwk.alg === 'string' || kty === 'AKP')) {\n candidate = alg === jwk.alg;\n }\n if (candidate && typeof jwk.use === 'string') {\n candidate = jwk.use === 'sig';\n }\n if (candidate && Array.isArray(jwk.key_ops)) {\n candidate = jwk.key_ops.includes('verify');\n }\n if (candidate) {\n switch (alg) {\n case 'ES256':\n candidate = jwk.crv === 'P-256';\n break;\n case 'ES384':\n candidate = jwk.crv === 'P-384';\n break;\n case 'ES512':\n candidate = jwk.crv === 'P-521';\n break;\n case 'Ed25519':\n case 'EdDSA':\n candidate = jwk.crv === 'Ed25519';\n break;\n }\n }\n return candidate;\n });\n const { 0: jwk, length } = candidates;\n if (length === 0) {\n throw new JWKSNoMatchingKey();\n }\n if (length !== 1) {\n const error = new JWKSMultipleMatchingKeys();\n const _cached = this.#cached;\n error[Symbol.asyncIterator] = async function* () {\n for (const jwk of candidates) {\n try {\n yield await importWithAlgCache(_cached, jwk, alg);\n }\n catch { }\n }\n };\n throw error;\n }\n return importWithAlgCache(this.#cached, jwk, alg);\n }\n}\nasync function importWithAlgCache(cache, jwk, alg) {\n const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);\n if (cached[alg] === undefined) {\n const key = await importJWK({ ...jwk, ext: true }, alg);\n if (key instanceof Uint8Array || key.type !== 'public') {\n throw new JWKSInvalid('JSON Web Key Set members must be public keys');\n }\n cached[alg] = key;\n }\n return cached[alg];\n}\nexport function createLocalJWKSet(jwks) {\n const set = new LocalJWKSet(jwks);\n const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(localJWKSet, {\n jwks: {\n value: () => structuredClone(set.jwks()),\n enumerable: false,\n configurable: false,\n writable: false,\n },\n });\n return localJWKSet;\n}\n","import { JOSEError, JWKSNoMatchingKey, JWKSTimeout } from '../util/errors.js';\nimport { createLocalJWKSet } from './local.js';\nimport { isObject } from '../lib/is_object.js';\nfunction isCloudflareWorkers() {\n return (typeof WebSocketPair !== 'undefined' ||\n (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||\n (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel'));\n}\nlet USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'jose';\n const VERSION = 'v6.1.3';\n USER_AGENT = `${NAME}/${VERSION}`;\n}\nexport const customFetch = Symbol();\nasync function fetchJwks(url, headers, signal, fetchImpl = fetch) {\n const response = await fetchImpl(url, {\n method: 'GET',\n signal,\n redirect: 'manual',\n headers,\n }).catch((err) => {\n if (err.name === 'TimeoutError') {\n throw new JWKSTimeout();\n }\n throw err;\n });\n if (response.status !== 200) {\n throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');\n }\n try {\n return await response.json();\n }\n catch {\n throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON');\n }\n}\nexport const jwksCache = Symbol();\nfunction isFreshJwksCache(input, cacheMaxAge) {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n if (!('uat' in input) || typeof input.uat !== 'number' || Date.now() - input.uat >= cacheMaxAge) {\n return false;\n }\n if (!('jwks' in input) ||\n !isObject(input.jwks) ||\n !Array.isArray(input.jwks.keys) ||\n !Array.prototype.every.call(input.jwks.keys, isObject)) {\n return false;\n }\n return true;\n}\nclass RemoteJWKSet {\n #url;\n #timeoutDuration;\n #cooldownDuration;\n #cacheMaxAge;\n #jwksTimestamp;\n #pendingFetch;\n #headers;\n #customFetch;\n #local;\n #cache;\n constructor(url, options) {\n if (!(url instanceof URL)) {\n throw new TypeError('url must be an instance of URL');\n }\n this.#url = new URL(url.href);\n this.#timeoutDuration =\n typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000;\n this.#cooldownDuration =\n typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000;\n this.#cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000;\n this.#headers = new Headers(options?.headers);\n if (USER_AGENT && !this.#headers.has('User-Agent')) {\n this.#headers.set('User-Agent', USER_AGENT);\n }\n if (!this.#headers.has('accept')) {\n this.#headers.set('accept', 'application/json');\n this.#headers.append('accept', 'application/jwk-set+json');\n }\n this.#customFetch = options?.[customFetch];\n if (options?.[jwksCache] !== undefined) {\n this.#cache = options?.[jwksCache];\n if (isFreshJwksCache(options?.[jwksCache], this.#cacheMaxAge)) {\n this.#jwksTimestamp = this.#cache.uat;\n this.#local = createLocalJWKSet(this.#cache.jwks);\n }\n }\n }\n pendingFetch() {\n return !!this.#pendingFetch;\n }\n coolingDown() {\n return typeof this.#jwksTimestamp === 'number'\n ? Date.now() < this.#jwksTimestamp + this.#cooldownDuration\n : false;\n }\n fresh() {\n return typeof this.#jwksTimestamp === 'number'\n ? Date.now() < this.#jwksTimestamp + this.#cacheMaxAge\n : false;\n }\n jwks() {\n return this.#local?.jwks();\n }\n async getKey(protectedHeader, token) {\n if (!this.#local || !this.fresh()) {\n await this.reload();\n }\n try {\n return await this.#local(protectedHeader, token);\n }\n catch (err) {\n if (err instanceof JWKSNoMatchingKey) {\n if (this.coolingDown() === false) {\n await this.reload();\n return this.#local(protectedHeader, token);\n }\n }\n throw err;\n }\n }\n async reload() {\n if (this.#pendingFetch && isCloudflareWorkers()) {\n this.#pendingFetch = undefined;\n }\n this.#pendingFetch ||= fetchJwks(this.#url.href, this.#headers, AbortSignal.timeout(this.#timeoutDuration), this.#customFetch)\n .then((json) => {\n this.#local = createLocalJWKSet(json);\n if (this.#cache) {\n this.#cache.uat = Date.now();\n this.#cache.jwks = json;\n }\n this.#jwksTimestamp = Date.now();\n this.#pendingFetch = undefined;\n })\n .catch((err) => {\n this.#pendingFetch = undefined;\n throw err;\n });\n await this.#pendingFetch;\n }\n}\nexport function createRemoteJWKSet(url, options) {\n const set = new RemoteJWKSet(url, options);\n const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(remoteJWKSet, {\n coolingDown: {\n get: () => set.coolingDown(),\n enumerable: true,\n configurable: false,\n },\n fresh: {\n get: () => set.fresh(),\n enumerable: true,\n configurable: false,\n },\n reload: {\n value: () => set.reload(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n reloading: {\n get: () => set.pendingFetch(),\n enumerable: true,\n configurable: false,\n },\n jwks: {\n value: () => set.jwks(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n });\n return remoteJWKSet;\n}\n","/**\n * OidcLoginService - OAuth2/OIDC authorization-code login with PKCE.\n *\n * The service is provider-generic and works with standards-compliant IdPs such\n * as Kanidm, Dex, Keycloak, Authentik, Google, and others. It handles provider\n * discovery, authorization URL construction, token exchange, ID token\n * verification, and SMRT User/Profile creation.\n *\n * @packageDocumentation\n */\n\nimport { getPackageConfig } from '@happyvertical/smrt-config';\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport {\n createRemoteJWKSet,\n customFetch,\n type JWTPayload,\n type JWTVerifyGetKey,\n jwtVerify,\n} from 'jose';\nimport {\n type OidcClaims,\n type OidcIdentityResult,\n UserCollection,\n} from '../collections/UserCollection.js';\n\nconst DEFAULT_SCOPES = ['openid', 'profile', 'email'] as const;\nconst DEFAULT_CLOCK_TOLERANCE_SECONDS = 15;\nconst DEFAULT_METADATA_CACHE_TTL_MS = 5 * 60 * 1000;\nconst WELL_KNOWN_PATH = '/.well-known/openid-configuration';\n\nexport type OidcProviderKind = 'kanidm' | 'dex' | 'generic';\n\nexport type OidcTokenEndpointAuthMethod =\n | 'client_secret_basic'\n | 'client_secret_post'\n | 'none';\n\nexport interface OidcProviderConfig {\n /**\n * Optional preset label for documentation and UI.\n *\n * Kanidm and Dex are standards-compliant OIDC providers, so the preset does\n * not change protocol behavior; it lets apps name their intent clearly.\n */\n kind?: OidcProviderKind;\n /** OIDC issuer URL, e.g. https://id.example.com/dex */\n issuer: string;\n /** OAuth2/OIDC client ID registered with the provider */\n clientId: string;\n /** OAuth2/OIDC client secret for confidential clients */\n clientSecret?: string;\n /**\n * Redirect URI registered with the provider.\n *\n * SvelteKit helpers can derive this from the current request when omitted.\n */\n redirectUri?: string;\n /** Scopes to request. Defaults to openid profile email. */\n scopes?: string[];\n /** Override the discovery document URL when needed. */\n discoveryUrl?: string;\n /** Additional authorization request parameters. */\n authorizationParams?: Record<string, string | number | boolean | undefined>;\n /**\n * Client authentication method for the token endpoint.\n *\n * Defaults to client_secret_basic when clientSecret exists, otherwise none.\n */\n tokenEndpointAuthMethod?: OidcTokenEndpointAuthMethod;\n}\n\nexport interface OidcProviderResolutionOptions {\n defaultProvider?: string;\n providers?: Record<string, OidcProviderConfig>;\n}\n\nexport interface UsersOidcConfig extends OidcProviderResolutionOptions {\n /** Seconds before login transaction cookies expire. */\n transactionTtl?: number;\n}\n\nexport interface OidcProviderResolution {\n provider: OidcProviderConfig;\n providerName: string;\n}\n\nexport interface ResolvedOidcProviderConfig extends OidcProviderConfig {\n redirectUri: string;\n}\n\nexport interface OidcProviderMetadata {\n authorization_endpoint: string;\n end_session_endpoint?: string;\n issuer: string;\n jwks_uri: string;\n token_endpoint: string;\n userinfo_endpoint?: string;\n [key: string]: unknown;\n}\n\nexport interface OidcTransaction {\n codeVerifier: string;\n createdAt: number;\n nonce: string;\n provider: string;\n returnTo?: string;\n state: string;\n}\n\nexport interface CreateAuthorizationUrlOptions {\n authorizationParams?: Record<string, string | number | boolean | undefined>;\n transaction?: OidcTransaction;\n}\n\nexport interface OidcTokenSet {\n accessToken?: string;\n expiresAt?: Date;\n idToken: string;\n refreshToken?: string;\n scope?: string;\n tokenType?: string;\n}\n\nexport interface OidcCallbackResult {\n claims: OidcClaims;\n tokens: OidcTokenSet;\n}\n\nexport interface OidcLoginResult extends OidcIdentityResult {\n claims: OidcClaims;\n tokens: OidcTokenSet;\n}\n\nexport interface OidcLoginServiceOptions extends SmrtClassOptions {\n /** Provider key, e.g. kanidm or dex */\n providerName: string;\n /** Fully resolved provider config. redirectUri is required here. */\n provider: ResolvedOidcProviderConfig;\n /** Optional fetch override for tests or custom runtimes. */\n fetch?: typeof fetch;\n /** JWT clock tolerance passed to jose. Defaults to 15 seconds. */\n clockTolerance?: number | string;\n /** Provider metadata cache TTL in milliseconds. Defaults to 5 minutes. */\n metadataCacheTtlMs?: number;\n}\n\nexport class OidcLoginError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'OidcLoginError';\n }\n}\n\ninterface UsersAuthPackageConfig extends Record<string, unknown> {\n auth?: {\n oidc?: UsersOidcConfig;\n };\n}\n\ninterface TokenEndpointResponse {\n access_token?: unknown;\n error?: unknown;\n error_description?: unknown;\n expires_in?: unknown;\n id_token?: unknown;\n refresh_token?: unknown;\n scope?: unknown;\n token_type?: unknown;\n}\n\ntype OidcClaimSource = JWTPayload | Record<string, unknown>;\n\nexport function getUsersOidcConfig(): UsersOidcConfig {\n const config = getPackageConfig<UsersAuthPackageConfig>('users', {});\n return config.auth?.oidc ?? {};\n}\n\nfunction normalizeIssuer(issuer: string): string {\n return issuer.replace(/\\/+$/u, '');\n}\n\nfunction resolveDiscoveryUrl(provider: OidcProviderConfig): string {\n if (provider.discoveryUrl) return provider.discoveryUrl;\n return `${normalizeIssuer(provider.issuer)}${WELL_KNOWN_PATH}`;\n}\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n return btoa(binary)\n .replaceAll('+', '-')\n .replaceAll('/', '_')\n .replace(/=+$/u, '');\n}\n\nfunction base64UrlToBytes(value: string): Uint8Array {\n const normalized = value.replaceAll('-', '+').replaceAll('_', '/');\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n '=',\n );\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n\n return bytes;\n}\n\nfunction randomBase64Url(byteLength = 32): string {\n const bytes = new Uint8Array(byteLength);\n crypto.getRandomValues(bytes);\n return bytesToBase64Url(bytes);\n}\n\nasync function pkceChallenge(codeVerifier: string): Promise<string> {\n const bytes = new TextEncoder().encode(codeVerifier);\n const digest = await crypto.subtle.digest('SHA-256', bytes);\n return bytesToBase64Url(new Uint8Array(digest));\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n return btoa(binary);\n}\n\nfunction formUrlEncode(value: string): string {\n const params = new URLSearchParams();\n params.set('value', value);\n return params.toString().slice('value='.length);\n}\n\nfunction encodeBasicAuth(clientId: string, clientSecret: string): string {\n const credentials = `${formUrlEncode(clientId)}:${formUrlEncode(clientSecret)}`;\n return bytesToBase64(new TextEncoder().encode(credentials));\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction asBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n return undefined;\n}\n\nfunction ensureFetch(fetchOverride?: typeof fetch): typeof fetch {\n const runtimeFetch = fetchOverride ?? globalThis.fetch;\n if (!runtimeFetch) {\n throw new OidcLoginError('OIDC login requires a fetch implementation.');\n }\n return runtimeFetch;\n}\n\nfunction requireString(value: unknown, field: string): string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new OidcLoginError(`OIDC provider metadata missing \"${field}\".`);\n }\n return value;\n}\n\nasync function readJsonResponse<T>(\n response: Response,\n context: string,\n): Promise<T> {\n try {\n return (await response.json()) as T;\n } catch {\n throw new OidcLoginError(`${context} returned invalid JSON.`);\n }\n}\n\nfunction normalizeClaims(\n payload: OidcClaimSource,\n issuer: string,\n sourceName = 'OIDC claims',\n): OidcClaims {\n const sub = asString(payload.sub);\n if (!sub) {\n throw new OidcLoginError(`${sourceName} missing required \"sub\" claim.`);\n }\n\n return {\n sub,\n iss: asString(payload.iss) ?? issuer,\n email: asString(payload.email),\n email_verified: asBoolean(payload.email_verified),\n name: asString(payload.name),\n preferred_username: asString(payload.preferred_username),\n };\n}\n\nfunction mergeClaims(\n idTokenClaims: OidcClaims,\n userInfoClaims: OidcClaims,\n): OidcClaims {\n if (userInfoClaims.sub !== idTokenClaims.sub) {\n throw new OidcLoginError('OIDC userinfo subject does not match ID token.');\n }\n\n return {\n ...idTokenClaims,\n email: idTokenClaims.email ?? userInfoClaims.email,\n email_verified:\n idTokenClaims.email_verified ?? userInfoClaims.email_verified,\n name: idTokenClaims.name ?? userInfoClaims.name,\n preferred_username:\n idTokenClaims.preferred_username ?? userInfoClaims.preferred_username,\n };\n}\n\nfunction validateAuthorizedParty(payload: JWTPayload, clientId: string): void {\n const authorizedParty = asString(payload.azp);\n\n if (authorizedParty && authorizedParty !== clientId) {\n throw new OidcLoginError('OIDC authorized party validation failed.');\n }\n\n if (\n Array.isArray(payload.aud) &&\n payload.aud.length > 1 &&\n authorizedParty !== clientId\n ) {\n throw new OidcLoginError('OIDC authorized party validation failed.');\n }\n}\n\nfunction getTokenEndpointAuthMethod(\n provider: OidcProviderConfig,\n): OidcTokenEndpointAuthMethod {\n return (\n provider.tokenEndpointAuthMethod ??\n (provider.clientSecret ? 'client_secret_basic' : 'none')\n );\n}\n\nfunction getScopes(provider: OidcProviderConfig): string[] {\n return provider.scopes?.length ? provider.scopes : [...DEFAULT_SCOPES];\n}\n\nfunction parseTokenResponse(json: TokenEndpointResponse): OidcTokenSet {\n if (typeof json.id_token !== 'string') {\n throw new OidcLoginError('OIDC token response missing \"id_token\".');\n }\n\n return {\n accessToken: asString(json.access_token),\n expiresAt:\n typeof json.expires_in === 'number'\n ? new Date(Date.now() + json.expires_in * 1000)\n : undefined,\n idToken: json.id_token,\n refreshToken: asString(json.refresh_token),\n scope: asString(json.scope),\n tokenType: asString(json.token_type),\n };\n}\n\nfunction parseTransaction(value: unknown): OidcTransaction {\n if (!value || typeof value !== 'object') {\n throw new OidcLoginError('Invalid OIDC login transaction.');\n }\n\n const record = value as Partial<OidcTransaction>;\n if (\n !record.provider ||\n !record.state ||\n !record.nonce ||\n !record.codeVerifier ||\n typeof record.createdAt !== 'number'\n ) {\n throw new OidcLoginError('Invalid OIDC login transaction.');\n }\n\n return {\n codeVerifier: record.codeVerifier,\n createdAt: record.createdAt,\n nonce: record.nonce,\n provider: record.provider,\n returnTo: asString(record.returnTo),\n state: record.state,\n };\n}\n\nexport function encodeOidcTransaction(transaction: OidcTransaction): string {\n const json = JSON.stringify(transaction);\n return bytesToBase64Url(new TextEncoder().encode(json));\n}\n\nexport function decodeOidcTransaction(value: string): OidcTransaction {\n try {\n const json = new TextDecoder().decode(base64UrlToBytes(value));\n return parseTransaction(JSON.parse(json));\n } catch (error) {\n if (error instanceof OidcLoginError) throw error;\n throw new OidcLoginError('Invalid OIDC login transaction.');\n }\n}\n\nexport function resolveOidcProviderConfig(\n providerName?: string,\n options: OidcProviderResolutionOptions = {},\n): OidcProviderResolution {\n const oidcConfig = getUsersOidcConfig();\n const providers = {\n ...(oidcConfig.providers ?? {}),\n ...(options.providers ?? {}),\n };\n const resolvedProviderName =\n providerName ?? options.defaultProvider ?? oidcConfig.defaultProvider;\n\n if (!resolvedProviderName) {\n throw new OidcLoginError(\n 'No OIDC provider specified. Pass a provider name or configure packages.users.auth.oidc.defaultProvider.',\n );\n }\n\n const provider = providers[resolvedProviderName];\n if (!provider) {\n throw new OidcLoginError(\n `Unknown OIDC provider \"${resolvedProviderName}\". Configure it under packages.users.auth.oidc.providers.`,\n );\n }\n\n if (!provider.issuer || !provider.clientId) {\n throw new OidcLoginError(\n `OIDC provider \"${resolvedProviderName}\" requires issuer and clientId.`,\n );\n }\n\n return {\n provider,\n providerName: resolvedProviderName,\n };\n}\n\nexport class OidcLoginService {\n private readonly classOptions: SmrtClassOptions;\n private readonly clockTolerance: number | string;\n private readonly fetchImpl: typeof fetch;\n private readonly metadataCacheTtlMs: number;\n private metadataFetchedAt = 0;\n private metadataPromise?: Promise<OidcProviderMetadata>;\n private remoteJwks?: JWTVerifyGetKey;\n readonly provider: ResolvedOidcProviderConfig;\n readonly providerName: string;\n\n constructor(options: OidcLoginServiceOptions) {\n const {\n clockTolerance,\n fetch: fetchOverride,\n metadataCacheTtlMs,\n provider,\n providerName,\n ...classOptions\n } = options;\n\n if (!provider.redirectUri) {\n throw new OidcLoginError(\n `OIDC provider \"${providerName}\" requires a redirectUri.`,\n );\n }\n\n this.classOptions = classOptions;\n this.clockTolerance = clockTolerance ?? DEFAULT_CLOCK_TOLERANCE_SECONDS;\n this.fetchImpl = ensureFetch(fetchOverride);\n this.metadataCacheTtlMs =\n metadataCacheTtlMs ?? DEFAULT_METADATA_CACHE_TTL_MS;\n this.provider = {\n ...provider,\n issuer: normalizeIssuer(provider.issuer),\n };\n this.providerName = providerName;\n }\n\n createTransaction(returnTo?: string): OidcTransaction {\n return {\n codeVerifier: randomBase64Url(32),\n createdAt: Date.now(),\n nonce: randomBase64Url(32),\n provider: this.providerName,\n returnTo,\n state: randomBase64Url(32),\n };\n }\n\n async getMetadata(): Promise<OidcProviderMetadata> {\n const cacheExpired =\n this.metadataFetchedAt > 0 &&\n Date.now() - this.metadataFetchedAt > this.metadataCacheTtlMs;\n\n if (!this.metadataPromise || cacheExpired) {\n this.metadataPromise = this.fetchMetadata()\n .then((metadata) => {\n this.metadataFetchedAt = Date.now();\n this.remoteJwks = undefined;\n return metadata;\n })\n .catch((error) => {\n this.metadataPromise = undefined;\n throw error;\n });\n }\n\n return this.metadataPromise;\n }\n\n private async fetchMetadata(): Promise<OidcProviderMetadata> {\n const discoveryUrl = resolveDiscoveryUrl(this.provider);\n const response = await this.fetchImpl(discoveryUrl, {\n headers: { accept: 'application/json' },\n });\n\n if (!response.ok) {\n throw new OidcLoginError(\n `OIDC discovery failed for \"${this.providerName}\" (${response.status}).`,\n );\n }\n\n const metadata = await readJsonResponse<Partial<OidcProviderMetadata>>(\n response,\n 'OIDC discovery',\n );\n const issuer = requireString(\n metadata.issuer ?? this.provider.issuer,\n 'issuer',\n );\n\n if (normalizeIssuer(issuer) !== this.provider.issuer) {\n throw new OidcLoginError(\n `OIDC discovery issuer mismatch for \"${this.providerName}\".`,\n );\n }\n\n return {\n ...metadata,\n authorization_endpoint: requireString(\n metadata.authorization_endpoint,\n 'authorization_endpoint',\n ),\n issuer,\n jwks_uri: requireString(metadata.jwks_uri, 'jwks_uri'),\n token_endpoint: requireString(metadata.token_endpoint, 'token_endpoint'),\n };\n }\n\n async createAuthorizationUrl(\n options: CreateAuthorizationUrlOptions = {},\n ): Promise<{ transaction: OidcTransaction; url: URL }> {\n const metadata = await this.getMetadata();\n const transaction = options.transaction ?? this.createTransaction();\n const codeChallenge = await pkceChallenge(transaction.codeVerifier);\n const url = new URL(metadata.authorization_endpoint);\n\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('client_id', this.provider.clientId);\n url.searchParams.set('redirect_uri', this.provider.redirectUri);\n url.searchParams.set('scope', getScopes(this.provider).join(' '));\n url.searchParams.set('state', transaction.state);\n url.searchParams.set('nonce', transaction.nonce);\n url.searchParams.set('code_challenge', codeChallenge);\n url.searchParams.set('code_challenge_method', 'S256');\n\n for (const [key, value] of Object.entries({\n ...this.provider.authorizationParams,\n ...options.authorizationParams,\n })) {\n if (value !== undefined) {\n url.searchParams.set(key, String(value));\n }\n }\n\n return { transaction, url };\n }\n\n async exchangeCallback(\n callbackUrl: string | URL,\n transaction: OidcTransaction,\n ): Promise<OidcCallbackResult> {\n const code = this.validateCallback(callbackUrl, transaction);\n const tokens = await this.exchangeCode(code, transaction);\n const idTokenClaims = await this.verifyIdToken(\n tokens.idToken,\n transaction.nonce,\n );\n const claims = await this.enrichClaimsFromUserInfo(idTokenClaims, tokens);\n\n return { claims, tokens };\n }\n\n async completeLogin(\n callbackUrl: string | URL,\n transaction: OidcTransaction,\n ): Promise<OidcLoginResult> {\n const { claims, tokens } = await this.exchangeCallback(\n callbackUrl,\n transaction,\n );\n const users = await UserCollection.create(this.classOptions);\n const result = await users.getOrCreateFromOidc(claims, this.providerName);\n\n return {\n ...result,\n claims,\n tokens,\n };\n }\n\n private validateCallback(\n callbackUrl: string | URL,\n transaction: OidcTransaction,\n ): string {\n if (transaction.provider !== this.providerName) {\n throw new OidcLoginError('OIDC login transaction provider mismatch.');\n }\n\n const url = callbackUrl instanceof URL ? callbackUrl : new URL(callbackUrl);\n const error = url.searchParams.get('error');\n if (error) {\n const description = url.searchParams.get('error_description');\n throw new OidcLoginError(\n description\n ? `OIDC provider returned \"${error}\": ${description}`\n : `OIDC provider returned \"${error}\".`,\n );\n }\n\n const state = url.searchParams.get('state');\n if (!state || state !== transaction.state) {\n throw new OidcLoginError('OIDC state validation failed.');\n }\n\n const responseIssuer = url.searchParams.get('iss');\n if (\n responseIssuer &&\n normalizeIssuer(responseIssuer) !== this.provider.issuer\n ) {\n throw new OidcLoginError('OIDC response issuer validation failed.');\n }\n\n const code = url.searchParams.get('code');\n if (!code) {\n throw new OidcLoginError('OIDC callback missing authorization code.');\n }\n\n return code;\n }\n\n private async exchangeCode(\n code: string,\n transaction: OidcTransaction,\n ): Promise<OidcTokenSet> {\n const metadata = await this.getMetadata();\n const body = new URLSearchParams({\n code,\n code_verifier: transaction.codeVerifier,\n grant_type: 'authorization_code',\n redirect_uri: this.provider.redirectUri,\n });\n const headers = new Headers({\n accept: 'application/json',\n 'content-type': 'application/x-www-form-urlencoded',\n });\n\n const authMethod = getTokenEndpointAuthMethod(this.provider);\n if (authMethod === 'client_secret_basic') {\n if (!this.provider.clientSecret) {\n throw new OidcLoginError(\n `OIDC provider \"${this.providerName}\" is missing clientSecret.`,\n );\n }\n headers.set(\n 'authorization',\n `Basic ${encodeBasicAuth(this.provider.clientId, this.provider.clientSecret)}`,\n );\n } else {\n body.set('client_id', this.provider.clientId);\n if (authMethod === 'client_secret_post') {\n if (!this.provider.clientSecret) {\n throw new OidcLoginError(\n `OIDC provider \"${this.providerName}\" is missing clientSecret.`,\n );\n }\n body.set('client_secret', this.provider.clientSecret);\n }\n }\n\n const response = await this.fetchImpl(metadata.token_endpoint, {\n body,\n headers,\n method: 'POST',\n });\n const json = await readJsonResponse<TokenEndpointResponse>(\n response,\n 'OIDC token endpoint',\n );\n\n if (!response.ok) {\n const providerError = asString(json.error);\n const description = asString(json.error_description);\n throw new OidcLoginError(\n description\n ? `OIDC token exchange failed (${providerError ?? response.status}): ${description}`\n : `OIDC token exchange failed (${providerError ?? response.status}).`,\n );\n }\n\n return parseTokenResponse(json);\n }\n\n private async enrichClaimsFromUserInfo(\n claims: OidcClaims,\n tokens: OidcTokenSet,\n ): Promise<OidcClaims> {\n if (claims.email || !tokens.accessToken) {\n return claims;\n }\n\n const metadata = await this.getMetadata();\n if (!metadata.userinfo_endpoint) {\n return claims;\n }\n\n const tokenType = tokens.tokenType ?? 'Bearer';\n const response = await this.fetchImpl(metadata.userinfo_endpoint, {\n headers: {\n accept: 'application/json',\n authorization: `${tokenType} ${tokens.accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw new OidcLoginError(\n `OIDC userinfo request failed (${response.status}).`,\n );\n }\n\n const userInfo = await readJsonResponse<Record<string, unknown>>(\n response,\n 'OIDC userinfo endpoint',\n );\n\n return mergeClaims(\n claims,\n normalizeClaims(userInfo, metadata.issuer, 'OIDC userinfo'),\n );\n }\n\n private async verifyIdToken(\n idToken: string,\n expectedNonce: string,\n ): Promise<OidcClaims> {\n const metadata = await this.getMetadata();\n this.remoteJwks ??= createRemoteJWKSet(new URL(metadata.jwks_uri), {\n [customFetch]: this.fetchImpl,\n });\n\n const { payload } = await jwtVerify(idToken, this.remoteJwks, {\n audience: this.provider.clientId,\n clockTolerance: this.clockTolerance,\n issuer: metadata.issuer,\n });\n\n validateAuthorizedParty(payload, this.provider.clientId);\n\n if (payload.nonce !== expectedNonce) {\n throw new OidcLoginError('OIDC nonce validation failed.');\n }\n\n return normalizeClaims(payload, metadata.issuer, 'OIDC ID token');\n }\n}\n","/**\n * PermissionResolver - Resolves effective permissions for a user in a tenant\n * @packageDocumentation\n */\n\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { GroupMemberCollection } from '../collections/GroupMemberCollection.js';\nimport { GroupRoleCollection } from '../collections/GroupRoleCollection.js';\nimport { MembershipCollection } from '../collections/MembershipCollection.js';\nimport { MembershipOverrideCollection } from '../collections/MembershipOverrideCollection.js';\nimport { PermissionCollection } from '../collections/PermissionCollection.js';\nimport { RolePermissionCollection } from '../collections/RolePermissionCollection.js';\nimport { TenantCollection } from '../collections/TenantCollection.js';\nimport { TenantPermissionOverrideCollection } from '../collections/TenantPermissionOverrideCollection.js';\nimport type { Membership } from '../models/Membership.js';\nimport type { Tenant } from '../models/Tenant.js';\n\n/**\n * Permission resolution result\n */\nexport interface PermissionResolutionResult {\n /** Set of granted permission slugs */\n permissions: Set<string>;\n /** Membership ID used for resolution */\n membershipId: string | null;\n /** Role ID from membership */\n roleId: string | null;\n /** Group IDs that contributed permissions */\n groupIds: string[];\n /** Permission IDs explicitly denied */\n deniedPermissionIds: string[];\n}\n\nexport interface PermissionResolutionOptions {\n /**\n * Active membership already resolved by the caller for this user/tenant.\n * Passing this lets request-scoped session loaders avoid re-querying the\n * same membership row before resolving permissions.\n */\n membership?: Membership | null;\n}\n\n/**\n * Tenant permission inheritance chain result\n */\nexport interface TenantPermissionInheritanceResult {\n /** Effective tenant permissions (slugs) after inheritance resolution */\n permissions: Set<string>;\n /** Tenant IDs that contributed to the inheritance chain */\n contributingTenantIds: string[];\n /** Whether inheritance was active (at least one tenant in chain had inheritPermissions: true) */\n inheritanceActive: boolean;\n /**\n * Permission slugs explicitly DENY'd by a `TenantPermissionOverride` anywhere\n * in the tenant hierarchy. These are a HARD, tenant-wide block:\n * `resolvePermissions` subtracts them AFTER role + group grants are applied,\n * so a tenant-DENY overrides a permission a role/group otherwise grants. A\n * more-specific membership-override GRANT can still re-add a slug listed here;\n * a membership-override DENY stays absolute. (This set is independent of the\n * net `permissions` above, which only reflects DENY's effect on the inherited\n * cascade.)\n */\n deniedPermissions: Set<string>;\n}\n\n/**\n * PermissionResolver resolves the effective permissions for a user in a tenant.\n *\n * Resolution algorithm:\n * 1. Resolve tenant hierarchy permissions (if hierarchical tenants are used)\n * 2. Get user's membership in the tenant\n * 3. Get base permissions from membership's role\n * 4. Get user's groups in the tenant\n * 5. Add permissions from group roles\n * 6. Apply membership overrides (grant/deny)\n *\n * DENY overrides take precedence over GRANT overrides at every level.\n *\n * ## Hierarchical Tenant Permissions\n *\n * When tenants are organized hierarchically, permissions can cascade from\n * parent tenants to child tenants. The cascade is controlled by:\n * - Parent's `cascadePermissions`: If true, parent pushes permissions down\n * - Child's `inheritPermissions`: If true, child accepts parent's permissions\n *\n * Child tenants can override inherited permissions using TenantPermissionOverride:\n * - INHERIT: Use parent's value (default)\n * - GRANT: Explicitly grant at this level\n * - DENY: Explicitly block (even if parent grants)\n *\n * @example\n * ```typescript\n * const resolver = new PermissionResolver(options);\n * await resolver.initialize();\n *\n * // Check single permission\n * const canCreate = await resolver.hasPermission(userId, tenantId, 'articles.create');\n *\n * // Get all permissions\n * const result = await resolver.resolvePermissions(userId, tenantId);\n * console.log(result.permissions); // Set<string>\n *\n * // Resolve tenant-level permissions only (without user context)\n * const tenantPerms = await resolver.resolveTenantPermissions(tenantId);\n * ```\n */\nexport class PermissionResolver {\n private options: SmrtClassOptions;\n private membershipCollection!: MembershipCollection;\n private rolePermissionCollection!: RolePermissionCollection;\n private membershipOverrideCollection!: MembershipOverrideCollection;\n private groupMemberCollection!: GroupMemberCollection;\n private groupRoleCollection!: GroupRoleCollection;\n private permissionCollection!: PermissionCollection;\n private tenantCollection!: TenantCollection;\n private tenantPermissionOverrideCollection!: TenantPermissionOverrideCollection;\n\n constructor(options: SmrtClassOptions) {\n this.options = options;\n }\n\n /**\n * Initialize collections\n *\n * Each collection is created via the inherited static `SmrtCollection.create()`\n * factory, which is generically typed to return the concrete subclass instance.\n */\n async initialize(): Promise<void> {\n this.membershipCollection = await MembershipCollection.create(this.options);\n this.rolePermissionCollection =\n await RolePermissionCollection.create(this.options);\n this.membershipOverrideCollection =\n await MembershipOverrideCollection.create(this.options);\n this.groupMemberCollection =\n await GroupMemberCollection.create(this.options);\n this.groupRoleCollection = await GroupRoleCollection.create(this.options);\n this.permissionCollection = await PermissionCollection.create(this.options);\n this.tenantCollection = await TenantCollection.create(this.options);\n this.tenantPermissionOverrideCollection =\n await TenantPermissionOverrideCollection.create(this.options);\n }\n\n // ============= Tenant Hierarchy Permission Resolution =============\n\n /**\n * Resolve effective permissions for a tenant, considering hierarchy inheritance.\n *\n * Algorithm:\n * 1. Get the tenant and its ancestors (from root to immediate parent)\n * 2. Batch fetch all permission overrides for the entire chain (single query)\n * 3. Walk down the chain, building up permissions:\n * - Start with root tenant's permissions\n * - For each child: if parent.cascadePermissions && child.inheritPermissions:\n * - Merge parent's permissions\n * - Apply child's overrides (GRANT adds, DENY removes)\n * 4. Return the final effective permission set\n */\n async resolveTenantPermissions(\n tenantId: string,\n ): Promise<TenantPermissionInheritanceResult> {\n const result: TenantPermissionInheritanceResult = {\n permissions: new Set<string>(),\n contributingTenantIds: [],\n inheritanceActive: false,\n deniedPermissions: new Set<string>(),\n };\n\n const tenant = await this.tenantCollection.get({ id: tenantId });\n if (!tenant) {\n return result;\n }\n\n // Get the inheritance chain from root to this tenant\n const ancestors =\n await this.tenantCollection.getAncestorsFromRoot(tenantId);\n const chain: Tenant[] = [...ancestors, tenant];\n\n // Batch fetch all permission overrides for the entire chain (single query)\n const chainTenantIds = chain.map((t) => t.id!);\n const allOverridesMap =\n await this.tenantPermissionOverrideCollection.getOverridesByEffectBatch(\n chainTenantIds,\n );\n\n // Build a set of permission IDs for batch lookup. Also track every\n // tenant-level DENY id across the chain: tenant-DENY is a hard, tenant-wide\n // block that `resolvePermissions` subtracts from role/group grants too, so\n // it must be reported independently of the net inherited `permissions` set\n // (which only reflects DENY's effect on the cascade, not on roles).\n const allPermissionIds = new Set<string>();\n const deniedPermissionIds = new Set<string>();\n for (const overrides of allOverridesMap.values()) {\n for (const id of overrides.grantedPermissionIds) allPermissionIds.add(id);\n for (const id of overrides.deniedPermissionIds) {\n allPermissionIds.add(id);\n deniedPermissionIds.add(id);\n }\n }\n\n // Process each tenant in the chain\n let inheritedPermissions = new Set<string>();\n\n for (let i = 0; i < chain.length; i++) {\n const current = chain[i];\n const isFirst = i === 0;\n const previous = isFirst ? null : chain[i - 1];\n\n // Check if inheritance is active for this tenant\n const shouldInherit =\n !isFirst && previous?.cascadePermissions && current.inheritPermissions;\n\n if (shouldInherit) {\n result.inheritanceActive = true;\n }\n\n // Get this tenant's permission overrides from the batch result\n const overrides = allOverridesMap.get(current.id!) ?? {\n grantedPermissionIds: [],\n deniedPermissionIds: [],\n inheritedPermissionIds: [],\n };\n\n // Build this tenant's effective permissions\n const currentPermissions = new Set<string>();\n\n // Track if this tenant actually contributed to the permission set\n let contributed = false;\n\n // Start with inherited permissions if applicable\n if (shouldInherit && inheritedPermissions.size > 0) {\n for (const permId of inheritedPermissions) {\n currentPermissions.add(permId);\n }\n contributed = true;\n }\n\n // Apply grants\n for (const permId of overrides.grantedPermissionIds) {\n currentPermissions.add(permId);\n contributed = true;\n }\n\n // Apply denies (remove) - only counts as contribution if something was actually removed\n for (const permId of overrides.deniedPermissionIds) {\n if (currentPermissions.has(permId)) {\n currentPermissions.delete(permId);\n contributed = true;\n }\n }\n\n // Only add to contributingTenantIds if this tenant actually affected the final set\n if (contributed && !result.contributingTenantIds.includes(current.id!)) {\n result.contributingTenantIds.push(current.id!);\n }\n\n // This becomes the inherited set for the next iteration\n inheritedPermissions = currentPermissions;\n }\n\n // Batch fetch all permissions to get slugs\n if (allPermissionIds.size > 0) {\n const permissionsMap = await this.permissionCollection.findByIds(\n Array.from(allPermissionIds),\n );\n\n // Convert IDs to slugs in the result\n for (const permId of inheritedPermissions) {\n const perm = permissionsMap.get(permId);\n if (perm?.slug) {\n result.permissions.add(perm.slug);\n }\n }\n\n // Record the slugs DENY'd at any tenant level so callers can enforce the\n // hard tenant-wide block over role/group grants — but NET against the\n // cascade's own resolution: a slug a more-specific tenant GRANT re-added\n // (so it survives in the net-granted `inheritedPermissions`) must NOT be\n // in the hard-block set, because the cascade already decided GRANT\n // (most-specific wins). Without this guard a parent-DENY + child-GRANT\n // slug would wrongly override the child GRANT and any role/group grant.\n for (const permId of deniedPermissionIds) {\n if (inheritedPermissions.has(permId)) continue;\n const perm = permissionsMap.get(permId);\n if (perm?.slug) {\n result.deniedPermissions.add(perm.slug);\n }\n }\n }\n\n return result;\n }\n\n /**\n * Get the inheritance chain for a tenant (for debugging/display purposes)\n */\n async getTenantInheritanceChain(\n tenantId: string,\n ): Promise<Array<{ tenant: Tenant; inherits: boolean; cascades: boolean }>> {\n const tenant = await this.tenantCollection.get({ id: tenantId });\n if (!tenant) {\n return [];\n }\n\n const ancestors =\n await this.tenantCollection.getAncestorsFromRoot(tenantId);\n const chain: Array<{\n tenant: Tenant;\n inherits: boolean;\n cascades: boolean;\n }> = [];\n\n for (let i = 0; i < ancestors.length; i++) {\n const current = ancestors[i];\n const next = i + 1 < ancestors.length ? ancestors[i + 1] : tenant;\n\n chain.push({\n tenant: current,\n inherits: false, // Root or ancestor doesn't inherit in this context\n cascades: current.cascadePermissions && next.inheritPermissions,\n });\n }\n\n // Add the target tenant\n chain.push({\n tenant: tenant,\n inherits: tenant.inheritPermissions && ancestors.length > 0,\n cascades: tenant.cascadePermissions,\n });\n\n return chain;\n }\n\n /**\n * Resolve all effective permissions for a user in a tenant.\n *\n * Precedence (broad -> specific, most-specific wins):\n * tenant-inherited (cascade)\n * -> role\n * -> group roles\n * -> tenant-DENY (removes; overrides role/group grants, tenant-wide)\n * -> membership GRANT (re-adds; most specific, can win over a tenant-DENY)\n * -> membership DENY (absolute; always wins)\n *\n * Algorithm:\n * 1. Get membership and collect all permission IDs from all sources\n * 2. Batch fetch all permissions in a single query\n * 3. Apply permissions from role, then groups\n * 4. Subtract tenant-level DENY'd slugs (hard tenant-wide block)\n * 5. Apply membership GRANT overrides (can re-add a tenant-DENY'd slug)\n * 6. Subtract membership DENY overrides (absolute precedence)\n */\n async resolvePermissions(\n userId: string,\n tenantId: string,\n options: PermissionResolutionOptions = {},\n ): Promise<PermissionResolutionResult> {\n const result: PermissionResolutionResult = {\n permissions: new Set<string>(),\n membershipId: null,\n roleId: null,\n groupIds: [],\n deniedPermissionIds: [],\n };\n\n // 1. Get membership, reusing a request-scoped row when the caller already\n // resolved it for this exact user/tenant.\n const membership =\n options.membership === undefined\n ? await this.membershipCollection.findByUserAndTenant(userId, tenantId)\n : options.membership;\n if (!membership || !membership.isActive()) {\n return result;\n }\n if (membership.userId !== userId || membership.tenantId !== tenantId) {\n return result;\n }\n\n result.membershipId = membership.id ?? null;\n result.roleId = membership.roleId ?? null;\n\n const tenantPermissions = await this.resolveTenantPermissions(tenantId);\n for (const slug of tenantPermissions.permissions) {\n result.permissions.add(slug);\n }\n\n if (!membership.roleId) {\n return result;\n }\n\n // 2. Collect all permission IDs from all sources (no awaits in loops)\n const allPermissionIds: Set<string> = new Set();\n const rolePermissionIds: string[] = [];\n const groupRolePermissionIds: Map<string, string[]> = new Map();\n\n // 2a. Get base role permissions\n const baseRolePermIds =\n await this.rolePermissionCollection.getPermissionIds(membership.roleId);\n for (const id of baseRolePermIds) {\n allPermissionIds.add(id);\n rolePermissionIds.push(id);\n }\n\n // 2b. Get user's groups in the tenant (scoped to prevent cross-tenant leakage)\n const groupIds = await this.groupMemberCollection.getGroupIdsForTenant(\n userId,\n tenantId,\n );\n result.groupIds = groupIds;\n\n // 2c. Collect permissions from group roles\n for (const groupId of groupIds) {\n const groupRoleIds = await this.groupRoleCollection.getRoleIds(groupId);\n for (const roleId of groupRoleIds) {\n const permIds =\n await this.rolePermissionCollection.getPermissionIds(roleId);\n for (const id of permIds) {\n allPermissionIds.add(id);\n }\n groupRolePermissionIds.set(roleId, permIds);\n }\n }\n\n // 2d. Get membership overrides\n if (!membership.id) {\n return result;\n }\n const membershipId = membership.id;\n const grantedPermissionIds =\n await this.membershipOverrideCollection.getGrantedPermissionIds(\n membershipId,\n );\n const deniedPermissionIds =\n await this.membershipOverrideCollection.getDeniedPermissionIds(\n membershipId,\n );\n\n result.deniedPermissionIds = deniedPermissionIds;\n\n for (const id of grantedPermissionIds) {\n allPermissionIds.add(id);\n }\n for (const id of deniedPermissionIds) {\n allPermissionIds.add(id);\n }\n\n // 3. Batch fetch all permissions in a single query\n const permissionsMap = await this.permissionCollection.findByIds(\n Array.from(allPermissionIds),\n );\n\n // Build ID to slug mapping\n const permissionIdToSlug = new Map<string, string>();\n for (const [id, perm] of permissionsMap) {\n if (perm.slug) {\n permissionIdToSlug.set(id, perm.slug);\n }\n }\n\n // 4. Apply permissions from role\n for (const permId of rolePermissionIds) {\n const slug = permissionIdToSlug.get(permId);\n if (slug) {\n result.permissions.add(slug);\n }\n }\n\n // 5. Apply permissions from group roles\n for (const permIds of groupRolePermissionIds.values()) {\n for (const permId of permIds) {\n const slug = permissionIdToSlug.get(permId);\n if (slug) {\n result.permissions.add(slug);\n }\n }\n }\n\n // 6. Subtract tenant-level DENY'd slugs. A tenant-DENY is a HARD,\n // tenant-wide block that overrides role and group grants too — sitting just\n // above the most-specific membership overrides in precedence. It runs\n // BEFORE the membership GRANT pass so a more-specific membership GRANT (step\n // 7) can deliberately re-add a slug a tenant DENYs.\n for (const slug of tenantPermissions.deniedPermissions) {\n result.permissions.delete(slug);\n }\n\n // 7. Apply granted membership overrides (most specific GRANT; can re-add a\n // tenant-DENY'd slug).\n for (const permId of grantedPermissionIds) {\n const slug = permissionIdToSlug.get(permId);\n if (slug) {\n result.permissions.add(slug);\n }\n }\n\n // 8. Remove denied membership overrides (DENY takes absolute precedence over\n // tenant, role, group, and granted membership permissions).\n for (const permId of deniedPermissionIds) {\n const slug = permissionIdToSlug.get(permId);\n if (slug) {\n result.permissions.delete(slug);\n }\n }\n\n return result;\n }\n\n /**\n * Check if a user has a specific permission in a tenant\n */\n async hasPermission(\n userId: string,\n tenantId: string,\n permissionSlug: string,\n options: PermissionResolutionOptions = {},\n ): Promise<boolean> {\n const result = await this.resolvePermissions(userId, tenantId, options);\n return result.permissions.has(permissionSlug);\n }\n\n /**\n * Check if a user has all of the specified permissions\n */\n async hasAllPermissions(\n userId: string,\n tenantId: string,\n permissionSlugs: string[],\n options: PermissionResolutionOptions = {},\n ): Promise<boolean> {\n const result = await this.resolvePermissions(userId, tenantId, options);\n return permissionSlugs.every((slug) => result.permissions.has(slug));\n }\n\n /**\n * Check if a user has any of the specified permissions\n */\n async hasAnyPermission(\n userId: string,\n tenantId: string,\n permissionSlugs: string[],\n options: PermissionResolutionOptions = {},\n ): Promise<boolean> {\n const result = await this.resolvePermissions(userId, tenantId, options);\n return permissionSlugs.some((slug) => result.permissions.has(slug));\n }\n\n /**\n * Static factory method\n */\n static async create(options: SmrtClassOptions): Promise<PermissionResolver> {\n const resolver = new PermissionResolver(options);\n await resolver.initialize();\n return resolver;\n }\n}\n","/**\n * SessionService - Higher-level session management combining sessions with user/permission loading\n * @packageDocumentation\n */\n\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { MembershipCollection } from '../collections/MembershipCollection.js';\nimport {\n type CreateSessionOptions,\n SessionCollection,\n} from '../collections/SessionCollection.js';\nimport { UserCollection } from '../collections/UserCollection.js';\nimport type { Membership } from '../models/Membership.js';\nimport { DEFAULT_SESSION_TTL, type Session } from '../models/Session.js';\nimport type { User } from '../models/User.js';\nimport { PermissionResolver } from './PermissionResolver.js';\n\n/**\n * Session context with user and permissions\n */\nexport interface SessionContext {\n /** The User record */\n user: User;\n /** Active membership for the current tenant, if one was resolved */\n membership?: Membership | null;\n /** Resolved permission slugs */\n permissions: string[];\n /** Tenant ID from session (if any) */\n tenantId: string | null;\n /** Session ID */\n sessionId: string;\n}\n\n/**\n * Result of {@link SessionService.switchTenant}.\n *\n * A successful switch into a non-null tenant ROTATES the session id (#1354\n * follow-up): a brand-new {@link Session} is minted and the old one is revoked,\n * so a captured pre-switch id stops validating. Callers MUST persist `sessionId`\n * (e.g. re-set the session cookie) after a rotation.\n */\nexport interface SwitchTenantResult {\n /** Whether the switch succeeded (true also for a `null` clear). */\n switched: boolean;\n /**\n * The session id to use going forward: the NEW id after a rotation, the\n * unchanged id after a `null` clear, or `null` when the switch failed\n * (unknown session or non-member — fail-closed).\n */\n sessionId: string | null;\n /** The resulting session (new on rotation; existing on clear; null on failure). */\n session: Session | null;\n /** True only when a fresh session id was minted (non-null tenant switch). */\n rotated: boolean;\n}\n\n/**\n * Options for SessionService\n */\nexport interface SessionServiceOptions extends SmrtClassOptions {\n /** Default session TTL in seconds (default: 7 days) */\n defaultTTL?: number;\n /** Cookie name (default: 'sid') */\n cookieName?: string;\n /** Whether to auto-extend sessions on access (default: false) */\n autoExtend?: boolean;\n}\n\n/**\n * SessionService provides high-level session management that combines\n * session storage with user and permission loading.\n *\n * This is the main service to use for session-based authentication.\n *\n * @example\n * ```typescript\n * const sessionService = await SessionService.create({\n * db: { type: 'sqlite', url: 'app.db' },\n * defaultTTL: 7 * 24 * 60 * 60, // 7 days\n * });\n *\n * // Create session after login\n * const sessionId = await sessionService.createSession(userId, tenantId);\n *\n * // Load session context on each request\n * const context = await sessionService.loadSessionContext(sessionId);\n * if (context) {\n * console.log('User:', context.user.email);\n * console.log('Permissions:', context.permissions);\n * }\n *\n * // Destroy session on logout\n * await sessionService.destroySession(sessionId);\n * ```\n */\nexport class SessionService {\n private options: SessionServiceOptions;\n private sessionCollection!: SessionCollection;\n private userCollection!: UserCollection;\n private membershipCollection!: MembershipCollection;\n private permissionResolver!: PermissionResolver;\n private defaultTTL: number;\n private autoExtend: boolean;\n\n constructor(options: SessionServiceOptions) {\n this.options = options;\n this.defaultTTL = options.defaultTTL ?? DEFAULT_SESSION_TTL;\n this.autoExtend = options.autoExtend ?? false;\n }\n\n /**\n * Initialize collections\n */\n async initialize(): Promise<void> {\n this.sessionCollection = await SessionCollection.create(this.options);\n this.userCollection = await UserCollection.create(this.options);\n this.membershipCollection =\n await MembershipCollection.create(this.options);\n this.permissionResolver = await PermissionResolver.create(this.options);\n }\n\n /**\n * Create a new session for a user\n *\n * @param userId - The user ID\n * @param tenantId - Optional tenant context\n * @param options - Additional session options\n * @returns The session ID\n */\n async createSession(\n userId: string,\n tenantId?: string,\n options?: Partial<CreateSessionOptions>,\n ): Promise<string> {\n const session = await this.sessionCollection.createSession({\n userId,\n tenantId,\n ttl: options?.ttl ?? this.defaultTTL,\n userAgent: options?.userAgent,\n ipAddress: options?.ipAddress,\n data: options?.data,\n });\n\n return session.id as string;\n }\n\n /**\n * Load full session context (user + permissions)\n *\n * Returns null if session is invalid or user doesn't exist\n */\n async loadSessionContext(sessionId: string): Promise<SessionContext | null> {\n // Find valid session\n const session = await this.sessionCollection.findValidSession(sessionId);\n if (!session) return null;\n\n // Load user\n const user = await this.userCollection.get(session.userId);\n if (!user || !user.isActive()) return null;\n\n // Resolve permissions (only if tenant context exists)\n let permissions: string[] = [];\n let membership: Membership | null = null;\n if (session.tenantId) {\n const resolvedMembership =\n await this.membershipCollection.findByUserAndTenant(\n session.userId,\n session.tenantId,\n );\n membership = resolvedMembership?.isActive() ? resolvedMembership : null;\n\n const result = await this.permissionResolver.resolvePermissions(\n session.userId,\n session.tenantId,\n { membership },\n );\n permissions = Array.from(result.permissions);\n }\n\n // Touch session (and optionally extend)\n if (this.autoExtend) {\n session.extend(this.defaultTTL);\n } else {\n session.touch();\n }\n await session.save();\n\n return {\n user,\n membership,\n permissions,\n tenantId: session.tenantId,\n sessionId: session.id as string,\n };\n }\n\n /**\n * Get the initialized database connection backing this session service.\n */\n getDatabase() {\n return this.sessionCollection.db;\n }\n\n /**\n * Refresh session (extend expiry, update lastAccessed)\n */\n async refreshSession(sessionId: string): Promise<boolean> {\n return this.sessionCollection.touch(sessionId, true, this.defaultTTL);\n }\n\n /**\n * Destroy a session (revoke it)\n */\n async destroySession(sessionId: string): Promise<boolean> {\n return this.sessionCollection.revokeSession(sessionId);\n }\n\n /**\n * Destroy all sessions for a user (logout from all devices)\n */\n async destroyAllUserSessions(userId: string): Promise<number> {\n return this.sessionCollection.revokeUserSessions(userId);\n }\n\n /**\n * Switch tenant context for a session.\n *\n * A session's `tenantId` is the tenant-isolation key for every `@TenantScoped`\n * query, so it must never be set to a tenant the session's user is not an\n * active member of — otherwise a caller could read/write another tenant's data\n * by feeding an arbitrary id here (e.g. straight from untrusted form data).\n *\n * Fail-closed (#1400): the user's ACTIVE membership in the target tenant is\n * verified BEFORE any write. A non-member switch returns\n * `{ switched: false, ... }` and mutates nothing.\n *\n * Session-id ROTATION (#1354 follow-up): a successful switch into a non-null\n * tenant mints a BRAND-NEW session (fresh secure id, fresh TTL) for the same\n * user with the new tenant, then REVOKES the old session — so any captured\n * pre-switch session id immediately stops validating, shrinking the blast\n * radius of a leaked id across a privilege/tenant boundary. The device context\n * (user agent, IP, custom data) carries over to the new session. Callers MUST\n * persist the returned `sessionId` (e.g. re-set the cookie).\n *\n * Passing `null` clears the tenant context, is always allowed, and stays\n * in-place (no rotation — there is no privilege boundary being crossed).\n *\n * @returns A {@link SwitchTenantResult}; check `switched` for success.\n */\n async switchTenant(\n sessionId: string,\n tenantId: string | null,\n ): Promise<SwitchTenantResult> {\n const failClosed: SwitchTenantResult = {\n switched: false,\n sessionId: null,\n session: null,\n rotated: false,\n };\n\n const session = await this.sessionCollection.findValidSession(sessionId);\n if (!session) return failClosed;\n\n // Clearing the tenant context crosses no privilege boundary, so keep the\n // existing session in place (no rotation needed).\n if (tenantId === null) {\n const ok = await this.sessionCollection.setSessionTenant(sessionId, null);\n if (!ok) return failClosed;\n const updated = await this.sessionCollection.findValidSession(sessionId);\n return {\n switched: true,\n sessionId,\n session: updated,\n rotated: false,\n };\n }\n\n // Fail-closed membership check BEFORE any write.\n const membership = await this.membershipCollection.findByUserAndTenant(\n session.userId,\n tenantId,\n );\n if (!membership || !membership.isActive()) {\n return failClosed;\n }\n\n // Rotate FAIL-CLOSED: revoke the old session FIRST, then mint the fresh one.\n // If the second write fails the caller ends up needing to re-auth (the old\n // id is already invalid) rather than retaining a still-valid stale-tenant\n // session — so a captured pre-switch id provably stops validating before we\n // ever report success.\n await this.sessionCollection.revokeSession(sessionId);\n const rotated = await this.sessionCollection.createSession({\n userId: session.userId,\n tenantId,\n ttl: this.defaultTTL,\n userAgent: session.userAgent,\n ipAddress: session.ipAddress,\n data: session.data,\n });\n\n return {\n switched: true,\n sessionId: rotated.id as string,\n session: rotated,\n rotated: true,\n };\n }\n\n /**\n * Get all active sessions for a user (for \"manage sessions\" UI)\n */\n async getUserSessions(userId: string) {\n return this.sessionCollection.findByUser(userId);\n }\n\n /**\n * Clean up expired sessions (run periodically)\n */\n async cleanupExpiredSessions(): Promise<number> {\n return this.sessionCollection.deleteExpired();\n }\n\n /**\n * Check if a permission is granted for the session\n */\n async hasPermission(sessionId: string, permission: string): Promise<boolean> {\n const context = await this.loadSessionContext(sessionId);\n if (!context) return false;\n return context.permissions.includes(permission);\n }\n\n /**\n * Get session data\n */\n async getSessionData<T>(\n sessionId: string,\n key: string,\n ): Promise<T | undefined> {\n return this.sessionCollection.getSessionData<T>(sessionId, key);\n }\n\n /**\n * Set session data\n */\n async setSessionData(\n sessionId: string,\n key: string,\n value: unknown,\n ): Promise<boolean> {\n return this.sessionCollection.setSessionData(sessionId, key, value);\n }\n\n /**\n * Static factory method\n */\n static async create(options: SessionServiceOptions): Promise<SessionService> {\n const service = new SessionService(options);\n await service.initialize();\n return service;\n }\n}\n","/**\n * Request-scoped session permission context helpers\n * @packageDocumentation\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { getPackageConfig } from '@happyvertical/smrt-config';\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n type SessionContext,\n SessionService,\n type SessionServiceOptions,\n} from './SessionService.js';\n\ninterface QueryableDatabase extends DatabaseInterface {\n beginTransaction?: () => Promise<TransactionDatabase>;\n url: string;\n}\n\ninterface TransactionDatabase extends QueryableDatabase {\n commit: () => Promise<void>;\n isActive: () => boolean;\n rollback: () => Promise<void>;\n}\n\nexport interface SessionPermissionRuntimeContext {\n database?: QueryableDatabase;\n permissions: string[];\n permissionSet: Set<string>;\n membership: SessionContext['membership'];\n postgresRls: boolean;\n session: SessionContext | null;\n sessionId: string | null;\n superAdminBypass: boolean;\n systemContext: boolean;\n tenantId: string | null;\n user: SessionContext['user'] | null;\n userId: string | null;\n}\n\nexport interface SessionPermissionRuntimeOptions extends SmrtClassOptions {\n enterTenantContext?: boolean;\n postgresRls?: boolean;\n sessionId?: string | null;\n sessionService?: SessionService;\n superAdminBypass?: boolean;\n systemContext?: boolean;\n}\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtGetRequestPermissionContext:\n | (() => SessionPermissionRuntimeContext | undefined)\n | undefined;\n // eslint-disable-next-line no-var\n var __smrtGetRequestScopedDatabase:\n | (() => QueryableDatabase | undefined)\n | undefined;\n}\n\nconst requestPermissionContextStorage =\n new AsyncLocalStorage<SessionPermissionRuntimeContext>();\n\nexport function getCurrentSessionPermissionContext():\n | SessionPermissionRuntimeContext\n | undefined {\n return requestPermissionContextStorage.getStore();\n}\n\nexport function getRequestScopedDatabase(): QueryableDatabase | undefined {\n return getCurrentSessionPermissionContext()?.database;\n}\n\nglobalThis.__smrtGetRequestPermissionContext ??=\n getCurrentSessionPermissionContext;\nglobalThis.__smrtGetRequestScopedDatabase ??= getRequestScopedDatabase;\n\nfunction isProbablyPostgres(\n configDb: SmrtClassOptions['db'],\n database: QueryableDatabase,\n): boolean {\n if (\n configDb &&\n typeof configDb === 'object' &&\n !('query' in configDb) &&\n 'type' in configDb &&\n configDb.type === 'postgres'\n ) {\n return true;\n }\n\n if (typeof database.url === 'string' && database.url.startsWith('postgres')) {\n return true;\n }\n\n return (database.constructor?.name || '').toLowerCase().includes('postgres');\n}\n\nasync function setPostgresSessionVariables(\n database: QueryableDatabase,\n context: SessionPermissionRuntimeContext,\n): Promise<void> {\n await database.query(\n \"SELECT set_config('smrt.tenant_id', $1, true)\",\n context.tenantId ?? '',\n );\n await database.query(\n \"SELECT set_config('smrt.user_id', $1, true)\",\n context.userId ?? '',\n );\n await database.query(\n \"SELECT set_config('smrt.session_id', $1, true)\",\n context.sessionId ?? '',\n );\n await database.query(\n \"SELECT set_config('smrt.permissions', $1, true)\",\n JSON.stringify(context.permissions),\n );\n await database.query(\n \"SELECT set_config('smrt.super_admin_bypass', $1, true)\",\n context.superAdminBypass ? 'true' : 'false',\n );\n await database.query(\n \"SELECT set_config('smrt.system_context', $1, true)\",\n context.systemContext ? 'true' : 'false',\n );\n}\n\nfunction isModuleNotFoundError(error: unknown): boolean {\n return (\n error instanceof Error &&\n ((error as NodeJS.ErrnoException).code === 'ERR_MODULE_NOT_FOUND' ||\n /Cannot find package '@happyvertical\\/smrt-tenancy'/.test(error.message))\n );\n}\n\nasync function runWithOptionalTenantContext<T>(\n options: SessionPermissionRuntimeOptions,\n context: SessionPermissionRuntimeContext,\n fn: () => Promise<T>,\n): Promise<T> {\n if (options.systemContext) {\n try {\n const tenancy = await import('@happyvertical/smrt-tenancy');\n return await tenancy.withSystemContext(fn);\n } catch (error) {\n if (isModuleNotFoundError(error)) {\n return await fn();\n }\n throw error;\n }\n }\n\n if (!options.enterTenantContext || !context.tenantId) {\n return await fn();\n }\n\n try {\n const tenancy = await import('@happyvertical/smrt-tenancy');\n return await tenancy.withTenant(\n {\n database: context.database,\n permissions: context.permissionSet,\n superAdminBypass: context.superAdminBypass,\n tenantId: context.tenantId,\n user: context.user ?? undefined,\n userId: context.userId ?? undefined,\n },\n fn,\n );\n } catch (error) {\n if (isModuleNotFoundError(error)) {\n return await fn();\n }\n throw error;\n }\n}\n\nexport async function withSessionPermissionContext<T>(\n options: SessionPermissionRuntimeOptions,\n fn: (context: SessionPermissionRuntimeContext) => Promise<T>,\n): Promise<T> {\n const {\n enterTenantContext: _enterTenantContext,\n postgresRls: _postgresRls,\n sessionId: _sessionId,\n sessionService: _sessionService,\n superAdminBypass: _superAdminBypass,\n systemContext: _systemContext,\n ...sessionServiceOptions\n } = options;\n const sessionService =\n options.sessionService ??\n (await SessionService.create({\n ...sessionServiceOptions,\n } as SessionServiceOptions));\n const configuredDb =\n (sessionServiceOptions as SessionServiceOptions).db ??\n (sessionServiceOptions as SessionServiceOptions).persistence;\n const session =\n options.sessionId === undefined || options.sessionId === null\n ? null\n : await sessionService.loadSessionContext(options.sessionId);\n const permissionSet = new Set(session?.permissions ?? []);\n const baseDatabase = sessionService.getDatabase() as QueryableDatabase;\n const config = getPackageConfig<{\n permissions?: { postgres?: { enabled?: boolean } };\n }>('users', {});\n const usePostgresRls =\n (options.postgresRls ?? config.permissions?.postgres?.enabled ?? false) &&\n isProbablyPostgres(configuredDb, baseDatabase);\n\n let transaction: TransactionDatabase | undefined;\n let rolledBack = false;\n if (usePostgresRls) {\n if (!baseDatabase.beginTransaction) {\n throw new Error(\n 'Postgres RLS requires a database adapter that supports beginTransaction().',\n );\n }\n transaction = await baseDatabase.beginTransaction();\n }\n\n const runtimeContext: SessionPermissionRuntimeContext = {\n database: transaction ?? baseDatabase,\n permissions: session?.permissions ?? [],\n permissionSet,\n membership: session?.membership ?? null,\n postgresRls: usePostgresRls,\n session,\n sessionId: session?.sessionId ?? null,\n superAdminBypass: options.superAdminBypass ?? false,\n systemContext: options.systemContext ?? false,\n tenantId: session?.tenantId ?? null,\n user: session?.user ?? null,\n userId: session?.user.id ?? null,\n };\n\n try {\n if (transaction) {\n await setPostgresSessionVariables(transaction, runtimeContext);\n }\n\n return await requestPermissionContextStorage.run(runtimeContext, async () =>\n runWithOptionalTenantContext(options, runtimeContext, () =>\n fn(runtimeContext),\n ),\n );\n } catch (error) {\n if (transaction) {\n const active = transaction.isActive ? transaction.isActive() : true;\n if (active) {\n rolledBack = true;\n await transaction.rollback();\n }\n }\n throw error;\n } finally {\n if (transaction && !rolledBack) {\n const active = transaction.isActive ? transaction.isActive() : true;\n if (active) {\n await transaction.commit();\n }\n }\n }\n}\n","/**\n * TerminalAuthService — device-code grant for terminal/CLI logins.\n *\n * Flow:\n * 1. CLI calls `createRequest(origin)` → user code (short, displayed) + device\n * code (long, kept secret) + verification URL.\n * 2. User opens the verification URL in a browser, signs in normally, and\n * POSTs the user code via `approveRequest({ user, tenantId, userCode })`.\n * 3. CLI polls `exchangeDeviceCode(deviceCode)`; once approved, gets back the\n * bearer session id (an opaque token usable as `Authorization: Bearer …`).\n * 4. Server-side request handlers resolve incoming bearer tokens via\n * `loadBearerSession(token)`, and revoke them via `destroyBearerSession`.\n *\n * The service is framework-agnostic: it does not set cookies, parse Request\n * objects, or render pages. SvelteKit glue lives in the package's\n * `./sveltekit` subpath.\n *\n * @packageDocumentation\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { UsersCliAuthRequestCollection } from '../collections/CliAuthRequestCollection.js';\nimport type {\n CliAuthRequestStatus,\n UsersCliAuthRequest,\n} from '../models/CliAuthRequest.js';\nimport type { User } from '../models/User.js';\nimport { type SessionContext, SessionService } from './SessionService.js';\n\n/** Default polling interval the CLI should honour while waiting for approval. */\nexport const DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS = 2;\n/** Default lifetime of a pending request (10 minutes). */\nexport const DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS = 10 * 60;\n/** Default lifetime of the session minted on approval (30 days). */\nexport const DEFAULT_CLI_SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;\n/** Default cap on consecutive failed approve attempts per user before lockout. */\nexport const DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS = 5;\n/** Default sliding window for counting failed approve attempts (5 minutes). */\nexport const DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS = 5 * 60;\n\n/**\n * Options for {@link TerminalAuthService}.\n */\nexport interface TerminalAuthServiceOptions extends SmrtClassOptions {\n /**\n * Cookie name passed through to {@link SessionService}. Should match the\n * site's normal session cookie name so the same SessionService can\n * resolve both browser cookies and CLI bearer tokens.\n */\n sessionCookieName?: string;\n /**\n * Prefix prepended to randomly generated user codes — purely for human\n * recognition (\"WG-1A2B3C4D\"). Defaults to no prefix.\n */\n userCodePrefix?: string;\n /** TTL of a pending request, in seconds. */\n requestTtlSeconds?: number;\n /** TTL of the session minted on approval, in seconds. */\n sessionTtlSeconds?: number;\n /** Polling interval hint returned to clients. */\n pollIntervalSeconds?: number;\n /**\n * Path on the site's origin where the approval page is mounted. Used to\n * build the verification URL returned to the CLI. Defaults to\n * `/terminal-login`.\n */\n verificationPath?: string;\n /** Whether the underlying SessionService should auto-extend on access. */\n sessionAutoExtend?: boolean;\n /**\n * Maximum consecutive failed approve attempts allowed per user inside the\n * sliding window before the user is locked out from approving any further\n * codes. Defaults to {@link DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS}.\n *\n * User codes are only 32 bits of entropy; without this throttle, an\n * authenticated attacker could brute-force pending codes and hijack\n * another user's CLI session by approving it themselves.\n */\n maxApproveAttempts?: number;\n /**\n * Sliding window (seconds) over which {@link maxApproveAttempts} counts.\n * Defaults to {@link DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS}.\n */\n approveAttemptWindowSeconds?: number;\n}\n\n/**\n * What `createRequest` returns to the CLI.\n */\nexport interface CliAuthStartResult {\n deviceCode: string;\n expiresAt: string;\n interval: number;\n userCode: string;\n verificationUrl: string;\n}\n\n/**\n * What `exchangeDeviceCode` returns to the polling CLI.\n */\nexport type CliAuthTokenResult =\n | { status: 'pending'; expiresAt: string; interval: number }\n | { status: 'expired' }\n | {\n status: 'approved';\n accessToken: string;\n expiresIn: number;\n tokenType: 'Bearer';\n };\n\n/**\n * Inputs for `approveRequest`. The caller is responsible for authenticating\n * the user via its existing browser session before calling this.\n */\nexport interface ApproveCliAuthRequestInput {\n userCode: string;\n user: Pick<User, 'id' | 'email'>;\n tenantId: string | null | undefined;\n ipAddress?: string;\n userAgent?: string;\n}\n\nfunction base64url(bytes: Buffer): string {\n return bytes.toString('base64url');\n}\n\nfunction hashDeviceCode(deviceCode: string): string {\n return createHash('sha256').update(deviceCode).digest('hex');\n}\n\nfunction isExpired(request: UsersCliAuthRequest): boolean {\n return new Date(request.expiresAt).getTime() <= Date.now();\n}\n\n/**\n * High-level orchestration of the terminal device-code flow.\n */\nexport class TerminalAuthService {\n private readonly options: TerminalAuthServiceOptions;\n private readonly userCodePrefix: string;\n private readonly requestTtlSeconds: number;\n private readonly sessionTtlSeconds: number;\n private readonly pollIntervalSeconds: number;\n private readonly verificationPath: string;\n private readonly maxApproveAttempts: number;\n private readonly approveAttemptWindowMs: number;\n private readonly failedApprovesByUser = new Map<\n string,\n { count: number; firstAttemptAt: number }\n >();\n private requestCollection!: UsersCliAuthRequestCollection;\n private sessionService!: SessionService;\n\n constructor(options: TerminalAuthServiceOptions) {\n this.options = options;\n // Lookups uppercase the submitted code before querying, so the stored\n // form must also be uppercase — normalize once here so consumers can\n // pass any case.\n this.userCodePrefix = (options.userCodePrefix ?? '').trim().toUpperCase();\n this.requestTtlSeconds =\n options.requestTtlSeconds ?? DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS;\n this.sessionTtlSeconds =\n options.sessionTtlSeconds ?? DEFAULT_CLI_SESSION_TTL_SECONDS;\n this.pollIntervalSeconds =\n options.pollIntervalSeconds ?? DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS;\n this.maxApproveAttempts =\n options.maxApproveAttempts ?? DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS;\n this.approveAttemptWindowMs =\n (options.approveAttemptWindowSeconds ??\n DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS) * 1000;\n const verificationPath = options.verificationPath ?? '/terminal-login';\n this.verificationPath = verificationPath.startsWith('/')\n ? verificationPath\n : `/${verificationPath}`;\n }\n\n async initialize(): Promise<void> {\n this.requestCollection =\n await UsersCliAuthRequestCollection.create(this.options);\n this.sessionService = await SessionService.create({\n ...this.options,\n autoExtend: this.options.sessionAutoExtend ?? true,\n cookieName: this.options.sessionCookieName,\n defaultTTL: this.sessionTtlSeconds,\n });\n }\n\n static async create(\n options: TerminalAuthServiceOptions,\n ): Promise<TerminalAuthService> {\n const service = new TerminalAuthService(options);\n await service.initialize();\n return service;\n }\n\n private makeUserCode(): string {\n const raw = randomBytes(6).toString('hex').toUpperCase().slice(0, 8);\n return this.userCodePrefix ? `${this.userCodePrefix}-${raw}` : raw;\n }\n\n /**\n * Generate a user code that is not currently in use by another *active*\n * (pending or approved-but-unclaimed) request. Collisions are vanishingly\n * rare (1 in 2^32 per attempt) but happen at scale; retrying keeps the\n * affected CLI from being locked out.\n */\n private async makeUniqueUserCode(maxAttempts = 5): Promise<string> {\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n const candidate = this.makeUserCode();\n const existing = await this.requestCollection.findByUserCode(candidate);\n if (!existing || existing.status === 'expired') {\n return candidate;\n }\n }\n throw new TerminalAuthError(\n 'Unable to generate a unique terminal user code; try again.',\n );\n }\n\n /**\n * Start a new request. Returns the device code the CLI keeps secret, the\n * user code the human types into the browser, and the verification URL to\n * open. The device code is stored only as a hash.\n */\n async createRequest(origin: string): Promise<CliAuthStartResult> {\n const trimmedOrigin = origin.replace(/\\/+$/u, '');\n const deviceCode = base64url(randomBytes(32));\n const userCode = await this.makeUniqueUserCode();\n const expiresAt = new Date(Date.now() + this.requestTtlSeconds * 1000);\n\n const request = await this.requestCollection.create({\n deviceCodeHash: hashDeviceCode(deviceCode),\n expiresAt,\n status: 'pending',\n userCode,\n });\n await request.save();\n\n return {\n deviceCode,\n expiresAt: expiresAt.toISOString(),\n interval: this.pollIntervalSeconds,\n userCode,\n verificationUrl: `${trimmedOrigin}${this.verificationPath}?code=${encodeURIComponent(userCode)}`,\n };\n }\n\n /**\n * Look up a request by user code. Performs lazy expiry: pending requests\n * past their TTL are flipped to `expired` and persisted.\n */\n async getRequestForUserCode(\n userCode: string,\n ): Promise<UsersCliAuthRequest | null> {\n const request = await this.requestCollection.findByUserCode(userCode);\n if (!request) return null;\n\n if (request.status === 'pending' && isExpired(request)) {\n request.status = 'expired';\n await request.save();\n }\n return request;\n }\n\n /**\n * Mark a pending request as approved and mint a bearer session bound to the\n * approving user. Idempotent: re-approving an already-approved request is a\n * no-op. Throws if the user/tenant are missing, the request is unknown, or\n * the request has expired.\n */\n async approveRequest(\n input: ApproveCliAuthRequestInput,\n ): Promise<UsersCliAuthRequest> {\n if (!input.user.id || !input.tenantId) {\n throw new TerminalAuthError(\n 'An authenticated tenant session is required.',\n );\n }\n\n this.assertApproveRateLimit(input.user.id);\n\n const request = await this.getRequestForUserCode(input.userCode);\n if (!request) {\n this.recordFailedApprove(input.user.id);\n throw new TerminalAuthError('Terminal login request not found.');\n }\n if (request.status === 'approved') {\n // Idempotent success — don't penalize a re-approval.\n return request;\n }\n if (request.status !== 'pending' || isExpired(request)) {\n request.status = 'expired';\n await request.save();\n this.recordFailedApprove(input.user.id);\n throw new TerminalAuthError('Terminal login request has expired.');\n }\n\n const sessionId = await this.sessionService.createSession(\n input.user.id,\n input.tenantId,\n {\n data: {\n approvedBy: input.user.email ?? input.user.id,\n kind: 'terminal',\n },\n ipAddress: input.ipAddress,\n ttl: this.sessionTtlSeconds,\n userAgent: input.userAgent,\n },\n );\n\n request.approvedAt = new Date();\n request.sessionId = sessionId;\n request.status = 'approved';\n request.tenantId = input.tenantId;\n request.userId = input.user.id;\n await request.save();\n this.failedApprovesByUser.delete(input.user.id);\n return request;\n }\n\n /**\n * Throw {@link TerminalAuthRateLimitError} if the user has exceeded the\n * configured failed-approve budget inside the current sliding window.\n */\n private assertApproveRateLimit(userId: string): void {\n const tracking = this.failedApprovesByUser.get(userId);\n if (!tracking) return;\n\n const elapsedMs = Date.now() - tracking.firstAttemptAt;\n if (elapsedMs >= this.approveAttemptWindowMs) {\n this.failedApprovesByUser.delete(userId);\n return;\n }\n\n if (tracking.count >= this.maxApproveAttempts) {\n const retryAfterSeconds = Math.max(\n 1,\n Math.ceil((this.approveAttemptWindowMs - elapsedMs) / 1000),\n );\n throw new TerminalAuthRateLimitError(\n 'Too many failed terminal-login attempts. Try again later.',\n retryAfterSeconds,\n );\n }\n }\n\n /** Increment the failed-approve counter for `userId`, starting the window if needed. */\n private recordFailedApprove(userId: string): void {\n const tracking = this.failedApprovesByUser.get(userId);\n if (!tracking) {\n this.failedApprovesByUser.set(userId, {\n count: 1,\n firstAttemptAt: Date.now(),\n });\n return;\n }\n tracking.count += 1;\n }\n\n /**\n * Exchange a device code (the secret the CLI keeps) for an access token\n * once the request has been approved. Returns `{ status: 'pending' }` while\n * the CLI should keep polling, and `{ status: 'expired' }` if the request\n * was never approved within its TTL.\n */\n async exchangeDeviceCode(deviceCode: string): Promise<CliAuthTokenResult> {\n const request = await this.requestCollection.findByDeviceCodeHash(\n hashDeviceCode(deviceCode),\n );\n if (!request) {\n return { status: 'expired' };\n }\n\n // Approved requests stay claimable even after the original request TTL —\n // the session has its own (longer) lifetime, and the CLI may poll just\n // after approval but after `expiresAt`. Check this before TTL expiry so\n // freshly minted sessions don't get orphaned.\n if (request.status === 'approved' && request.sessionId) {\n return {\n accessToken: request.sessionId,\n expiresIn: this.sessionTtlSeconds,\n status: 'approved',\n tokenType: 'Bearer',\n };\n }\n\n if (isExpired(request)) {\n if (request.status === 'pending') {\n request.status = 'expired';\n await request.save();\n }\n return { status: 'expired' };\n }\n\n if (request.status === 'pending') {\n return {\n expiresAt: new Date(request.expiresAt).toISOString(),\n interval: this.pollIntervalSeconds,\n status: 'pending',\n };\n }\n\n return { status: 'expired' };\n }\n\n /**\n * Resolve a bearer token issued by this service into a full session\n * context — load the user, permissions, and tenant just like the cookie\n * path does. Returns `null` if the token is unknown, expired, or revoked.\n */\n async loadBearerSession(token: string): Promise<SessionContext | null> {\n return this.sessionService.loadSessionContext(token);\n }\n\n /**\n * Revoke a bearer token (CLI logout). Returns true if a session was\n * actually revoked.\n */\n async destroyBearerSession(token: string): Promise<boolean> {\n return this.sessionService.destroySession(token);\n }\n\n /**\n * Delete expired pending requests (cleanup job).\n */\n async cleanupExpiredRequests(): Promise<number> {\n return this.requestCollection.deleteExpired();\n }\n\n /** The default polling interval clients should use. Exposed for tests. */\n get pollInterval(): number {\n return this.pollIntervalSeconds;\n }\n}\n\n/**\n * Error class for terminal auth failures the caller is expected to surface to\n * the user (vs. unexpected internal errors).\n */\nexport class TerminalAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TerminalAuthError';\n }\n}\n\n/**\n * Thrown when a user has exceeded the configured failed-approve budget. The\n * caller (SvelteKit handler, REST adapter, etc.) is expected to surface this\n * as HTTP 429 with `Retry-After: retryAfterSeconds`.\n */\nexport class TerminalAuthRateLimitError extends TerminalAuthError {\n readonly retryAfterSeconds: number;\n\n constructor(message: string, retryAfterSeconds: number) {\n super(message);\n this.name = 'TerminalAuthRateLimitError';\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\nexport type { CliAuthRequestStatus };\n"],"names":["__decorateClass","message","errors","encode","decodeBase64URL","jwk.isJWK","jwk.isSecretJWK","invalidKeyInput","jwk.isPrivateJWK","jwk.isPublicJWK","b64u","jwk","cache","field"],"mappings":"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","x_google_ignoreList":[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51]}