@happyvertical/smrt-users 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/AGENTS.md +85 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +459 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/chunks/TerminalAuthService-DoAMQ_yn.js +5118 -0
  8. package/dist/chunks/TerminalAuthService-DoAMQ_yn.js.map +1 -0
  9. package/dist/chunks/index-DkoYIvIu.js +169 -0
  10. package/dist/chunks/index-DkoYIvIu.js.map +1 -0
  11. package/dist/collections/CliAuthRequestCollection.d.ts +19 -0
  12. package/dist/collections/CliAuthRequestCollection.d.ts.map +1 -0
  13. package/dist/collections/GroupCollection.d.ts +17 -0
  14. package/dist/collections/GroupCollection.d.ts.map +1 -0
  15. package/dist/collections/GroupMemberCollection.d.ts +43 -0
  16. package/dist/collections/GroupMemberCollection.d.ts.map +1 -0
  17. package/dist/collections/GroupRoleCollection.d.ts +33 -0
  18. package/dist/collections/GroupRoleCollection.d.ts.map +1 -0
  19. package/dist/collections/MagicLinkTokenCollection.d.ts +26 -0
  20. package/dist/collections/MagicLinkTokenCollection.d.ts.map +1 -0
  21. package/dist/collections/MembershipCollection.d.ts +38 -0
  22. package/dist/collections/MembershipCollection.d.ts.map +1 -0
  23. package/dist/collections/MembershipOverrideCollection.d.ts +55 -0
  24. package/dist/collections/MembershipOverrideCollection.d.ts.map +1 -0
  25. package/dist/collections/PermissionCollection.d.ts +34 -0
  26. package/dist/collections/PermissionCollection.d.ts.map +1 -0
  27. package/dist/collections/RoleCollection.d.ts +29 -0
  28. package/dist/collections/RoleCollection.d.ts.map +1 -0
  29. package/dist/collections/RolePermissionCollection.d.ts +33 -0
  30. package/dist/collections/RolePermissionCollection.d.ts.map +1 -0
  31. package/dist/collections/SessionCollection.d.ts +82 -0
  32. package/dist/collections/SessionCollection.d.ts.map +1 -0
  33. package/dist/collections/TenantCollection.d.ts +119 -0
  34. package/dist/collections/TenantCollection.d.ts.map +1 -0
  35. package/dist/collections/TenantPermissionOverrideCollection.d.ts +111 -0
  36. package/dist/collections/TenantPermissionOverrideCollection.d.ts.map +1 -0
  37. package/dist/collections/UserCollection.d.ts +116 -0
  38. package/dist/collections/UserCollection.d.ts.map +1 -0
  39. package/dist/collections/index.d.ts +19 -0
  40. package/dist/collections/index.d.ts.map +1 -0
  41. package/dist/index.d.ts +5 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +1482 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/manifest.json +5216 -0
  46. package/dist/models/CliAuthRequest.d.ts +25 -0
  47. package/dist/models/CliAuthRequest.d.ts.map +1 -0
  48. package/dist/models/Group.d.ts +34 -0
  49. package/dist/models/Group.d.ts.map +1 -0
  50. package/dist/models/GroupMember.d.ts +29 -0
  51. package/dist/models/GroupMember.d.ts.map +1 -0
  52. package/dist/models/GroupRole.d.ts +29 -0
  53. package/dist/models/GroupRole.d.ts.map +1 -0
  54. package/dist/models/MagicLinkToken.d.ts +22 -0
  55. package/dist/models/MagicLinkToken.d.ts.map +1 -0
  56. package/dist/models/Membership.d.ts +48 -0
  57. package/dist/models/Membership.d.ts.map +1 -0
  58. package/dist/models/MembershipOverride.d.ts +50 -0
  59. package/dist/models/MembershipOverride.d.ts.map +1 -0
  60. package/dist/models/Permission.d.ts +79 -0
  61. package/dist/models/Permission.d.ts.map +1 -0
  62. package/dist/models/Role.d.ts +67 -0
  63. package/dist/models/Role.d.ts.map +1 -0
  64. package/dist/models/RolePermission.d.ts +29 -0
  65. package/dist/models/RolePermission.d.ts.map +1 -0
  66. package/dist/models/Session.d.ts +105 -0
  67. package/dist/models/Session.d.ts.map +1 -0
  68. package/dist/models/Tenant.d.ts +138 -0
  69. package/dist/models/Tenant.d.ts.map +1 -0
  70. package/dist/models/TenantPermissionOverride.d.ts +74 -0
  71. package/dist/models/TenantPermissionOverride.d.ts.map +1 -0
  72. package/dist/models/User.d.ts +72 -0
  73. package/dist/models/User.d.ts.map +1 -0
  74. package/dist/models/index.d.ts +19 -0
  75. package/dist/models/index.d.ts.map +1 -0
  76. package/dist/playground.d.ts +2 -0
  77. package/dist/playground.d.ts.map +1 -0
  78. package/dist/playground.js +139 -0
  79. package/dist/playground.js.map +1 -0
  80. package/dist/services/MagicLinkService.d.ts +84 -0
  81. package/dist/services/MagicLinkService.d.ts.map +1 -0
  82. package/dist/services/OidcLoginService.d.ts +134 -0
  83. package/dist/services/OidcLoginService.d.ts.map +1 -0
  84. package/dist/services/PermissionCatalogService.d.ts +62 -0
  85. package/dist/services/PermissionCatalogService.d.ts.map +1 -0
  86. package/dist/services/PermissionResolver.d.ts +150 -0
  87. package/dist/services/PermissionResolver.d.ts.map +1 -0
  88. package/dist/services/PostgresPermissionPolicies.d.ts +29 -0
  89. package/dist/services/PostgresPermissionPolicies.d.ts.map +1 -0
  90. package/dist/services/SessionPermissionContext.d.ts +43 -0
  91. package/dist/services/SessionPermissionContext.d.ts.map +1 -0
  92. package/dist/services/SessionService.d.ts +139 -0
  93. package/dist/services/SessionService.d.ts.map +1 -0
  94. package/dist/services/TenantService.d.ts +135 -0
  95. package/dist/services/TenantService.d.ts.map +1 -0
  96. package/dist/services/TerminalAuthService.d.ts +189 -0
  97. package/dist/services/TerminalAuthService.d.ts.map +1 -0
  98. package/dist/services/index.d.ts +14 -0
  99. package/dist/services/index.d.ts.map +1 -0
  100. package/dist/smrt-knowledge.json +2744 -0
  101. package/dist/svelte/components/InviteUserModal.svelte +351 -0
  102. package/dist/svelte/components/InviteUserModal.svelte.d.ts +17 -0
  103. package/dist/svelte/components/InviteUserModal.svelte.d.ts.map +1 -0
  104. package/dist/svelte/components/UserAvatar.svelte +105 -0
  105. package/dist/svelte/components/UserAvatar.svelte.d.ts +10 -0
  106. package/dist/svelte/components/UserAvatar.svelte.d.ts.map +1 -0
  107. package/dist/svelte/components/UserCard.svelte +179 -0
  108. package/dist/svelte/components/UserCard.svelte.d.ts +18 -0
  109. package/dist/svelte/components/UserCard.svelte.d.ts.map +1 -0
  110. package/dist/svelte/components/UserForm.svelte +194 -0
  111. package/dist/svelte/components/UserForm.svelte.d.ts +18 -0
  112. package/dist/svelte/components/UserForm.svelte.d.ts.map +1 -0
  113. package/dist/svelte/components/UserList.svelte +107 -0
  114. package/dist/svelte/components/UserList.svelte.d.ts +20 -0
  115. package/dist/svelte/components/UserList.svelte.d.ts.map +1 -0
  116. package/dist/svelte/components/UserMenu.svelte +326 -0
  117. package/dist/svelte/components/UserMenu.svelte.d.ts +33 -0
  118. package/dist/svelte/components/UserMenu.svelte.d.ts.map +1 -0
  119. package/dist/svelte/components/__tests__/InviteUserModal.test.js +54 -0
  120. package/dist/svelte/components/__tests__/UserAvatar.test.js +31 -0
  121. package/dist/svelte/components/__tests__/UserCard.test.js +39 -0
  122. package/dist/svelte/components/__tests__/UserForm.test.js +50 -0
  123. package/dist/svelte/components/__tests__/UserList.test.js +48 -0
  124. package/dist/svelte/components/__tests__/UserMenu.test.js +38 -0
  125. package/dist/svelte/i18n.d.ts +15 -0
  126. package/dist/svelte/i18n.d.ts.map +1 -0
  127. package/dist/svelte/i18n.js +15 -0
  128. package/dist/svelte/index.d.ts +23 -0
  129. package/dist/svelte/index.d.ts.map +1 -0
  130. package/dist/svelte/index.js +27 -0
  131. package/dist/svelte/playground.d.ts +151 -0
  132. package/dist/svelte/playground.d.ts.map +1 -0
  133. package/dist/svelte/playground.js +134 -0
  134. package/dist/sveltekit/index.d.ts +379 -0
  135. package/dist/sveltekit/index.d.ts.map +1 -0
  136. package/dist/sveltekit/resource-list-handler.d.ts +127 -0
  137. package/dist/sveltekit/resource-list-handler.d.ts.map +1 -0
  138. package/dist/sveltekit/types.d.ts +31 -0
  139. package/dist/sveltekit/types.d.ts.map +1 -0
  140. package/dist/sveltekit.d.ts +2 -0
  141. package/dist/sveltekit.d.ts.map +1 -0
  142. package/dist/sveltekit.js +978 -0
  143. package/dist/sveltekit.js.map +1 -0
  144. package/dist/types/index.d.ts +61 -0
  145. package/dist/types/index.d.ts.map +1 -0
  146. package/dist/ui.d.ts +10 -0
  147. package/dist/ui.d.ts.map +1 -0
  148. package/dist/ui.js +75 -0
  149. package/dist/ui.js.map +1 -0
  150. package/package.json +97 -0
@@ -0,0 +1,135 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { Membership } from '../models/Membership.js';
3
+ import { Tenant } from '../models/Tenant.js';
4
+ import { TenantPolicy } from '../types/index.js';
5
+ /**
6
+ * Result of tenant creation with ownership
7
+ */
8
+ export interface TenantWithOwnershipResult {
9
+ tenant: Tenant;
10
+ membership: Membership;
11
+ }
12
+ /**
13
+ * Result of ensureTenantForUser
14
+ */
15
+ export interface EnsureTenantResult {
16
+ /** The tenant (null if flexible mode and no existing tenant) */
17
+ tenant: Tenant | null;
18
+ /** The membership (null if no tenant) */
19
+ membership: Membership | null;
20
+ /** Whether a new tenant was created */
21
+ created: boolean;
22
+ }
23
+ /**
24
+ * TenantService manages tenant creation with configurable policies.
25
+ *
26
+ * Policies:
27
+ * - `flexible`: No tenant created on signup, user can have zero tenants
28
+ * - `personal`: Auto-create personal tenant on first login, can delete all
29
+ * - `required`: Auto-create personal tenant, must keep at least one
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const tenantService = new TenantService(options, {
34
+ * mode: 'personal',
35
+ * maxTenants: 5,
36
+ * defaultName: 'My Workspace',
37
+ * });
38
+ * await tenantService.initialize();
39
+ *
40
+ * // During OIDC login
41
+ * const { tenant, membership, created } = await tenantService.ensureTenantForUser(
42
+ * user.id,
43
+ * { email: user.email, name: user.name }
44
+ * );
45
+ *
46
+ * // Creating additional tenants
47
+ * if (await tenantService.canCreateTenant(user.id)) {
48
+ * const { tenant } = await tenantService.createTenantWithOwnership(
49
+ * user.id,
50
+ * 'New Organization'
51
+ * );
52
+ * }
53
+ * ```
54
+ */
55
+ export declare class TenantService {
56
+ private options;
57
+ private policy;
58
+ private tenantCollection;
59
+ private membershipCollection;
60
+ private roleCollection;
61
+ constructor(options: SmrtClassOptions, policy?: TenantPolicy);
62
+ /**
63
+ * Initialize collections
64
+ */
65
+ initialize(): Promise<void>;
66
+ /**
67
+ * Get the current policy
68
+ */
69
+ getPolicy(): TenantPolicy;
70
+ /**
71
+ * Create a tenant and make the user the owner
72
+ *
73
+ * @param userId - The user to make owner
74
+ * @param name - Tenant name
75
+ * @param options - Optional slug override
76
+ * @returns The created tenant and membership
77
+ */
78
+ createTenantWithOwnership(userId: string, name: string, options?: {
79
+ slug?: string;
80
+ }): Promise<TenantWithOwnershipResult>;
81
+ /**
82
+ * Check if a user can create a new tenant
83
+ *
84
+ * Returns false if maxTenants limit is reached (0 = unlimited)
85
+ */
86
+ canCreateTenant(userId: string): Promise<boolean>;
87
+ /**
88
+ * Get a specific error message explaining why a tenant cannot be deleted.
89
+ *
90
+ * @returns Error message if deletion is not allowed, or null if allowed.
91
+ */
92
+ private getDeleteTenantError;
93
+ /**
94
+ * Check if a user can delete a specific tenant
95
+ *
96
+ * Returns false if:
97
+ * - User is not an active member
98
+ * - User is not the owner
99
+ * - Policy is 'required' and this is the last tenant
100
+ */
101
+ canDeleteTenant(userId: string, tenantId: string): Promise<boolean>;
102
+ /**
103
+ * Delete a tenant
104
+ *
105
+ * Note: This does not cascade delete related records (memberships, etc.).
106
+ * The caller should handle cleanup of related data if needed.
107
+ *
108
+ * @throws Error if user cannot delete the tenant (with specific reason)
109
+ */
110
+ deleteTenant(userId: string, tenantId: string): Promise<void>;
111
+ /**
112
+ * Ensure a tenant exists for the user based on policy
113
+ *
114
+ * Called during OIDC login to apply tenant policy:
115
+ * - `flexible`: Returns first existing tenant or null (no auto-create)
116
+ * - `personal`/`required`: Creates default tenant if none exists
117
+ *
118
+ * @param userId - The user ID
119
+ * @param userInfo - User info for naming the auto-created tenant
120
+ * @returns Tenant and membership (may be null in flexible mode)
121
+ */
122
+ ensureTenantForUser(userId: string, userInfo: {
123
+ email?: string;
124
+ name?: string;
125
+ }): Promise<EnsureTenantResult>;
126
+ /**
127
+ * Get all tenants for a user (where they are owner)
128
+ */
129
+ getOwnedTenants(userId: string): Promise<Tenant[]>;
130
+ /**
131
+ * Static factory method
132
+ */
133
+ static create(options: SmrtClassOptions, policy?: TenantPolicy): Promise<TenantService>;
134
+ }
135
+ //# sourceMappingURL=TenantService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantService.d.ts","sourceRoot":"","sources":["../../src/services/TenantService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yCAAyC;IACzC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,oBAAoB,CAAwB;IACpD,OAAO,CAAC,cAAc,CAAkB;gBAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,YAAY;IAK5D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;OAEG;IACH,SAAS,IAAI,YAAY;IAIzB;;;;;;;OAOG;IACG,yBAAyB,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1B,OAAO,CAAC,yBAAyB,CAAC;IAmCrC;;;;OAIG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBvD;;;;OAIG;YACW,oBAAoB;IAwClC;;;;;;;OAOG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE;;;;;;;OAOG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE;;;;;;;;;;OAUG;IACG,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,kBAAkB,CAAC;IA+C9B;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAuBxD;;OAEG;WACU,MAAM,CACjB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;CAK1B"}
@@ -0,0 +1,189 @@
1
+ import { SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { CliAuthRequestStatus, UsersCliAuthRequest } from '../models/CliAuthRequest.js';
3
+ import { User } from '../models/User.js';
4
+ import { SessionContext } from './SessionService.js';
5
+ /** Default polling interval the CLI should honour while waiting for approval. */
6
+ export declare const DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS = 2;
7
+ /** Default lifetime of a pending request (10 minutes). */
8
+ export declare const DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS: number;
9
+ /** Default lifetime of the session minted on approval (30 days). */
10
+ export declare const DEFAULT_CLI_SESSION_TTL_SECONDS: number;
11
+ /** Default cap on consecutive failed approve attempts per user before lockout. */
12
+ export declare const DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS = 5;
13
+ /** Default sliding window for counting failed approve attempts (5 minutes). */
14
+ export declare const DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS: number;
15
+ /**
16
+ * Options for {@link TerminalAuthService}.
17
+ */
18
+ export interface TerminalAuthServiceOptions extends SmrtClassOptions {
19
+ /**
20
+ * Cookie name passed through to {@link SessionService}. Should match the
21
+ * site's normal session cookie name so the same SessionService can
22
+ * resolve both browser cookies and CLI bearer tokens.
23
+ */
24
+ sessionCookieName?: string;
25
+ /**
26
+ * Prefix prepended to randomly generated user codes — purely for human
27
+ * recognition ("WG-1A2B3C4D"). Defaults to no prefix.
28
+ */
29
+ userCodePrefix?: string;
30
+ /** TTL of a pending request, in seconds. */
31
+ requestTtlSeconds?: number;
32
+ /** TTL of the session minted on approval, in seconds. */
33
+ sessionTtlSeconds?: number;
34
+ /** Polling interval hint returned to clients. */
35
+ pollIntervalSeconds?: number;
36
+ /**
37
+ * Path on the site's origin where the approval page is mounted. Used to
38
+ * build the verification URL returned to the CLI. Defaults to
39
+ * `/terminal-login`.
40
+ */
41
+ verificationPath?: string;
42
+ /** Whether the underlying SessionService should auto-extend on access. */
43
+ sessionAutoExtend?: boolean;
44
+ /**
45
+ * Maximum consecutive failed approve attempts allowed per user inside the
46
+ * sliding window before the user is locked out from approving any further
47
+ * codes. Defaults to {@link DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS}.
48
+ *
49
+ * User codes are only 32 bits of entropy; without this throttle, an
50
+ * authenticated attacker could brute-force pending codes and hijack
51
+ * another user's CLI session by approving it themselves.
52
+ */
53
+ maxApproveAttempts?: number;
54
+ /**
55
+ * Sliding window (seconds) over which {@link maxApproveAttempts} counts.
56
+ * Defaults to {@link DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS}.
57
+ */
58
+ approveAttemptWindowSeconds?: number;
59
+ }
60
+ /**
61
+ * What `createRequest` returns to the CLI.
62
+ */
63
+ export interface CliAuthStartResult {
64
+ deviceCode: string;
65
+ expiresAt: string;
66
+ interval: number;
67
+ userCode: string;
68
+ verificationUrl: string;
69
+ }
70
+ /**
71
+ * What `exchangeDeviceCode` returns to the polling CLI.
72
+ */
73
+ export type CliAuthTokenResult = {
74
+ status: 'pending';
75
+ expiresAt: string;
76
+ interval: number;
77
+ } | {
78
+ status: 'expired';
79
+ } | {
80
+ status: 'approved';
81
+ accessToken: string;
82
+ expiresIn: number;
83
+ tokenType: 'Bearer';
84
+ };
85
+ /**
86
+ * Inputs for `approveRequest`. The caller is responsible for authenticating
87
+ * the user via its existing browser session before calling this.
88
+ */
89
+ export interface ApproveCliAuthRequestInput {
90
+ userCode: string;
91
+ user: Pick<User, 'id' | 'email'>;
92
+ tenantId: string | null | undefined;
93
+ ipAddress?: string;
94
+ userAgent?: string;
95
+ }
96
+ /**
97
+ * High-level orchestration of the terminal device-code flow.
98
+ */
99
+ export declare class TerminalAuthService {
100
+ private readonly options;
101
+ private readonly userCodePrefix;
102
+ private readonly requestTtlSeconds;
103
+ private readonly sessionTtlSeconds;
104
+ private readonly pollIntervalSeconds;
105
+ private readonly verificationPath;
106
+ private readonly maxApproveAttempts;
107
+ private readonly approveAttemptWindowMs;
108
+ private readonly failedApprovesByUser;
109
+ private requestCollection;
110
+ private sessionService;
111
+ constructor(options: TerminalAuthServiceOptions);
112
+ initialize(): Promise<void>;
113
+ static create(options: TerminalAuthServiceOptions): Promise<TerminalAuthService>;
114
+ private makeUserCode;
115
+ /**
116
+ * Generate a user code that is not currently in use by another *active*
117
+ * (pending or approved-but-unclaimed) request. Collisions are vanishingly
118
+ * rare (1 in 2^32 per attempt) but happen at scale; retrying keeps the
119
+ * affected CLI from being locked out.
120
+ */
121
+ private makeUniqueUserCode;
122
+ /**
123
+ * Start a new request. Returns the device code the CLI keeps secret, the
124
+ * user code the human types into the browser, and the verification URL to
125
+ * open. The device code is stored only as a hash.
126
+ */
127
+ createRequest(origin: string): Promise<CliAuthStartResult>;
128
+ /**
129
+ * Look up a request by user code. Performs lazy expiry: pending requests
130
+ * past their TTL are flipped to `expired` and persisted.
131
+ */
132
+ getRequestForUserCode(userCode: string): Promise<UsersCliAuthRequest | null>;
133
+ /**
134
+ * Mark a pending request as approved and mint a bearer session bound to the
135
+ * approving user. Idempotent: re-approving an already-approved request is a
136
+ * no-op. Throws if the user/tenant are missing, the request is unknown, or
137
+ * the request has expired.
138
+ */
139
+ approveRequest(input: ApproveCliAuthRequestInput): Promise<UsersCliAuthRequest>;
140
+ /**
141
+ * Throw {@link TerminalAuthRateLimitError} if the user has exceeded the
142
+ * configured failed-approve budget inside the current sliding window.
143
+ */
144
+ private assertApproveRateLimit;
145
+ /** Increment the failed-approve counter for `userId`, starting the window if needed. */
146
+ private recordFailedApprove;
147
+ /**
148
+ * Exchange a device code (the secret the CLI keeps) for an access token
149
+ * once the request has been approved. Returns `{ status: 'pending' }` while
150
+ * the CLI should keep polling, and `{ status: 'expired' }` if the request
151
+ * was never approved within its TTL.
152
+ */
153
+ exchangeDeviceCode(deviceCode: string): Promise<CliAuthTokenResult>;
154
+ /**
155
+ * Resolve a bearer token issued by this service into a full session
156
+ * context — load the user, permissions, and tenant just like the cookie
157
+ * path does. Returns `null` if the token is unknown, expired, or revoked.
158
+ */
159
+ loadBearerSession(token: string): Promise<SessionContext | null>;
160
+ /**
161
+ * Revoke a bearer token (CLI logout). Returns true if a session was
162
+ * actually revoked.
163
+ */
164
+ destroyBearerSession(token: string): Promise<boolean>;
165
+ /**
166
+ * Delete expired pending requests (cleanup job).
167
+ */
168
+ cleanupExpiredRequests(): Promise<number>;
169
+ /** The default polling interval clients should use. Exposed for tests. */
170
+ get pollInterval(): number;
171
+ }
172
+ /**
173
+ * Error class for terminal auth failures the caller is expected to surface to
174
+ * the user (vs. unexpected internal errors).
175
+ */
176
+ export declare class TerminalAuthError extends Error {
177
+ constructor(message: string);
178
+ }
179
+ /**
180
+ * Thrown when a user has exceeded the configured failed-approve budget. The
181
+ * caller (SvelteKit handler, REST adapter, etc.) is expected to surface this
182
+ * as HTTP 429 with `Retry-After: retryAfterSeconds`.
183
+ */
184
+ export declare class TerminalAuthRateLimitError extends TerminalAuthError {
185
+ readonly retryAfterSeconds: number;
186
+ constructor(message: string, retryAfterSeconds: number);
187
+ }
188
+ export type { CliAuthRequestStatus };
189
+ //# sourceMappingURL=TerminalAuthService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerminalAuthService.d.ts","sourceRoot":"","sources":["../../src/services/TerminalAuthService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AAE1E,iFAAiF;AACjF,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,0DAA0D;AAC1D,eAAO,MAAM,oCAAoC,QAAU,CAAC;AAC5D,oEAAoE;AACpE,eAAO,MAAM,+BAA+B,QAAoB,CAAC;AACjE,kFAAkF;AAClF,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,+EAA+E;AAC/E,eAAO,MAAM,+CAA+C,QAAS,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,gBAAgB;IAClE;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IACE,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEN;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAcD;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAGjC;IACJ,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,cAAc,CAAkB;gBAE5B,OAAO,EAAE,0BAA0B;IAuBzC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;WAYpB,MAAM,CACjB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC;IAM/B,OAAO,CAAC,YAAY;IAKpB;;;;;OAKG;YACW,kBAAkB;IAahC;;;;OAIG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBhE;;;OAGG;IACG,qBAAqB,CACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAWtC;;;;;OAKG;IACG,cAAc,CAClB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,mBAAmB,CAAC;IAiD/B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAsB9B,wFAAwF;IACxF,OAAO,CAAC,mBAAmB;IAY3B;;;;;OAKG;IACG,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAwCzE;;;;OAIG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAItE;;;OAGG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3D;;OAEG;IACG,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAI/C,0EAA0E;IAC1E,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,iBAAiB;IAC/D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;CAKvD;AAED,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Service exports for smrt-users
3
+ * @packageDocumentation
4
+ */
5
+ export { MagicLinkError, type MagicLinkResult, MagicLinkService, type MagicLinkServiceOptions, type MagicLinkVerifyResult, } from './MagicLinkService.js';
6
+ export { type CreateAuthorizationUrlOptions, decodeOidcTransaction, encodeOidcTransaction, getUsersOidcConfig, type OidcCallbackResult, OidcLoginError, type OidcLoginResult, OidcLoginService, type OidcLoginServiceOptions, type OidcProviderConfig, type OidcProviderKind, type OidcProviderMetadata, type OidcProviderResolution, type OidcProviderResolutionOptions, type OidcTokenEndpointAuthMethod, type OidcTokenSet, type OidcTransaction, type ResolvedOidcProviderConfig, resolveOidcProviderConfig, type UsersOidcConfig, } from './OidcLoginService.js';
7
+ export { type PermissionCatalog, PermissionCatalogService, type PermissionCatalogSource, type PermissionCatalogSyncResult, type PermissionDefinition, type PostgresPermissionAction, type PostgresPermissionBinding, registerPermissionDefinitions, syncPermissionCatalog, type UsersConfig, } from './PermissionCatalogService.js';
8
+ export { type PermissionResolutionOptions, type PermissionResolutionResult, PermissionResolver, type TenantPermissionInheritanceResult, } from './PermissionResolver.js';
9
+ export { applyPostgresPermissionPolicies, type GeneratePostgresPermissionSqlResult, generatePostgresPermissionSql, type PostgresPermissionPolicyReportItem, type PostgresPermissionPolicyTarget, } from './PostgresPermissionPolicies.js';
10
+ export { getCurrentSessionPermissionContext, getRequestScopedDatabase, type SessionPermissionRuntimeContext, type SessionPermissionRuntimeOptions, withSessionPermissionContext, } from './SessionPermissionContext.js';
11
+ export { type SessionContext, SessionService, type SessionServiceOptions, } from './SessionService.js';
12
+ export { type EnsureTenantResult, TenantService, type TenantWithOwnershipResult, } from './TenantService.js';
13
+ export { type ApproveCliAuthRequestInput, type CliAuthStartResult, type CliAuthTokenResult, DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS, DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS, DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, DEFAULT_CLI_SESSION_TTL_SECONDS, TerminalAuthError, TerminalAuthRateLimitError, TerminalAuthService, type TerminalAuthServiceOptions, } from './TerminalAuthService.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,6BAA6B,EAClC,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,kBAAkB,EAClB,KAAK,iCAAiC,GACvC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,+BAA+B,EAC/B,KAAK,mCAAmC,EACxC,6BAA6B,EAC7B,KAAK,kCAAkC,EACvC,KAAK,8BAA8B,GACpC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,kCAAkC,EAClC,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,+BAA+B,EACpC,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,kBAAkB,EACvB,aAAa,EACb,KAAK,yBAAyB,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,+CAA+C,EAC/C,qCAAqC,EACrC,sCAAsC,EACtC,oCAAoC,EACpC,+BAA+B,EAC/B,iBAAiB,EACjB,0BAA0B,EAC1B,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}