@spfn/auth 0.1.0-alpha.87 → 0.2.0-beta.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 (151) hide show
  1. package/README.md +1385 -1199
  2. package/dist/config.d.ts +405 -0
  3. package/dist/config.js +240 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/dto-81uR9gzF.d.ts +630 -0
  6. package/dist/errors.d.ts +196 -0
  7. package/dist/errors.js +173 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/index.d.ts +273 -14
  10. package/dist/index.js +511 -6665
  11. package/dist/index.js.map +1 -1
  12. package/dist/nextjs/api.js +345 -0
  13. package/dist/nextjs/api.js.map +1 -0
  14. package/dist/{adapters/nextjs → nextjs}/server.d.ts +47 -65
  15. package/dist/nextjs/server.js +179 -0
  16. package/dist/nextjs/server.js.map +1 -0
  17. package/dist/server.d.ts +4328 -529
  18. package/dist/server.js +7841 -1247
  19. package/dist/server.js.map +1 -1
  20. package/migrations/{0000_familiar_firebrand.sql → 0000_mysterious_colossus.sql} +53 -23
  21. package/migrations/meta/0000_snapshot.json +281 -46
  22. package/migrations/meta/_journal.json +2 -2
  23. package/package.json +33 -33
  24. package/dist/adapters/nextjs/api.d.ts +0 -446
  25. package/dist/adapters/nextjs/api.js +0 -3279
  26. package/dist/adapters/nextjs/api.js.map +0 -1
  27. package/dist/adapters/nextjs/server.js +0 -3645
  28. package/dist/adapters/nextjs/server.js.map +0 -1
  29. package/dist/lib/api/auth-codes-verify.d.ts +0 -37
  30. package/dist/lib/api/auth-codes-verify.js +0 -2949
  31. package/dist/lib/api/auth-codes-verify.js.map +0 -1
  32. package/dist/lib/api/auth-codes.d.ts +0 -37
  33. package/dist/lib/api/auth-codes.js +0 -2949
  34. package/dist/lib/api/auth-codes.js.map +0 -1
  35. package/dist/lib/api/auth-exists.d.ts +0 -38
  36. package/dist/lib/api/auth-exists.js +0 -2949
  37. package/dist/lib/api/auth-exists.js.map +0 -1
  38. package/dist/lib/api/auth-invitations-accept.d.ts +0 -38
  39. package/dist/lib/api/auth-invitations-accept.js +0 -2883
  40. package/dist/lib/api/auth-invitations-accept.js.map +0 -1
  41. package/dist/lib/api/auth-invitations-cancel.d.ts +0 -37
  42. package/dist/lib/api/auth-invitations-cancel.js +0 -2883
  43. package/dist/lib/api/auth-invitations-cancel.js.map +0 -1
  44. package/dist/lib/api/auth-invitations-delete.d.ts +0 -36
  45. package/dist/lib/api/auth-invitations-delete.js +0 -2883
  46. package/dist/lib/api/auth-invitations-delete.js.map +0 -1
  47. package/dist/lib/api/auth-invitations-resend.d.ts +0 -37
  48. package/dist/lib/api/auth-invitations-resend.js +0 -2883
  49. package/dist/lib/api/auth-invitations-resend.js.map +0 -1
  50. package/dist/lib/api/auth-invitations.d.ts +0 -109
  51. package/dist/lib/api/auth-invitations.js +0 -2887
  52. package/dist/lib/api/auth-invitations.js.map +0 -1
  53. package/dist/lib/api/auth-keys-rotate.d.ts +0 -37
  54. package/dist/lib/api/auth-keys-rotate.js +0 -2949
  55. package/dist/lib/api/auth-keys-rotate.js.map +0 -1
  56. package/dist/lib/api/auth-login.d.ts +0 -39
  57. package/dist/lib/api/auth-login.js +0 -2949
  58. package/dist/lib/api/auth-login.js.map +0 -1
  59. package/dist/lib/api/auth-logout.d.ts +0 -36
  60. package/dist/lib/api/auth-logout.js +0 -2949
  61. package/dist/lib/api/auth-logout.js.map +0 -1
  62. package/dist/lib/api/auth-me.d.ts +0 -50
  63. package/dist/lib/api/auth-me.js +0 -2949
  64. package/dist/lib/api/auth-me.js.map +0 -1
  65. package/dist/lib/api/auth-password.d.ts +0 -36
  66. package/dist/lib/api/auth-password.js +0 -2949
  67. package/dist/lib/api/auth-password.js.map +0 -1
  68. package/dist/lib/api/auth-register.d.ts +0 -38
  69. package/dist/lib/api/auth-register.js +0 -2949
  70. package/dist/lib/api/auth-register.js.map +0 -1
  71. package/dist/lib/api/index.d.ts +0 -356
  72. package/dist/lib/api/index.js +0 -3261
  73. package/dist/lib/api/index.js.map +0 -1
  74. package/dist/lib/config.d.ts +0 -70
  75. package/dist/lib/config.js +0 -64
  76. package/dist/lib/config.js.map +0 -1
  77. package/dist/lib/contracts/auth.d.ts +0 -302
  78. package/dist/lib/contracts/auth.js +0 -2951
  79. package/dist/lib/contracts/auth.js.map +0 -1
  80. package/dist/lib/contracts/index.d.ts +0 -3
  81. package/dist/lib/contracts/index.js +0 -3190
  82. package/dist/lib/contracts/index.js.map +0 -1
  83. package/dist/lib/contracts/invitation.d.ts +0 -243
  84. package/dist/lib/contracts/invitation.js +0 -2883
  85. package/dist/lib/contracts/invitation.js.map +0 -1
  86. package/dist/lib/crypto.d.ts +0 -76
  87. package/dist/lib/crypto.js +0 -127
  88. package/dist/lib/crypto.js.map +0 -1
  89. package/dist/lib/index.d.ts +0 -4
  90. package/dist/lib/index.js +0 -313
  91. package/dist/lib/index.js.map +0 -1
  92. package/dist/lib/session.d.ts +0 -68
  93. package/dist/lib/session.js +0 -126
  94. package/dist/lib/session.js.map +0 -1
  95. package/dist/lib/types/api.d.ts +0 -45
  96. package/dist/lib/types/api.js +0 -1
  97. package/dist/lib/types/api.js.map +0 -1
  98. package/dist/lib/types/index.d.ts +0 -3
  99. package/dist/lib/types/index.js +0 -2647
  100. package/dist/lib/types/index.js.map +0 -1
  101. package/dist/lib/types/schemas.d.ts +0 -45
  102. package/dist/lib/types/schemas.js +0 -2647
  103. package/dist/lib/types/schemas.js.map +0 -1
  104. package/dist/lib.js +0 -1
  105. package/dist/lib.js.map +0 -1
  106. package/dist/plugin.d.ts +0 -12
  107. package/dist/plugin.js +0 -9083
  108. package/dist/plugin.js.map +0 -1
  109. package/dist/server/entities/index.d.ts +0 -11
  110. package/dist/server/entities/index.js +0 -395
  111. package/dist/server/entities/index.js.map +0 -1
  112. package/dist/server/entities/invitations.d.ts +0 -241
  113. package/dist/server/entities/invitations.js +0 -184
  114. package/dist/server/entities/invitations.js.map +0 -1
  115. package/dist/server/entities/permissions.d.ts +0 -196
  116. package/dist/server/entities/permissions.js +0 -49
  117. package/dist/server/entities/permissions.js.map +0 -1
  118. package/dist/server/entities/role-permissions.d.ts +0 -107
  119. package/dist/server/entities/role-permissions.js +0 -115
  120. package/dist/server/entities/role-permissions.js.map +0 -1
  121. package/dist/server/entities/roles.d.ts +0 -196
  122. package/dist/server/entities/roles.js +0 -50
  123. package/dist/server/entities/roles.js.map +0 -1
  124. package/dist/server/entities/schema.d.ts +0 -14
  125. package/dist/server/entities/schema.js +0 -7
  126. package/dist/server/entities/schema.js.map +0 -1
  127. package/dist/server/entities/user-permissions.d.ts +0 -163
  128. package/dist/server/entities/user-permissions.js +0 -193
  129. package/dist/server/entities/user-permissions.js.map +0 -1
  130. package/dist/server/entities/user-public-keys.d.ts +0 -227
  131. package/dist/server/entities/user-public-keys.js +0 -156
  132. package/dist/server/entities/user-public-keys.js.map +0 -1
  133. package/dist/server/entities/user-social-accounts.d.ts +0 -189
  134. package/dist/server/entities/user-social-accounts.js +0 -149
  135. package/dist/server/entities/user-social-accounts.js.map +0 -1
  136. package/dist/server/entities/users.d.ts +0 -235
  137. package/dist/server/entities/users.js +0 -117
  138. package/dist/server/entities/users.js.map +0 -1
  139. package/dist/server/entities/verification-codes.d.ts +0 -191
  140. package/dist/server/entities/verification-codes.js +0 -49
  141. package/dist/server/entities/verification-codes.js.map +0 -1
  142. package/dist/server/routes/auth/index.d.ts +0 -10
  143. package/dist/server/routes/auth/index.js +0 -4460
  144. package/dist/server/routes/auth/index.js.map +0 -1
  145. package/dist/server/routes/index.d.ts +0 -6
  146. package/dist/server/routes/index.js +0 -6584
  147. package/dist/server/routes/index.js.map +0 -1
  148. package/dist/server/routes/invitations/index.d.ts +0 -10
  149. package/dist/server/routes/invitations/index.js +0 -4395
  150. package/dist/server/routes/invitations/index.js.map +0 -1
  151. /package/dist/{lib.d.ts → nextjs/api.d.ts} +0 -0
@@ -1,241 +0,0 @@
1
- import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
-
3
- /**
4
- * @spfn/auth - User Invitations Entity
5
- *
6
- * Invitation system for invite-only user registration
7
- *
8
- * Features:
9
- * - Email-based invitations with unique tokens
10
- * - Role assignment at invitation time
11
- * - Expiration and status tracking
12
- * - Audit trail (who invited whom, when accepted)
13
- * - Metadata support for custom data
14
- */
15
- declare const invitations: drizzle_orm_pg_core.PgTableWithColumns<{
16
- name: "user_invitations";
17
- schema: string;
18
- columns: {
19
- createdAt: drizzle_orm_pg_core.PgColumn<{
20
- name: "created_at";
21
- tableName: "user_invitations";
22
- dataType: "date";
23
- columnType: "PgTimestamp";
24
- data: Date;
25
- driverParam: string;
26
- notNull: true;
27
- hasDefault: true;
28
- isPrimaryKey: false;
29
- isAutoincrement: false;
30
- hasRuntimeDefault: false;
31
- enumValues: undefined;
32
- baseColumn: never;
33
- identity: undefined;
34
- generated: undefined;
35
- }, {}, {}>;
36
- updatedAt: drizzle_orm_pg_core.PgColumn<{
37
- name: "updated_at";
38
- tableName: "user_invitations";
39
- dataType: "date";
40
- columnType: "PgTimestamp";
41
- data: Date;
42
- driverParam: string;
43
- notNull: true;
44
- hasDefault: true;
45
- isPrimaryKey: false;
46
- isAutoincrement: false;
47
- hasRuntimeDefault: false;
48
- enumValues: undefined;
49
- baseColumn: never;
50
- identity: undefined;
51
- generated: undefined;
52
- }, {}, {}>;
53
- id: drizzle_orm_pg_core.PgColumn<{
54
- name: "id";
55
- tableName: "user_invitations";
56
- dataType: "number";
57
- columnType: "PgBigSerial53";
58
- data: number;
59
- driverParam: number;
60
- notNull: true;
61
- hasDefault: true;
62
- isPrimaryKey: true;
63
- isAutoincrement: false;
64
- hasRuntimeDefault: false;
65
- enumValues: undefined;
66
- baseColumn: never;
67
- identity: undefined;
68
- generated: undefined;
69
- }, {}, {}>;
70
- email: drizzle_orm_pg_core.PgColumn<{
71
- name: "email";
72
- tableName: "user_invitations";
73
- dataType: "string";
74
- columnType: "PgText";
75
- data: string;
76
- driverParam: string;
77
- notNull: true;
78
- hasDefault: false;
79
- isPrimaryKey: false;
80
- isAutoincrement: false;
81
- hasRuntimeDefault: false;
82
- enumValues: [string, ...string[]];
83
- baseColumn: never;
84
- identity: undefined;
85
- generated: undefined;
86
- }, {}, {}>;
87
- token: drizzle_orm_pg_core.PgColumn<{
88
- name: "token";
89
- tableName: "user_invitations";
90
- dataType: "string";
91
- columnType: "PgText";
92
- data: string;
93
- driverParam: string;
94
- notNull: true;
95
- hasDefault: false;
96
- isPrimaryKey: false;
97
- isAutoincrement: false;
98
- hasRuntimeDefault: false;
99
- enumValues: [string, ...string[]];
100
- baseColumn: never;
101
- identity: undefined;
102
- generated: undefined;
103
- }, {}, {}>;
104
- roleId: drizzle_orm_pg_core.PgColumn<{
105
- name: "role_id";
106
- tableName: "user_invitations";
107
- dataType: "number";
108
- columnType: "PgBigInt53";
109
- data: number;
110
- driverParam: string | number;
111
- notNull: true;
112
- hasDefault: false;
113
- isPrimaryKey: false;
114
- isAutoincrement: false;
115
- hasRuntimeDefault: false;
116
- enumValues: undefined;
117
- baseColumn: never;
118
- identity: undefined;
119
- generated: undefined;
120
- }, {}, {}>;
121
- invitedBy: drizzle_orm_pg_core.PgColumn<{
122
- name: "invited_by";
123
- tableName: "user_invitations";
124
- dataType: "number";
125
- columnType: "PgBigInt53";
126
- data: number;
127
- driverParam: string | number;
128
- notNull: true;
129
- hasDefault: false;
130
- isPrimaryKey: false;
131
- isAutoincrement: false;
132
- hasRuntimeDefault: false;
133
- enumValues: undefined;
134
- baseColumn: never;
135
- identity: undefined;
136
- generated: undefined;
137
- }, {}, {}>;
138
- status: drizzle_orm_pg_core.PgColumn<{
139
- name: "status";
140
- tableName: "user_invitations";
141
- dataType: "string";
142
- columnType: "PgText";
143
- data: "pending" | "accepted" | "expired" | "cancelled";
144
- driverParam: string;
145
- notNull: true;
146
- hasDefault: true;
147
- isPrimaryKey: false;
148
- isAutoincrement: false;
149
- hasRuntimeDefault: false;
150
- enumValues: ["pending", "accepted", "expired", "cancelled"];
151
- baseColumn: never;
152
- identity: undefined;
153
- generated: undefined;
154
- }, {}, {}>;
155
- expiresAt: drizzle_orm_pg_core.PgColumn<{
156
- name: "expires_at";
157
- tableName: "user_invitations";
158
- dataType: "date";
159
- columnType: "PgTimestamp";
160
- data: Date;
161
- driverParam: string;
162
- notNull: true;
163
- hasDefault: false;
164
- isPrimaryKey: false;
165
- isAutoincrement: false;
166
- hasRuntimeDefault: false;
167
- enumValues: undefined;
168
- baseColumn: never;
169
- identity: undefined;
170
- generated: undefined;
171
- }, {}, {}>;
172
- acceptedAt: drizzle_orm_pg_core.PgColumn<{
173
- name: "accepted_at";
174
- tableName: "user_invitations";
175
- dataType: "date";
176
- columnType: "PgTimestamp";
177
- data: Date;
178
- driverParam: string;
179
- notNull: false;
180
- hasDefault: false;
181
- isPrimaryKey: false;
182
- isAutoincrement: false;
183
- hasRuntimeDefault: false;
184
- enumValues: undefined;
185
- baseColumn: never;
186
- identity: undefined;
187
- generated: undefined;
188
- }, {}, {}>;
189
- cancelledAt: drizzle_orm_pg_core.PgColumn<{
190
- name: "cancelled_at";
191
- tableName: "user_invitations";
192
- dataType: "date";
193
- columnType: "PgTimestamp";
194
- data: Date;
195
- driverParam: string;
196
- notNull: false;
197
- hasDefault: false;
198
- isPrimaryKey: false;
199
- isAutoincrement: false;
200
- hasRuntimeDefault: false;
201
- enumValues: undefined;
202
- baseColumn: never;
203
- identity: undefined;
204
- generated: undefined;
205
- }, {}, {}>;
206
- metadata: drizzle_orm_pg_core.PgColumn<{
207
- name: "metadata";
208
- tableName: "user_invitations";
209
- dataType: "json";
210
- columnType: "PgJsonb";
211
- data: unknown;
212
- driverParam: unknown;
213
- notNull: false;
214
- hasDefault: false;
215
- isPrimaryKey: false;
216
- isAutoincrement: false;
217
- hasRuntimeDefault: false;
218
- enumValues: undefined;
219
- baseColumn: never;
220
- identity: undefined;
221
- generated: undefined;
222
- }, {}, {}>;
223
- };
224
- dialect: "pg";
225
- }>;
226
- type Invitation = typeof invitations.$inferSelect;
227
- type NewInvitation = typeof invitations.$inferInsert;
228
- type InvitationStatus = 'pending' | 'accepted' | 'expired' | 'cancelled';
229
- type InvitationWithDetails = Invitation & {
230
- role: {
231
- id: number;
232
- name: string;
233
- displayName: string;
234
- };
235
- inviter: {
236
- id: number;
237
- email: string | null;
238
- };
239
- };
240
-
241
- export { type Invitation, type InvitationStatus, type InvitationWithDetails, type NewInvitation, invitations };
@@ -1,184 +0,0 @@
1
- // src/server/entities/invitations.ts
2
- import { text as text3, timestamp as timestamp2, bigint as bigint2, index as index3, jsonb } from "drizzle-orm/pg-core";
3
- import { id as id3, timestamps as timestamps3 } from "@spfn/core/db";
4
-
5
- // src/server/entities/roles.ts
6
- import { text, boolean, integer, index } from "drizzle-orm/pg-core";
7
- import { id, timestamps } from "@spfn/core/db";
8
-
9
- // src/server/entities/schema.ts
10
- import { createFunctionSchema } from "@spfn/core/db";
11
- var authSchema = createFunctionSchema("@spfn/auth");
12
-
13
- // src/server/entities/roles.ts
14
- var roles = authSchema.table(
15
- "roles",
16
- {
17
- // Primary key
18
- id: id(),
19
- // Role identifier (used in code, e.g., 'admin', 'editor')
20
- // Must be unique, lowercase, kebab-case recommended
21
- name: text("name").notNull().unique(),
22
- // Display name for UI (e.g., 'Administrator', 'Content Editor')
23
- displayName: text("display_name").notNull(),
24
- // Role description
25
- description: text("description"),
26
- // Built-in role flag
27
- // true: Core package roles (user, admin, superadmin) - cannot be deleted
28
- // false: Custom or preset roles - can be deleted
29
- isBuiltin: boolean("is_builtin").notNull().default(false),
30
- // System role flag
31
- // true: Defined in code (builtin or preset) - deletion restricted
32
- // false: Runtime created custom role - fully manageable
33
- isSystem: boolean("is_system").notNull().default(false),
34
- // Active status
35
- // false: Deactivated role (users cannot be assigned)
36
- isActive: boolean("is_active").notNull().default(true),
37
- // Priority level (higher = more privileged)
38
- // superadmin: 100, admin: 80, user: 10
39
- // Used for role hierarchy and conflict resolution
40
- priority: integer("priority").notNull().default(10),
41
- ...timestamps()
42
- },
43
- (table) => [
44
- index("roles_name_idx").on(table.name),
45
- index("roles_is_system_idx").on(table.isSystem),
46
- index("roles_is_active_idx").on(table.isActive),
47
- index("roles_is_builtin_idx").on(table.isBuiltin),
48
- index("roles_priority_idx").on(table.priority)
49
- ]
50
- );
51
-
52
- // src/server/entities/users.ts
53
- import { text as text2, timestamp, check, boolean as boolean2, bigint, index as index2 } from "drizzle-orm/pg-core";
54
- import { id as id2, timestamps as timestamps2 } from "@spfn/core/db";
55
- import { sql } from "drizzle-orm";
56
- var users = authSchema.table(
57
- "users",
58
- {
59
- // Identity
60
- id: id2(),
61
- // Email address (unique identifier)
62
- // Used for: login, password reset, notifications
63
- email: text2("email").unique(),
64
- // Phone number in E.164 international format
65
- // Format: +[country code][number] (e.g., +821012345678)
66
- // Used for: SMS login, 2FA, notifications
67
- phone: text2("phone").unique(),
68
- // Authentication
69
- // Bcrypt password hash ($2b$10$[salt][hash], 60 chars)
70
- // Nullable to support OAuth-only accounts
71
- passwordHash: text2("password_hash"),
72
- // Force password change on next login
73
- // Use cases: initial setup, security breach, policy violation
74
- passwordChangeRequired: boolean2("password_change_required").notNull().default(false),
75
- // Authorization (Role-Based Access Control)
76
- // Foreign key to roles table
77
- // References built-in roles: user (default), admin, superadmin
78
- // Can also reference custom roles created at runtime
79
- roleId: bigint("role_id", { mode: "number" }).references(() => roles.id).notNull(),
80
- // Account status
81
- // - active: Normal operation (default)
82
- // - inactive: Deactivated (user request, dormant)
83
- // - suspended: Locked (security incident, ToS violation)
84
- status: text2(
85
- "status",
86
- {
87
- enum: ["active", "inactive", "suspended"]
88
- }
89
- ).notNull().default("active"),
90
- // Verification timestamps
91
- // null = unverified, timestamp = verified at this time
92
- // Email verification (via verification code or magic link)
93
- emailVerifiedAt: timestamp("email_verified_at", { withTimezone: true }),
94
- // Phone verification (via SMS OTP)
95
- phoneVerifiedAt: timestamp("phone_verified_at", { withTimezone: true }),
96
- // Metadata
97
- // Last successful login timestamp
98
- // Used for: security auditing, dormant account detection
99
- lastLoginAt: timestamp("last_login_at", { withTimezone: true }),
100
- ...timestamps2()
101
- },
102
- (table) => [
103
- // Database constraints
104
- // Ensure at least one identifier exists (email OR phone)
105
- check(
106
- "email_or_phone_check",
107
- sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`
108
- ),
109
- // Indexes for query optimization
110
- index2("users_email_idx").on(table.email),
111
- index2("users_phone_idx").on(table.phone),
112
- index2("users_status_idx").on(table.status),
113
- index2("users_role_id_idx").on(table.roleId)
114
- ]
115
- );
116
-
117
- // src/server/entities/invitations.ts
118
- var invitations = authSchema.table(
119
- "user_invitations",
120
- {
121
- // Primary key
122
- id: id3(),
123
- // Target email address for the invitation
124
- // Will become the user's email upon acceptance
125
- email: text3("email").notNull(),
126
- // Unique invitation token (UUID v4)
127
- // Used in invitation URL: /auth/invite/{token}
128
- // Single-use token that expires after acceptance
129
- token: text3("token").notNull().unique(),
130
- // Role to be assigned when invitation is accepted
131
- // Foreign key to roles table
132
- roleId: bigint2("role_id", { mode: "number" }).references(() => roles.id).notNull(),
133
- // User who created this invitation
134
- // Foreign key to users table
135
- // Used for: audit trail, permission checks
136
- invitedBy: bigint2("invited_by", { mode: "number" }).references(() => users.id).notNull(),
137
- // Invitation status
138
- // - pending: Invitation sent, awaiting acceptance
139
- // - accepted: User accepted and account created
140
- // - expired: Invitation expired (automatic)
141
- // - cancelled: Invitation cancelled by admin
142
- status: text3(
143
- "status",
144
- {
145
- enum: ["pending", "accepted", "expired", "cancelled"]
146
- }
147
- ).notNull().default("pending"),
148
- // Expiration timestamp (default: 7 days from creation)
149
- // Invitation cannot be accepted after this time
150
- // Background job should update status to 'expired'
151
- expiresAt: timestamp2("expires_at", { withTimezone: true }).notNull(),
152
- // Timestamp when invitation was accepted
153
- // null = not yet accepted
154
- // Used for: audit trail, analytics
155
- acceptedAt: timestamp2("accepted_at", { withTimezone: true }),
156
- // Timestamp when invitation was cancelled
157
- // null = not cancelled
158
- // Used for: audit trail
159
- cancelledAt: timestamp2("cancelled_at", { withTimezone: true }),
160
- // Additional metadata (JSONB)
161
- // Use cases:
162
- // - Custom welcome message
163
- // - Onboarding instructions
164
- // - Team/department assignment
165
- // - Custom fields for app-specific data
166
- // Example: { message: "Welcome!", department: "Engineering" }
167
- metadata: jsonb("metadata"),
168
- ...timestamps3()
169
- },
170
- (table) => [
171
- // Indexes for query optimization
172
- index3("invitations_token_idx").on(table.token),
173
- index3("invitations_email_idx").on(table.email),
174
- index3("invitations_status_idx").on(table.status),
175
- index3("invitations_invited_by_idx").on(table.invitedBy),
176
- index3("invitations_expires_at_idx").on(table.expiresAt),
177
- // For cleanup jobs
178
- index3("invitations_role_id_idx").on(table.roleId)
179
- ]
180
- );
181
- export {
182
- invitations
183
- };
184
- //# sourceMappingURL=invitations.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/server/entities/invitations.ts","../../../src/server/entities/roles.ts","../../../src/server/entities/schema.ts","../../../src/server/entities/users.ts"],"sourcesContent":["/**\n * @spfn/auth - User Invitations Entity\n *\n * Invitation system for invite-only user registration\n *\n * Features:\n * - Email-based invitations with unique tokens\n * - Role assignment at invitation time\n * - Expiration and status tracking\n * - Audit trail (who invited whom, when accepted)\n * - Metadata support for custom data\n */\n\nimport { text, timestamp, bigint, index, jsonb } from 'drizzle-orm/pg-core';\nimport { id, timestamps } from '@spfn/core/db';\nimport { roles } from './roles';\nimport { users } from './users';\nimport { authSchema } from './schema';\n\nexport const invitations = authSchema.table('user_invitations',\n {\n // Primary key\n id: id(),\n\n // Target email address for the invitation\n // Will become the user's email upon acceptance\n email: text('email').notNull(),\n\n // Unique invitation token (UUID v4)\n // Used in invitation URL: /auth/invite/{token}\n // Single-use token that expires after acceptance\n token: text('token').notNull().unique(),\n\n // Role to be assigned when invitation is accepted\n // Foreign key to roles table\n roleId: bigint('role_id', { mode: 'number' })\n .references(() => roles.id)\n .notNull(),\n\n // User who created this invitation\n // Foreign key to users table\n // Used for: audit trail, permission checks\n invitedBy: bigint('invited_by', { mode: 'number' })\n .references(() => users.id)\n .notNull(),\n\n // Invitation status\n // - pending: Invitation sent, awaiting acceptance\n // - accepted: User accepted and account created\n // - expired: Invitation expired (automatic)\n // - cancelled: Invitation cancelled by admin\n status: text(\n 'status',\n {\n enum: ['pending', 'accepted', 'expired', 'cancelled']\n }\n ).notNull().default('pending'),\n\n // Expiration timestamp (default: 7 days from creation)\n // Invitation cannot be accepted after this time\n // Background job should update status to 'expired'\n expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),\n\n // Timestamp when invitation was accepted\n // null = not yet accepted\n // Used for: audit trail, analytics\n acceptedAt: timestamp('accepted_at', { withTimezone: true }),\n\n // Timestamp when invitation was cancelled\n // null = not cancelled\n // Used for: audit trail\n cancelledAt: timestamp('cancelled_at', { withTimezone: true }),\n\n // Additional metadata (JSONB)\n // Use cases:\n // - Custom welcome message\n // - Onboarding instructions\n // - Team/department assignment\n // - Custom fields for app-specific data\n // Example: { message: \"Welcome!\", department: \"Engineering\" }\n metadata: jsonb('metadata'),\n\n ...timestamps(),\n },\n (table) => [\n // Indexes for query optimization\n index('invitations_token_idx').on(table.token),\n index('invitations_email_idx').on(table.email),\n index('invitations_status_idx').on(table.status),\n index('invitations_invited_by_idx').on(table.invitedBy),\n index('invitations_expires_at_idx').on(table.expiresAt), // For cleanup jobs\n index('invitations_role_id_idx').on(table.roleId),\n ]\n);\n\n// Type exports\nexport type Invitation = typeof invitations.$inferSelect;\nexport type NewInvitation = typeof invitations.$inferInsert;\nexport type InvitationStatus = 'pending' | 'accepted' | 'expired' | 'cancelled';\n\n// Helper type with joined data\nexport type InvitationWithDetails = Invitation &\n{\n role: {\n id: number;\n name: string;\n displayName: string;\n };\n inviter: {\n id: number;\n email: string | null;\n };\n};","/**\n * @spfn/auth - Roles Entity\n *\n * Role-based access control (RBAC) roles table\n *\n * Features:\n * - Built-in roles (user, admin, superadmin) - cannot be deleted\n * - System roles (preset roles) - can be deactivated\n * - Custom roles (runtime created) - fully manageable\n * - Priority-based hierarchy\n */\n\nimport { text, boolean, integer, index } from 'drizzle-orm/pg-core';\nimport { id, timestamps } from '@spfn/core/db';\nimport { authSchema } from './schema';\n\nexport const roles = authSchema.table('roles',\n {\n // Primary key\n id: id(),\n\n // Role identifier (used in code, e.g., 'admin', 'editor')\n // Must be unique, lowercase, kebab-case recommended\n name: text('name').notNull().unique(),\n\n // Display name for UI (e.g., 'Administrator', 'Content Editor')\n displayName: text('display_name').notNull(),\n\n // Role description\n description: text('description'),\n\n // Built-in role flag\n // true: Core package roles (user, admin, superadmin) - cannot be deleted\n // false: Custom or preset roles - can be deleted\n isBuiltin: boolean('is_builtin').notNull().default(false),\n\n // System role flag\n // true: Defined in code (builtin or preset) - deletion restricted\n // false: Runtime created custom role - fully manageable\n isSystem: boolean('is_system').notNull().default(false),\n\n // Active status\n // false: Deactivated role (users cannot be assigned)\n isActive: boolean('is_active').notNull().default(true),\n\n // Priority level (higher = more privileged)\n // superadmin: 100, admin: 80, user: 10\n // Used for role hierarchy and conflict resolution\n priority: integer('priority').notNull().default(10),\n\n ...timestamps(),\n },\n (table) => [\n index('roles_name_idx').on(table.name),\n index('roles_is_system_idx').on(table.isSystem),\n index('roles_is_active_idx').on(table.isActive),\n index('roles_is_builtin_idx').on(table.isBuiltin),\n index('roles_priority_idx').on(table.priority),\n ]\n);\n\n// Type exports\nexport type RoleEntity = typeof roles.$inferSelect;\nexport type NewRoleEntity = typeof roles.$inferInsert;\n\n// Legacy alias for backward compatibility\nexport type Role = RoleEntity;\nexport type NewRole = NewRoleEntity;","/**\n * @spfn/auth - Database Schema Definition\n *\n * Defines the 'spfn_auth' PostgreSQL schema for all auth-related tables\n */\n\nimport { createFunctionSchema } from '@spfn/core/db';\n\n/**\n * Auth schema for all authentication and authorization tables\n * Tables: users, roles, permissions, user_invitations, etc.\n */\nexport const authSchema = createFunctionSchema('@spfn/auth');","/**\n * @spfn/auth - Users Entity\n *\n * Main user table supporting multiple authentication methods\n *\n * Features:\n * - Email or phone-based registration\n * - Password authentication (bcrypt)\n * - OAuth support (nullable passwordHash)\n * - Role-based access control (RBAC)\n * - Account status management\n * - Email/phone verification\n */\n\nimport { text, timestamp, check, boolean, bigint, index } from 'drizzle-orm/pg-core';\nimport { id, timestamps } from '@spfn/core/db';\nimport { sql } from 'drizzle-orm';\nimport { roles } from './roles';\nimport { authSchema } from './schema';\n\nexport const users = authSchema.table('users',\n {\n // Identity\n id: id(),\n\n // Email address (unique identifier)\n // Used for: login, password reset, notifications\n email: text('email').unique(),\n\n // Phone number in E.164 international format\n // Format: +[country code][number] (e.g., +821012345678)\n // Used for: SMS login, 2FA, notifications\n phone: text('phone').unique(),\n\n // Authentication\n // Bcrypt password hash ($2b$10$[salt][hash], 60 chars)\n // Nullable to support OAuth-only accounts\n passwordHash: text('password_hash'),\n\n // Force password change on next login\n // Use cases: initial setup, security breach, policy violation\n passwordChangeRequired: boolean('password_change_required').notNull().default(false),\n\n // Authorization (Role-Based Access Control)\n // Foreign key to roles table\n // References built-in roles: user (default), admin, superadmin\n // Can also reference custom roles created at runtime\n roleId: bigint('role_id', { mode: 'number' })\n .references(() => roles.id)\n .notNull(),\n\n // Account status\n // - active: Normal operation (default)\n // - inactive: Deactivated (user request, dormant)\n // - suspended: Locked (security incident, ToS violation)\n status: text(\n 'status',\n {\n enum: ['active', 'inactive', 'suspended']\n }\n ).notNull().default('active'),\n\n // Verification timestamps\n // null = unverified, timestamp = verified at this time\n // Email verification (via verification code or magic link)\n emailVerifiedAt: timestamp('email_verified_at', { withTimezone: true }),\n\n // Phone verification (via SMS OTP)\n phoneVerifiedAt: timestamp('phone_verified_at', { withTimezone: true }),\n\n // Metadata\n // Last successful login timestamp\n // Used for: security auditing, dormant account detection\n lastLoginAt: timestamp('last_login_at', { withTimezone: true }),\n\n ...timestamps(),\n },\n (table) => [\n // Database constraints\n // Ensure at least one identifier exists (email OR phone)\n check(\n 'email_or_phone_check',\n sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`\n ),\n\n // Indexes for query optimization\n index('users_email_idx').on(table.email),\n index('users_phone_idx').on(table.phone),\n index('users_status_idx').on(table.status),\n index('users_role_id_idx').on(table.roleId),\n ]\n);\n\n// Type exports\nexport type User = typeof users.$inferSelect;\nexport type NewUser = typeof users.$inferInsert;\nexport type UserStatus = 'active' | 'inactive' | 'suspended';\n\n// Helper type with computed verification status\nexport type UserWithVerification = User &\n{\n isEmailVerified: boolean;\n isPhoneVerified: boolean;\n};"],"mappings":"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","names":["text","timestamp","bigint","index","id","timestamps","text","boolean","index","id","timestamps","id","text","boolean","timestamps","index","id","text","bigint","timestamp","timestamps","index"]}
@@ -1,196 +0,0 @@
1
- import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
-
3
- /**
4
- * @spfn/auth - Permissions Entity
5
- *
6
- * Granular permissions for RBAC system
7
- *
8
- * Features:
9
- * - Built-in permissions (auth:*, user:*, rbac:*) - required for package
10
- * - System permissions (preset permissions) - optional
11
- * - Custom permissions (app-specific) - defined by developers
12
- * - Category grouping for organization
13
- */
14
- declare const permissions: drizzle_orm_pg_core.PgTableWithColumns<{
15
- name: "permissions";
16
- schema: string;
17
- columns: {
18
- createdAt: drizzle_orm_pg_core.PgColumn<{
19
- name: "created_at";
20
- tableName: "permissions";
21
- dataType: "date";
22
- columnType: "PgTimestamp";
23
- data: Date;
24
- driverParam: string;
25
- notNull: true;
26
- hasDefault: true;
27
- isPrimaryKey: false;
28
- isAutoincrement: false;
29
- hasRuntimeDefault: false;
30
- enumValues: undefined;
31
- baseColumn: never;
32
- identity: undefined;
33
- generated: undefined;
34
- }, {}, {}>;
35
- updatedAt: drizzle_orm_pg_core.PgColumn<{
36
- name: "updated_at";
37
- tableName: "permissions";
38
- dataType: "date";
39
- columnType: "PgTimestamp";
40
- data: Date;
41
- driverParam: string;
42
- notNull: true;
43
- hasDefault: true;
44
- isPrimaryKey: false;
45
- isAutoincrement: false;
46
- hasRuntimeDefault: false;
47
- enumValues: undefined;
48
- baseColumn: never;
49
- identity: undefined;
50
- generated: undefined;
51
- }, {}, {}>;
52
- id: drizzle_orm_pg_core.PgColumn<{
53
- name: "id";
54
- tableName: "permissions";
55
- dataType: "number";
56
- columnType: "PgBigSerial53";
57
- data: number;
58
- driverParam: number;
59
- notNull: true;
60
- hasDefault: true;
61
- isPrimaryKey: true;
62
- isAutoincrement: false;
63
- hasRuntimeDefault: false;
64
- enumValues: undefined;
65
- baseColumn: never;
66
- identity: undefined;
67
- generated: undefined;
68
- }, {}, {}>;
69
- name: drizzle_orm_pg_core.PgColumn<{
70
- name: "name";
71
- tableName: "permissions";
72
- dataType: "string";
73
- columnType: "PgText";
74
- data: string;
75
- driverParam: string;
76
- notNull: true;
77
- hasDefault: false;
78
- isPrimaryKey: false;
79
- isAutoincrement: false;
80
- hasRuntimeDefault: false;
81
- enumValues: [string, ...string[]];
82
- baseColumn: never;
83
- identity: undefined;
84
- generated: undefined;
85
- }, {}, {}>;
86
- displayName: drizzle_orm_pg_core.PgColumn<{
87
- name: "display_name";
88
- tableName: "permissions";
89
- dataType: "string";
90
- columnType: "PgText";
91
- data: string;
92
- driverParam: string;
93
- notNull: true;
94
- hasDefault: false;
95
- isPrimaryKey: false;
96
- isAutoincrement: false;
97
- hasRuntimeDefault: false;
98
- enumValues: [string, ...string[]];
99
- baseColumn: never;
100
- identity: undefined;
101
- generated: undefined;
102
- }, {}, {}>;
103
- description: drizzle_orm_pg_core.PgColumn<{
104
- name: "description";
105
- tableName: "permissions";
106
- dataType: "string";
107
- columnType: "PgText";
108
- data: string;
109
- driverParam: string;
110
- notNull: false;
111
- hasDefault: false;
112
- isPrimaryKey: false;
113
- isAutoincrement: false;
114
- hasRuntimeDefault: false;
115
- enumValues: [string, ...string[]];
116
- baseColumn: never;
117
- identity: undefined;
118
- generated: undefined;
119
- }, {}, {}>;
120
- category: drizzle_orm_pg_core.PgColumn<{
121
- name: "category";
122
- tableName: "permissions";
123
- dataType: "string";
124
- columnType: "PgText";
125
- data: string;
126
- driverParam: string;
127
- notNull: false;
128
- hasDefault: false;
129
- isPrimaryKey: false;
130
- isAutoincrement: false;
131
- hasRuntimeDefault: false;
132
- enumValues: [string, ...string[]];
133
- baseColumn: never;
134
- identity: undefined;
135
- generated: undefined;
136
- }, {}, {}>;
137
- isBuiltin: drizzle_orm_pg_core.PgColumn<{
138
- name: "is_builtin";
139
- tableName: "permissions";
140
- dataType: "boolean";
141
- columnType: "PgBoolean";
142
- data: boolean;
143
- driverParam: boolean;
144
- notNull: true;
145
- hasDefault: true;
146
- isPrimaryKey: false;
147
- isAutoincrement: false;
148
- hasRuntimeDefault: false;
149
- enumValues: undefined;
150
- baseColumn: never;
151
- identity: undefined;
152
- generated: undefined;
153
- }, {}, {}>;
154
- isSystem: drizzle_orm_pg_core.PgColumn<{
155
- name: "is_system";
156
- tableName: "permissions";
157
- dataType: "boolean";
158
- columnType: "PgBoolean";
159
- data: boolean;
160
- driverParam: boolean;
161
- notNull: true;
162
- hasDefault: true;
163
- isPrimaryKey: false;
164
- isAutoincrement: false;
165
- hasRuntimeDefault: false;
166
- enumValues: undefined;
167
- baseColumn: never;
168
- identity: undefined;
169
- generated: undefined;
170
- }, {}, {}>;
171
- isActive: drizzle_orm_pg_core.PgColumn<{
172
- name: "is_active";
173
- tableName: "permissions";
174
- dataType: "boolean";
175
- columnType: "PgBoolean";
176
- data: boolean;
177
- driverParam: boolean;
178
- notNull: true;
179
- hasDefault: true;
180
- isPrimaryKey: false;
181
- isAutoincrement: false;
182
- hasRuntimeDefault: false;
183
- enumValues: undefined;
184
- baseColumn: never;
185
- identity: undefined;
186
- generated: undefined;
187
- }, {}, {}>;
188
- };
189
- dialect: "pg";
190
- }>;
191
- type PermissionEntity = typeof permissions.$inferSelect;
192
- type NewPermissionEntity = typeof permissions.$inferInsert;
193
- type Permission = PermissionEntity;
194
- type NewPermission = NewPermissionEntity;
195
-
196
- export { type NewPermission, type NewPermissionEntity, type Permission, type PermissionEntity, permissions };