@contractspec/lib.identity-rbac 3.7.6 → 3.7.7

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