@contractspec/lib.identity-rbac 3.7.6 → 3.7.10

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.
@@ -1,173 +1,10 @@
1
1
  // @bun
2
- // src/entities/user.ts
3
- import { defineEntity, field, index } from "@contractspec/lib.schema";
4
- var UserEntity = defineEntity({
5
- name: "User",
6
- description: "A user of the platform. Users hold core profile information and authenticate via Account records.",
7
- schema: "lssm_sigil",
8
- map: "user",
9
- fields: {
10
- id: field.id({ description: "Unique user identifier" }),
11
- email: field.email({ isUnique: true, description: "User email address" }),
12
- emailVerified: field.boolean({
13
- default: false,
14
- description: "Whether email has been verified"
15
- }),
16
- name: field.string({ isOptional: true, description: "Display name" }),
17
- firstName: field.string({ isOptional: true, description: "First name" }),
18
- lastName: field.string({ isOptional: true, description: "Last name" }),
19
- locale: field.string({
20
- isOptional: true,
21
- description: 'User locale (e.g., "en-US")'
22
- }),
23
- timezone: field.string({
24
- isOptional: true,
25
- description: 'Olson timezone (e.g., "Europe/Paris")'
26
- }),
27
- imageUrl: field.url({
28
- isOptional: true,
29
- description: "URL of avatar or profile picture"
30
- }),
31
- image: field.string({
32
- isOptional: true,
33
- description: "Legacy image field"
34
- }),
35
- metadata: field.json({
36
- isOptional: true,
37
- description: "Arbitrary user metadata"
38
- }),
39
- onboardingCompleted: field.boolean({
40
- default: false,
41
- description: "Whether onboarding is complete"
42
- }),
43
- onboardingStep: field.string({
44
- isOptional: true,
45
- description: "Current onboarding step"
46
- }),
47
- whitelistedAt: field.dateTime({
48
- isOptional: true,
49
- description: "When user was whitelisted"
50
- }),
51
- role: field.string({
52
- isOptional: true,
53
- default: '"user"',
54
- description: "User role (user, admin)"
55
- }),
56
- banned: field.boolean({
57
- default: false,
58
- description: "Whether user is banned"
59
- }),
60
- banReason: field.string({
61
- isOptional: true,
62
- description: "Reason for ban"
63
- }),
64
- banExpires: field.dateTime({
65
- isOptional: true,
66
- description: "When ban expires"
67
- }),
68
- phoneNumber: field.string({
69
- isOptional: true,
70
- isUnique: true,
71
- description: "Phone number"
72
- }),
73
- phoneNumberVerified: field.boolean({
74
- default: false,
75
- description: "Whether phone is verified"
76
- }),
77
- createdAt: field.createdAt(),
78
- updatedAt: field.updatedAt(),
79
- sessions: field.hasMany("Session"),
80
- accounts: field.hasMany("Account"),
81
- memberships: field.hasMany("Member"),
82
- invitations: field.hasMany("Invitation"),
83
- teamMemberships: field.hasMany("TeamMember"),
84
- policyBindings: field.hasMany("PolicyBinding"),
85
- apiKeys: field.hasMany("ApiKey"),
86
- passkeys: field.hasMany("Passkey")
87
- }
88
- });
89
- var SessionEntity = defineEntity({
90
- name: "Session",
91
- description: "Represents a login session (e.g., web session or API token).",
92
- schema: "lssm_sigil",
93
- map: "session",
94
- fields: {
95
- id: field.id(),
96
- userId: field.foreignKey(),
97
- expiresAt: field.dateTime({ description: "Session expiration time" }),
98
- token: field.string({ isUnique: true, description: "Session token" }),
99
- ipAddress: field.string({
100
- isOptional: true,
101
- description: "Client IP address"
102
- }),
103
- userAgent: field.string({
104
- isOptional: true,
105
- description: "Client user agent"
106
- }),
107
- impersonatedBy: field.string({
108
- isOptional: true,
109
- description: "Admin impersonating this session"
110
- }),
111
- activeOrganizationId: field.string({
112
- isOptional: true,
113
- description: "Active org context"
114
- }),
115
- activeTeamId: field.string({
116
- isOptional: true,
117
- description: "Active team context"
118
- }),
119
- createdAt: field.createdAt(),
120
- updatedAt: field.updatedAt(),
121
- user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
122
- }
123
- });
124
- var AccountEntity = defineEntity({
125
- name: "Account",
126
- description: "External authentication accounts (OAuth, password, etc.).",
127
- schema: "lssm_sigil",
128
- map: "account",
129
- fields: {
130
- id: field.id(),
131
- accountId: field.string({ description: "Account ID from provider" }),
132
- providerId: field.string({ description: "Provider identifier" }),
133
- userId: field.foreignKey(),
134
- accessToken: field.string({ isOptional: true }),
135
- refreshToken: field.string({ isOptional: true }),
136
- idToken: field.string({ isOptional: true }),
137
- accessTokenExpiresAt: field.dateTime({ isOptional: true }),
138
- refreshTokenExpiresAt: field.dateTime({ isOptional: true }),
139
- scope: field.string({ isOptional: true }),
140
- password: field.string({
141
- isOptional: true,
142
- description: "Hashed password for password providers"
143
- }),
144
- createdAt: field.createdAt(),
145
- updatedAt: field.updatedAt(),
146
- user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
147
- },
148
- indexes: [index.unique(["accountId", "providerId"])]
149
- });
150
- var VerificationEntity = defineEntity({
151
- name: "Verification",
152
- description: "Verification tokens for email/phone confirmation.",
153
- schema: "lssm_sigil",
154
- map: "verification",
155
- fields: {
156
- id: field.uuid(),
157
- identifier: field.string({ description: "Email or phone being verified" }),
158
- value: field.string({ description: "Verification code/token" }),
159
- expiresAt: field.dateTime({ description: "Token expiration" }),
160
- createdAt: field.createdAt(),
161
- updatedAt: field.updatedAt()
162
- }
163
- });
164
-
165
2
  // src/entities/organization.ts
166
3
  import {
167
- defineEntity as defineEntity2,
4
+ defineEntity,
168
5
  defineEntityEnum,
169
- field as field2,
170
- index as index2
6
+ field,
7
+ index
171
8
  } from "@contractspec/lib.schema";
172
9
  var OrganizationTypeEnum = defineEntityEnum({
173
10
  name: "OrganizationType",
@@ -175,251 +12,414 @@ var OrganizationTypeEnum = defineEntityEnum({
175
12
  schema: "lssm_sigil",
176
13
  description: "Type of organization in the platform."
177
14
  });
178
- var OrganizationEntity = defineEntity2({
15
+ var OrganizationEntity = defineEntity({
179
16
  name: "Organization",
180
17
  description: "An organization is a tenant boundary grouping users.",
181
18
  schema: "lssm_sigil",
182
19
  map: "organization",
183
20
  fields: {
184
- id: field2.id({ description: "Unique organization identifier" }),
185
- name: field2.string({ description: "Organization display name" }),
186
- slug: field2.string({
21
+ id: field.id({ description: "Unique organization identifier" }),
22
+ name: field.string({ description: "Organization display name" }),
23
+ slug: field.string({
187
24
  isOptional: true,
188
25
  isUnique: true,
189
26
  description: "URL-friendly identifier"
190
27
  }),
191
- logo: field2.url({ isOptional: true, description: "Organization logo URL" }),
192
- description: field2.string({
28
+ logo: field.url({ isOptional: true, description: "Organization logo URL" }),
29
+ description: field.string({
193
30
  isOptional: true,
194
31
  description: "Organization description"
195
32
  }),
196
- metadata: field2.json({
33
+ metadata: field.json({
197
34
  isOptional: true,
198
35
  description: "Arbitrary organization metadata"
199
36
  }),
200
- type: field2.enum("OrganizationType", { description: "Organization type" }),
201
- onboardingCompleted: field2.boolean({ default: false }),
202
- onboardingStep: field2.string({ isOptional: true }),
203
- referralCode: field2.string({
37
+ type: field.enum("OrganizationType", { description: "Organization type" }),
38
+ onboardingCompleted: field.boolean({ default: false }),
39
+ onboardingStep: field.string({ isOptional: true }),
40
+ referralCode: field.string({
204
41
  isOptional: true,
205
42
  isUnique: true,
206
43
  description: "Unique referral code"
207
44
  }),
208
- referredBy: field2.string({
45
+ referredBy: field.string({
209
46
  isOptional: true,
210
47
  description: "ID of referring user"
211
48
  }),
212
- createdAt: field2.createdAt(),
213
- updatedAt: field2.updatedAt(),
214
- members: field2.hasMany("Member"),
215
- invitations: field2.hasMany("Invitation"),
216
- teams: field2.hasMany("Team"),
217
- policyBindings: field2.hasMany("PolicyBinding")
49
+ createdAt: field.createdAt(),
50
+ updatedAt: field.updatedAt(),
51
+ members: field.hasMany("Member"),
52
+ invitations: field.hasMany("Invitation"),
53
+ teams: field.hasMany("Team"),
54
+ policyBindings: field.hasMany("PolicyBinding")
218
55
  },
219
56
  enums: [OrganizationTypeEnum]
220
57
  });
221
- var MemberEntity = defineEntity2({
58
+ var MemberEntity = defineEntity({
222
59
  name: "Member",
223
60
  description: "Membership of a user in an organization with a role.",
224
61
  schema: "lssm_sigil",
225
62
  map: "member",
226
63
  fields: {
227
- id: field2.id(),
228
- userId: field2.foreignKey(),
229
- organizationId: field2.foreignKey(),
230
- role: field2.string({
64
+ id: field.id(),
65
+ userId: field.foreignKey(),
66
+ organizationId: field.foreignKey(),
67
+ role: field.string({
231
68
  description: "Role in organization (owner, admin, member)"
232
69
  }),
233
- createdAt: field2.createdAt(),
234
- user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" }),
235
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
70
+ createdAt: field.createdAt(),
71
+ user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" }),
72
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
236
73
  onDelete: "Cascade"
237
74
  })
238
75
  },
239
- indexes: [index2.unique(["userId", "organizationId"])]
76
+ indexes: [index.unique(["userId", "organizationId"])]
240
77
  });
241
- var InvitationEntity = defineEntity2({
78
+ var InvitationEntity = defineEntity({
242
79
  name: "Invitation",
243
80
  description: "An invitation to join an organization.",
244
81
  schema: "lssm_sigil",
245
82
  map: "invitation",
246
83
  fields: {
247
- id: field2.id(),
248
- organizationId: field2.foreignKey(),
249
- email: field2.email({ description: "Invited email address" }),
250
- role: field2.string({
84
+ id: field.id(),
85
+ organizationId: field.foreignKey(),
86
+ email: field.email({ description: "Invited email address" }),
87
+ role: field.string({
251
88
  isOptional: true,
252
89
  description: "Role to assign on acceptance"
253
90
  }),
254
- status: field2.string({
91
+ status: field.string({
255
92
  default: '"pending"',
256
93
  description: "Invitation status"
257
94
  }),
258
- acceptedAt: field2.dateTime({ isOptional: true }),
259
- expiresAt: field2.dateTime({ isOptional: true }),
260
- inviterId: field2.foreignKey({
95
+ acceptedAt: field.dateTime({ isOptional: true }),
96
+ expiresAt: field.dateTime({ isOptional: true }),
97
+ inviterId: field.foreignKey({
261
98
  description: "User who sent the invitation"
262
99
  }),
263
- teamId: field2.string({ isOptional: true }),
264
- createdAt: field2.createdAt(),
265
- updatedAt: field2.updatedAt(),
266
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
100
+ teamId: field.string({ isOptional: true }),
101
+ createdAt: field.createdAt(),
102
+ updatedAt: field.updatedAt(),
103
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
267
104
  onDelete: "Cascade"
268
105
  }),
269
- inviter: field2.belongsTo("User", ["inviterId"], ["id"], {
106
+ inviter: field.belongsTo("User", ["inviterId"], ["id"], {
270
107
  onDelete: "Cascade"
271
108
  }),
272
- team: field2.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
109
+ team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
273
110
  }
274
111
  });
275
- var TeamEntity = defineEntity2({
112
+ var TeamEntity = defineEntity({
276
113
  name: "Team",
277
114
  description: "Team within an organization.",
278
115
  schema: "lssm_sigil",
279
116
  map: "team",
280
117
  fields: {
281
- id: field2.id(),
282
- name: field2.string({ description: "Team name" }),
283
- organizationId: field2.foreignKey(),
284
- createdAt: field2.createdAt(),
285
- updatedAt: field2.updatedAt(),
286
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
118
+ id: field.id(),
119
+ name: field.string({ description: "Team name" }),
120
+ organizationId: field.foreignKey(),
121
+ createdAt: field.createdAt(),
122
+ updatedAt: field.updatedAt(),
123
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
287
124
  onDelete: "Cascade"
288
125
  }),
289
- members: field2.hasMany("TeamMember"),
290
- invitations: field2.hasMany("Invitation")
126
+ members: field.hasMany("TeamMember"),
127
+ invitations: field.hasMany("Invitation")
291
128
  }
292
129
  });
293
- var TeamMemberEntity = defineEntity2({
130
+ var TeamMemberEntity = defineEntity({
294
131
  name: "TeamMember",
295
132
  description: "Team membership for a user.",
296
133
  schema: "lssm_sigil",
297
134
  map: "team_member",
298
135
  fields: {
299
- id: field2.id(),
300
- teamId: field2.foreignKey(),
301
- userId: field2.foreignKey(),
302
- createdAt: field2.createdAt(),
303
- team: field2.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" }),
304
- user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
136
+ id: field.id(),
137
+ teamId: field.foreignKey(),
138
+ userId: field.foreignKey(),
139
+ createdAt: field.createdAt(),
140
+ team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" }),
141
+ user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
305
142
  }
306
143
  });
307
144
 
308
145
  // src/entities/rbac.ts
309
- import { defineEntity as defineEntity3, field as field3, index as index3 } from "@contractspec/lib.schema";
310
- var RoleEntity = defineEntity3({
146
+ import { defineEntity as defineEntity2, field as field2, index as index2 } from "@contractspec/lib.schema";
147
+ var RoleEntity = defineEntity2({
311
148
  name: "Role",
312
149
  description: "A role defines a named set of permissions.",
313
150
  schema: "lssm_sigil",
314
151
  map: "role",
315
152
  fields: {
316
- id: field3.id(),
317
- name: field3.string({ isUnique: true, description: "Unique role name" }),
318
- description: field3.string({
153
+ id: field2.id(),
154
+ name: field2.string({ isUnique: true, description: "Unique role name" }),
155
+ description: field2.string({
319
156
  isOptional: true,
320
157
  description: "Role description"
321
158
  }),
322
- permissions: field3.string({
159
+ permissions: field2.string({
323
160
  isArray: true,
324
161
  description: "Array of permission names"
325
162
  }),
326
- createdAt: field3.createdAt(),
327
- updatedAt: field3.updatedAt(),
328
- policyBindings: field3.hasMany("PolicyBinding")
163
+ createdAt: field2.createdAt(),
164
+ updatedAt: field2.updatedAt(),
165
+ policyBindings: field2.hasMany("PolicyBinding")
329
166
  }
330
167
  });
331
- var PermissionEntity = defineEntity3({
168
+ var PermissionEntity = defineEntity2({
332
169
  name: "Permission",
333
170
  description: "A permission represents an atomic access right.",
334
171
  schema: "lssm_sigil",
335
172
  map: "permission",
336
173
  fields: {
337
- id: field3.id(),
338
- name: field3.string({
174
+ id: field2.id(),
175
+ name: field2.string({
339
176
  isUnique: true,
340
177
  description: "Unique permission name"
341
178
  }),
342
- description: field3.string({
179
+ description: field2.string({
343
180
  isOptional: true,
344
181
  description: "Permission description"
345
182
  }),
346
- createdAt: field3.createdAt(),
347
- updatedAt: field3.updatedAt()
183
+ createdAt: field2.createdAt(),
184
+ updatedAt: field2.updatedAt()
348
185
  }
349
186
  });
350
- var PolicyBindingEntity = defineEntity3({
187
+ var PolicyBindingEntity = defineEntity2({
351
188
  name: "PolicyBinding",
352
189
  description: "Binds roles to principals (users or organizations).",
353
190
  schema: "lssm_sigil",
354
191
  map: "policy_binding",
355
192
  fields: {
356
- id: field3.id(),
357
- roleId: field3.foreignKey(),
358
- targetType: field3.string({ description: '"user" or "organization"' }),
359
- targetId: field3.string({ description: "ID of User or Organization" }),
360
- expiresAt: field3.dateTime({
193
+ id: field2.id(),
194
+ roleId: field2.foreignKey(),
195
+ targetType: field2.string({ description: '"user" or "organization"' }),
196
+ targetId: field2.string({ description: "ID of User or Organization" }),
197
+ expiresAt: field2.dateTime({
361
198
  isOptional: true,
362
199
  description: "When binding expires"
363
200
  }),
364
- createdAt: field3.createdAt(),
365
- userId: field3.string({ isOptional: true }),
366
- organizationId: field3.string({ isOptional: true }),
367
- role: field3.belongsTo("Role", ["roleId"], ["id"], { onDelete: "Cascade" }),
368
- user: field3.belongsTo("User", ["userId"], ["id"]),
369
- organization: field3.belongsTo("Organization", ["organizationId"], ["id"])
201
+ createdAt: field2.createdAt(),
202
+ userId: field2.string({ isOptional: true }),
203
+ organizationId: field2.string({ isOptional: true }),
204
+ role: field2.belongsTo("Role", ["roleId"], ["id"], { onDelete: "Cascade" }),
205
+ user: field2.belongsTo("User", ["userId"], ["id"]),
206
+ organization: field2.belongsTo("Organization", ["organizationId"], ["id"])
370
207
  },
371
- indexes: [index3.on(["targetType", "targetId"])]
208
+ indexes: [index2.on(["targetType", "targetId"])]
372
209
  });
373
- var ApiKeyEntity = defineEntity3({
210
+ var ApiKeyEntity = defineEntity2({
374
211
  name: "ApiKey",
375
212
  description: "API keys for programmatic access.",
376
213
  schema: "lssm_sigil",
377
214
  map: "api_key",
378
215
  fields: {
379
- id: field3.id(),
380
- name: field3.string({ description: "API key name" }),
381
- start: field3.string({
216
+ id: field2.id(),
217
+ name: field2.string({ description: "API key name" }),
218
+ start: field2.string({
382
219
  description: "Starting characters for identification"
383
220
  }),
384
- prefix: field3.string({ description: "API key prefix" }),
385
- key: field3.string({ description: "Hashed API key" }),
221
+ prefix: field2.string({ description: "API key prefix" }),
222
+ key: field2.string({ description: "Hashed API key" }),
223
+ userId: field2.foreignKey(),
224
+ refillInterval: field2.int({ description: "Refill interval in ms" }),
225
+ refillAmount: field2.int({ description: "Amount to refill" }),
226
+ lastRefillAt: field2.dateTime(),
227
+ remaining: field2.int({ description: "Remaining requests" }),
228
+ requestCount: field2.int({ description: "Total requests made" }),
229
+ lastRequest: field2.dateTime(),
230
+ enabled: field2.boolean({ default: true }),
231
+ rateLimitEnabled: field2.boolean({ default: true }),
232
+ rateLimitTimeWindow: field2.int({ description: "Rate limit window in ms" }),
233
+ rateLimitMax: field2.int({ description: "Max requests in window" }),
234
+ expiresAt: field2.dateTime(),
235
+ permissions: field2.string({ isArray: true }),
236
+ metadata: field2.json({ isOptional: true }),
237
+ createdAt: field2.createdAt(),
238
+ updatedAt: field2.updatedAt(),
239
+ user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
240
+ }
241
+ });
242
+ var PasskeyEntity = defineEntity2({
243
+ name: "Passkey",
244
+ description: "WebAuthn passkeys for passwordless authentication.",
245
+ schema: "lssm_sigil",
246
+ map: "passkey",
247
+ fields: {
248
+ id: field2.id(),
249
+ name: field2.string({ description: "Passkey name" }),
250
+ publicKey: field2.string({ description: "Public key" }),
251
+ userId: field2.foreignKey(),
252
+ credentialID: field2.string({ description: "Credential ID" }),
253
+ counter: field2.int({ description: "Counter" }),
254
+ deviceType: field2.string({ description: "Device type" }),
255
+ backedUp: field2.boolean({ description: "Whether passkey is backed up" }),
256
+ transports: field2.string({ description: "Transports" }),
257
+ aaguid: field2.string({ description: "Authenticator GUID" }),
258
+ createdAt: field2.createdAt(),
259
+ user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
260
+ }
261
+ });
262
+
263
+ // src/entities/user.ts
264
+ import { defineEntity as defineEntity3, field as field3, index as index3 } from "@contractspec/lib.schema";
265
+ var UserEntity = defineEntity3({
266
+ name: "User",
267
+ description: "A user of the platform. Users hold core profile information and authenticate via Account records.",
268
+ schema: "lssm_sigil",
269
+ map: "user",
270
+ fields: {
271
+ id: field3.id({ description: "Unique user identifier" }),
272
+ email: field3.email({ isUnique: true, description: "User email address" }),
273
+ emailVerified: field3.boolean({
274
+ default: false,
275
+ description: "Whether email has been verified"
276
+ }),
277
+ name: field3.string({ isOptional: true, description: "Display name" }),
278
+ firstName: field3.string({ isOptional: true, description: "First name" }),
279
+ lastName: field3.string({ isOptional: true, description: "Last name" }),
280
+ locale: field3.string({
281
+ isOptional: true,
282
+ description: 'User locale (e.g., "en-US")'
283
+ }),
284
+ timezone: field3.string({
285
+ isOptional: true,
286
+ description: 'Olson timezone (e.g., "Europe/Paris")'
287
+ }),
288
+ imageUrl: field3.url({
289
+ isOptional: true,
290
+ description: "URL of avatar or profile picture"
291
+ }),
292
+ image: field3.string({
293
+ isOptional: true,
294
+ description: "Legacy image field"
295
+ }),
296
+ metadata: field3.json({
297
+ isOptional: true,
298
+ description: "Arbitrary user metadata"
299
+ }),
300
+ onboardingCompleted: field3.boolean({
301
+ default: false,
302
+ description: "Whether onboarding is complete"
303
+ }),
304
+ onboardingStep: field3.string({
305
+ isOptional: true,
306
+ description: "Current onboarding step"
307
+ }),
308
+ whitelistedAt: field3.dateTime({
309
+ isOptional: true,
310
+ description: "When user was whitelisted"
311
+ }),
312
+ role: field3.string({
313
+ isOptional: true,
314
+ default: '"user"',
315
+ description: "User role (user, admin)"
316
+ }),
317
+ banned: field3.boolean({
318
+ default: false,
319
+ description: "Whether user is banned"
320
+ }),
321
+ banReason: field3.string({
322
+ isOptional: true,
323
+ description: "Reason for ban"
324
+ }),
325
+ banExpires: field3.dateTime({
326
+ isOptional: true,
327
+ description: "When ban expires"
328
+ }),
329
+ phoneNumber: field3.string({
330
+ isOptional: true,
331
+ isUnique: true,
332
+ description: "Phone number"
333
+ }),
334
+ phoneNumberVerified: field3.boolean({
335
+ default: false,
336
+ description: "Whether phone is verified"
337
+ }),
338
+ createdAt: field3.createdAt(),
339
+ updatedAt: field3.updatedAt(),
340
+ sessions: field3.hasMany("Session"),
341
+ accounts: field3.hasMany("Account"),
342
+ memberships: field3.hasMany("Member"),
343
+ invitations: field3.hasMany("Invitation"),
344
+ teamMemberships: field3.hasMany("TeamMember"),
345
+ policyBindings: field3.hasMany("PolicyBinding"),
346
+ apiKeys: field3.hasMany("ApiKey"),
347
+ passkeys: field3.hasMany("Passkey")
348
+ }
349
+ });
350
+ var SessionEntity = defineEntity3({
351
+ name: "Session",
352
+ description: "Represents a login session (e.g., web session or API token).",
353
+ schema: "lssm_sigil",
354
+ map: "session",
355
+ fields: {
356
+ id: field3.id(),
386
357
  userId: field3.foreignKey(),
387
- refillInterval: field3.int({ description: "Refill interval in ms" }),
388
- refillAmount: field3.int({ description: "Amount to refill" }),
389
- lastRefillAt: field3.dateTime(),
390
- remaining: field3.int({ description: "Remaining requests" }),
391
- requestCount: field3.int({ description: "Total requests made" }),
392
- lastRequest: field3.dateTime(),
393
- enabled: field3.boolean({ default: true }),
394
- rateLimitEnabled: field3.boolean({ default: true }),
395
- rateLimitTimeWindow: field3.int({ description: "Rate limit window in ms" }),
396
- rateLimitMax: field3.int({ description: "Max requests in window" }),
397
- expiresAt: field3.dateTime(),
398
- permissions: field3.string({ isArray: true }),
399
- metadata: field3.json({ isOptional: true }),
358
+ expiresAt: field3.dateTime({ description: "Session expiration time" }),
359
+ token: field3.string({ isUnique: true, description: "Session token" }),
360
+ ipAddress: field3.string({
361
+ isOptional: true,
362
+ description: "Client IP address"
363
+ }),
364
+ userAgent: field3.string({
365
+ isOptional: true,
366
+ description: "Client user agent"
367
+ }),
368
+ impersonatedBy: field3.string({
369
+ isOptional: true,
370
+ description: "Admin impersonating this session"
371
+ }),
372
+ activeOrganizationId: field3.string({
373
+ isOptional: true,
374
+ description: "Active org context"
375
+ }),
376
+ activeTeamId: field3.string({
377
+ isOptional: true,
378
+ description: "Active team context"
379
+ }),
400
380
  createdAt: field3.createdAt(),
401
381
  updatedAt: field3.updatedAt(),
402
382
  user: field3.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
403
383
  }
404
384
  });
405
- var PasskeyEntity = defineEntity3({
406
- name: "Passkey",
407
- description: "WebAuthn passkeys for passwordless authentication.",
385
+ var AccountEntity = defineEntity3({
386
+ name: "Account",
387
+ description: "External authentication accounts (OAuth, password, etc.).",
408
388
  schema: "lssm_sigil",
409
- map: "passkey",
389
+ map: "account",
410
390
  fields: {
411
391
  id: field3.id(),
412
- name: field3.string({ description: "Passkey name" }),
413
- publicKey: field3.string({ description: "Public key" }),
392
+ accountId: field3.string({ description: "Account ID from provider" }),
393
+ providerId: field3.string({ description: "Provider identifier" }),
414
394
  userId: field3.foreignKey(),
415
- credentialID: field3.string({ description: "Credential ID" }),
416
- counter: field3.int({ description: "Counter" }),
417
- deviceType: field3.string({ description: "Device type" }),
418
- backedUp: field3.boolean({ description: "Whether passkey is backed up" }),
419
- transports: field3.string({ description: "Transports" }),
420
- aaguid: field3.string({ description: "Authenticator GUID" }),
395
+ accessToken: field3.string({ isOptional: true }),
396
+ refreshToken: field3.string({ isOptional: true }),
397
+ idToken: field3.string({ isOptional: true }),
398
+ accessTokenExpiresAt: field3.dateTime({ isOptional: true }),
399
+ refreshTokenExpiresAt: field3.dateTime({ isOptional: true }),
400
+ scope: field3.string({ isOptional: true }),
401
+ password: field3.string({
402
+ isOptional: true,
403
+ description: "Hashed password for password providers"
404
+ }),
421
405
  createdAt: field3.createdAt(),
406
+ updatedAt: field3.updatedAt(),
422
407
  user: field3.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
408
+ },
409
+ indexes: [index3.unique(["accountId", "providerId"])]
410
+ });
411
+ var VerificationEntity = defineEntity3({
412
+ name: "Verification",
413
+ description: "Verification tokens for email/phone confirmation.",
414
+ schema: "lssm_sigil",
415
+ map: "verification",
416
+ fields: {
417
+ id: field3.uuid(),
418
+ identifier: field3.string({ description: "Email or phone being verified" }),
419
+ value: field3.string({ description: "Verification code/token" }),
420
+ expiresAt: field3.dateTime({ description: "Token expiration" }),
421
+ createdAt: field3.createdAt(),
422
+ updatedAt: field3.updatedAt()
423
423
  }
424
424
  });
425
425
  // src/entities/index.ts