@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,6 +1,6 @@
1
1
  // src/contracts/user.ts
2
- import { SchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
3
2
  import { defineCommand, defineQuery } from "@contractspec/lib.contracts-spec";
3
+ import { ScalarTypeEnum, SchemaModel } from "@contractspec/lib.schema";
4
4
  var OWNERS = ["platform.identity-rbac"];
5
5
  var UserProfileModel = new SchemaModel({
6
6
  name: "UserProfile",
@@ -220,8 +220,8 @@ var ListUsersContract = defineQuery({
220
220
  });
221
221
 
222
222
  // src/contracts/organization.ts
223
- import { ScalarTypeEnum as ScalarTypeEnum2, SchemaModel as SchemaModel2 } from "@contractspec/lib.schema";
224
223
  import { defineCommand as defineCommand2, defineQuery as defineQuery2 } from "@contractspec/lib.contracts-spec";
224
+ import { ScalarTypeEnum as ScalarTypeEnum2, SchemaModel as SchemaModel2 } from "@contractspec/lib.schema";
225
225
  var OWNERS2 = ["platform.identity-rbac"];
226
226
  var OrganizationModel = new SchemaModel2({
227
227
  name: "Organization",
@@ -630,8 +630,8 @@ var ListUserOrgsContract = defineQuery2({
630
630
  });
631
631
 
632
632
  // src/contracts/rbac.ts
633
- import { SchemaModel as SchemaModel3, ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
634
633
  import { defineCommand as defineCommand3, defineQuery as defineQuery3 } from "@contractspec/lib.contracts-spec";
634
+ import { ScalarTypeEnum as ScalarTypeEnum3, SchemaModel as SchemaModel3 } from "@contractspec/lib.schema";
635
635
  var RoleModel = new SchemaModel3({
636
636
  name: "Role",
637
637
  description: "RBAC role definition",
@@ -984,175 +984,12 @@ var ListUserPermissionsContract = defineQuery3({
984
984
  auth: "user"
985
985
  }
986
986
  });
987
- // src/entities/user.ts
988
- import { defineEntity, field, index } from "@contractspec/lib.schema";
989
- var UserEntity = defineEntity({
990
- name: "User",
991
- description: "A user of the platform. Users hold core profile information and authenticate via Account records.",
992
- schema: "lssm_sigil",
993
- map: "user",
994
- fields: {
995
- id: field.id({ description: "Unique user identifier" }),
996
- email: field.email({ isUnique: true, description: "User email address" }),
997
- emailVerified: field.boolean({
998
- default: false,
999
- description: "Whether email has been verified"
1000
- }),
1001
- name: field.string({ isOptional: true, description: "Display name" }),
1002
- firstName: field.string({ isOptional: true, description: "First name" }),
1003
- lastName: field.string({ isOptional: true, description: "Last name" }),
1004
- locale: field.string({
1005
- isOptional: true,
1006
- description: 'User locale (e.g., "en-US")'
1007
- }),
1008
- timezone: field.string({
1009
- isOptional: true,
1010
- description: 'Olson timezone (e.g., "Europe/Paris")'
1011
- }),
1012
- imageUrl: field.url({
1013
- isOptional: true,
1014
- description: "URL of avatar or profile picture"
1015
- }),
1016
- image: field.string({
1017
- isOptional: true,
1018
- description: "Legacy image field"
1019
- }),
1020
- metadata: field.json({
1021
- isOptional: true,
1022
- description: "Arbitrary user metadata"
1023
- }),
1024
- onboardingCompleted: field.boolean({
1025
- default: false,
1026
- description: "Whether onboarding is complete"
1027
- }),
1028
- onboardingStep: field.string({
1029
- isOptional: true,
1030
- description: "Current onboarding step"
1031
- }),
1032
- whitelistedAt: field.dateTime({
1033
- isOptional: true,
1034
- description: "When user was whitelisted"
1035
- }),
1036
- role: field.string({
1037
- isOptional: true,
1038
- default: '"user"',
1039
- description: "User role (user, admin)"
1040
- }),
1041
- banned: field.boolean({
1042
- default: false,
1043
- description: "Whether user is banned"
1044
- }),
1045
- banReason: field.string({
1046
- isOptional: true,
1047
- description: "Reason for ban"
1048
- }),
1049
- banExpires: field.dateTime({
1050
- isOptional: true,
1051
- description: "When ban expires"
1052
- }),
1053
- phoneNumber: field.string({
1054
- isOptional: true,
1055
- isUnique: true,
1056
- description: "Phone number"
1057
- }),
1058
- phoneNumberVerified: field.boolean({
1059
- default: false,
1060
- description: "Whether phone is verified"
1061
- }),
1062
- createdAt: field.createdAt(),
1063
- updatedAt: field.updatedAt(),
1064
- sessions: field.hasMany("Session"),
1065
- accounts: field.hasMany("Account"),
1066
- memberships: field.hasMany("Member"),
1067
- invitations: field.hasMany("Invitation"),
1068
- teamMemberships: field.hasMany("TeamMember"),
1069
- policyBindings: field.hasMany("PolicyBinding"),
1070
- apiKeys: field.hasMany("ApiKey"),
1071
- passkeys: field.hasMany("Passkey")
1072
- }
1073
- });
1074
- var SessionEntity = defineEntity({
1075
- name: "Session",
1076
- description: "Represents a login session (e.g., web session or API token).",
1077
- schema: "lssm_sigil",
1078
- map: "session",
1079
- fields: {
1080
- id: field.id(),
1081
- userId: field.foreignKey(),
1082
- expiresAt: field.dateTime({ description: "Session expiration time" }),
1083
- token: field.string({ isUnique: true, description: "Session token" }),
1084
- ipAddress: field.string({
1085
- isOptional: true,
1086
- description: "Client IP address"
1087
- }),
1088
- userAgent: field.string({
1089
- isOptional: true,
1090
- description: "Client user agent"
1091
- }),
1092
- impersonatedBy: field.string({
1093
- isOptional: true,
1094
- description: "Admin impersonating this session"
1095
- }),
1096
- activeOrganizationId: field.string({
1097
- isOptional: true,
1098
- description: "Active org context"
1099
- }),
1100
- activeTeamId: field.string({
1101
- isOptional: true,
1102
- description: "Active team context"
1103
- }),
1104
- createdAt: field.createdAt(),
1105
- updatedAt: field.updatedAt(),
1106
- user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1107
- }
1108
- });
1109
- var AccountEntity = defineEntity({
1110
- name: "Account",
1111
- description: "External authentication accounts (OAuth, password, etc.).",
1112
- schema: "lssm_sigil",
1113
- map: "account",
1114
- fields: {
1115
- id: field.id(),
1116
- accountId: field.string({ description: "Account ID from provider" }),
1117
- providerId: field.string({ description: "Provider identifier" }),
1118
- userId: field.foreignKey(),
1119
- accessToken: field.string({ isOptional: true }),
1120
- refreshToken: field.string({ isOptional: true }),
1121
- idToken: field.string({ isOptional: true }),
1122
- accessTokenExpiresAt: field.dateTime({ isOptional: true }),
1123
- refreshTokenExpiresAt: field.dateTime({ isOptional: true }),
1124
- scope: field.string({ isOptional: true }),
1125
- password: field.string({
1126
- isOptional: true,
1127
- description: "Hashed password for password providers"
1128
- }),
1129
- createdAt: field.createdAt(),
1130
- updatedAt: field.updatedAt(),
1131
- user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1132
- },
1133
- indexes: [index.unique(["accountId", "providerId"])]
1134
- });
1135
- var VerificationEntity = defineEntity({
1136
- name: "Verification",
1137
- description: "Verification tokens for email/phone confirmation.",
1138
- schema: "lssm_sigil",
1139
- map: "verification",
1140
- fields: {
1141
- id: field.uuid(),
1142
- identifier: field.string({ description: "Email or phone being verified" }),
1143
- value: field.string({ description: "Verification code/token" }),
1144
- expiresAt: field.dateTime({ description: "Token expiration" }),
1145
- createdAt: field.createdAt(),
1146
- updatedAt: field.updatedAt()
1147
- }
1148
- });
1149
-
1150
987
  // src/entities/organization.ts
1151
988
  import {
1152
- defineEntity as defineEntity2,
989
+ defineEntity,
1153
990
  defineEntityEnum,
1154
- field as field2,
1155
- index as index2
991
+ field,
992
+ index
1156
993
  } from "@contractspec/lib.schema";
1157
994
  var OrganizationTypeEnum = defineEntityEnum({
1158
995
  name: "OrganizationType",
@@ -1160,251 +997,414 @@ var OrganizationTypeEnum = defineEntityEnum({
1160
997
  schema: "lssm_sigil",
1161
998
  description: "Type of organization in the platform."
1162
999
  });
1163
- var OrganizationEntity = defineEntity2({
1000
+ var OrganizationEntity = defineEntity({
1164
1001
  name: "Organization",
1165
1002
  description: "An organization is a tenant boundary grouping users.",
1166
1003
  schema: "lssm_sigil",
1167
1004
  map: "organization",
1168
1005
  fields: {
1169
- id: field2.id({ description: "Unique organization identifier" }),
1170
- name: field2.string({ description: "Organization display name" }),
1171
- slug: field2.string({
1006
+ id: field.id({ description: "Unique organization identifier" }),
1007
+ name: field.string({ description: "Organization display name" }),
1008
+ slug: field.string({
1172
1009
  isOptional: true,
1173
1010
  isUnique: true,
1174
1011
  description: "URL-friendly identifier"
1175
1012
  }),
1176
- logo: field2.url({ isOptional: true, description: "Organization logo URL" }),
1177
- description: field2.string({
1013
+ logo: field.url({ isOptional: true, description: "Organization logo URL" }),
1014
+ description: field.string({
1178
1015
  isOptional: true,
1179
1016
  description: "Organization description"
1180
1017
  }),
1181
- metadata: field2.json({
1018
+ metadata: field.json({
1182
1019
  isOptional: true,
1183
1020
  description: "Arbitrary organization metadata"
1184
1021
  }),
1185
- type: field2.enum("OrganizationType", { description: "Organization type" }),
1186
- onboardingCompleted: field2.boolean({ default: false }),
1187
- onboardingStep: field2.string({ isOptional: true }),
1188
- referralCode: field2.string({
1022
+ type: field.enum("OrganizationType", { description: "Organization type" }),
1023
+ onboardingCompleted: field.boolean({ default: false }),
1024
+ onboardingStep: field.string({ isOptional: true }),
1025
+ referralCode: field.string({
1189
1026
  isOptional: true,
1190
1027
  isUnique: true,
1191
1028
  description: "Unique referral code"
1192
1029
  }),
1193
- referredBy: field2.string({
1030
+ referredBy: field.string({
1194
1031
  isOptional: true,
1195
1032
  description: "ID of referring user"
1196
1033
  }),
1197
- createdAt: field2.createdAt(),
1198
- updatedAt: field2.updatedAt(),
1199
- members: field2.hasMany("Member"),
1200
- invitations: field2.hasMany("Invitation"),
1201
- teams: field2.hasMany("Team"),
1202
- policyBindings: field2.hasMany("PolicyBinding")
1034
+ createdAt: field.createdAt(),
1035
+ updatedAt: field.updatedAt(),
1036
+ members: field.hasMany("Member"),
1037
+ invitations: field.hasMany("Invitation"),
1038
+ teams: field.hasMany("Team"),
1039
+ policyBindings: field.hasMany("PolicyBinding")
1203
1040
  },
1204
1041
  enums: [OrganizationTypeEnum]
1205
1042
  });
1206
- var MemberEntity = defineEntity2({
1043
+ var MemberEntity = defineEntity({
1207
1044
  name: "Member",
1208
1045
  description: "Membership of a user in an organization with a role.",
1209
1046
  schema: "lssm_sigil",
1210
1047
  map: "member",
1211
1048
  fields: {
1212
- id: field2.id(),
1213
- userId: field2.foreignKey(),
1214
- organizationId: field2.foreignKey(),
1215
- role: field2.string({
1049
+ id: field.id(),
1050
+ userId: field.foreignKey(),
1051
+ organizationId: field.foreignKey(),
1052
+ role: field.string({
1216
1053
  description: "Role in organization (owner, admin, member)"
1217
1054
  }),
1218
- createdAt: field2.createdAt(),
1219
- user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" }),
1220
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
1055
+ createdAt: field.createdAt(),
1056
+ user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" }),
1057
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
1221
1058
  onDelete: "Cascade"
1222
1059
  })
1223
1060
  },
1224
- indexes: [index2.unique(["userId", "organizationId"])]
1061
+ indexes: [index.unique(["userId", "organizationId"])]
1225
1062
  });
1226
- var InvitationEntity = defineEntity2({
1063
+ var InvitationEntity = defineEntity({
1227
1064
  name: "Invitation",
1228
1065
  description: "An invitation to join an organization.",
1229
1066
  schema: "lssm_sigil",
1230
1067
  map: "invitation",
1231
1068
  fields: {
1232
- id: field2.id(),
1233
- organizationId: field2.foreignKey(),
1234
- email: field2.email({ description: "Invited email address" }),
1235
- role: field2.string({
1069
+ id: field.id(),
1070
+ organizationId: field.foreignKey(),
1071
+ email: field.email({ description: "Invited email address" }),
1072
+ role: field.string({
1236
1073
  isOptional: true,
1237
1074
  description: "Role to assign on acceptance"
1238
1075
  }),
1239
- status: field2.string({
1076
+ status: field.string({
1240
1077
  default: '"pending"',
1241
1078
  description: "Invitation status"
1242
1079
  }),
1243
- acceptedAt: field2.dateTime({ isOptional: true }),
1244
- expiresAt: field2.dateTime({ isOptional: true }),
1245
- inviterId: field2.foreignKey({
1080
+ acceptedAt: field.dateTime({ isOptional: true }),
1081
+ expiresAt: field.dateTime({ isOptional: true }),
1082
+ inviterId: field.foreignKey({
1246
1083
  description: "User who sent the invitation"
1247
1084
  }),
1248
- teamId: field2.string({ isOptional: true }),
1249
- createdAt: field2.createdAt(),
1250
- updatedAt: field2.updatedAt(),
1251
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
1085
+ teamId: field.string({ isOptional: true }),
1086
+ createdAt: field.createdAt(),
1087
+ updatedAt: field.updatedAt(),
1088
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
1252
1089
  onDelete: "Cascade"
1253
1090
  }),
1254
- inviter: field2.belongsTo("User", ["inviterId"], ["id"], {
1091
+ inviter: field.belongsTo("User", ["inviterId"], ["id"], {
1255
1092
  onDelete: "Cascade"
1256
1093
  }),
1257
- team: field2.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
1094
+ team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
1258
1095
  }
1259
1096
  });
1260
- var TeamEntity = defineEntity2({
1097
+ var TeamEntity = defineEntity({
1261
1098
  name: "Team",
1262
1099
  description: "Team within an organization.",
1263
1100
  schema: "lssm_sigil",
1264
1101
  map: "team",
1265
1102
  fields: {
1266
- id: field2.id(),
1267
- name: field2.string({ description: "Team name" }),
1268
- organizationId: field2.foreignKey(),
1269
- createdAt: field2.createdAt(),
1270
- updatedAt: field2.updatedAt(),
1271
- organization: field2.belongsTo("Organization", ["organizationId"], ["id"], {
1103
+ id: field.id(),
1104
+ name: field.string({ description: "Team name" }),
1105
+ organizationId: field.foreignKey(),
1106
+ createdAt: field.createdAt(),
1107
+ updatedAt: field.updatedAt(),
1108
+ organization: field.belongsTo("Organization", ["organizationId"], ["id"], {
1272
1109
  onDelete: "Cascade"
1273
1110
  }),
1274
- members: field2.hasMany("TeamMember"),
1275
- invitations: field2.hasMany("Invitation")
1111
+ members: field.hasMany("TeamMember"),
1112
+ invitations: field.hasMany("Invitation")
1276
1113
  }
1277
1114
  });
1278
- var TeamMemberEntity = defineEntity2({
1115
+ var TeamMemberEntity = defineEntity({
1279
1116
  name: "TeamMember",
1280
1117
  description: "Team membership for a user.",
1281
1118
  schema: "lssm_sigil",
1282
1119
  map: "team_member",
1283
1120
  fields: {
1284
- id: field2.id(),
1285
- teamId: field2.foreignKey(),
1286
- userId: field2.foreignKey(),
1287
- createdAt: field2.createdAt(),
1288
- team: field2.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" }),
1289
- user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1121
+ id: field.id(),
1122
+ teamId: field.foreignKey(),
1123
+ userId: field.foreignKey(),
1124
+ createdAt: field.createdAt(),
1125
+ team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" }),
1126
+ user: field.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1290
1127
  }
1291
1128
  });
1292
1129
 
1293
1130
  // src/entities/rbac.ts
1294
- import { defineEntity as defineEntity3, field as field3, index as index3 } from "@contractspec/lib.schema";
1295
- var RoleEntity = defineEntity3({
1131
+ import { defineEntity as defineEntity2, field as field2, index as index2 } from "@contractspec/lib.schema";
1132
+ var RoleEntity = defineEntity2({
1296
1133
  name: "Role",
1297
1134
  description: "A role defines a named set of permissions.",
1298
1135
  schema: "lssm_sigil",
1299
1136
  map: "role",
1300
1137
  fields: {
1301
- id: field3.id(),
1302
- name: field3.string({ isUnique: true, description: "Unique role name" }),
1303
- description: field3.string({
1138
+ id: field2.id(),
1139
+ name: field2.string({ isUnique: true, description: "Unique role name" }),
1140
+ description: field2.string({
1304
1141
  isOptional: true,
1305
1142
  description: "Role description"
1306
1143
  }),
1307
- permissions: field3.string({
1144
+ permissions: field2.string({
1308
1145
  isArray: true,
1309
1146
  description: "Array of permission names"
1310
1147
  }),
1311
- createdAt: field3.createdAt(),
1312
- updatedAt: field3.updatedAt(),
1313
- policyBindings: field3.hasMany("PolicyBinding")
1148
+ createdAt: field2.createdAt(),
1149
+ updatedAt: field2.updatedAt(),
1150
+ policyBindings: field2.hasMany("PolicyBinding")
1314
1151
  }
1315
1152
  });
1316
- var PermissionEntity = defineEntity3({
1153
+ var PermissionEntity = defineEntity2({
1317
1154
  name: "Permission",
1318
1155
  description: "A permission represents an atomic access right.",
1319
1156
  schema: "lssm_sigil",
1320
1157
  map: "permission",
1321
1158
  fields: {
1322
- id: field3.id(),
1323
- name: field3.string({
1159
+ id: field2.id(),
1160
+ name: field2.string({
1324
1161
  isUnique: true,
1325
1162
  description: "Unique permission name"
1326
1163
  }),
1327
- description: field3.string({
1164
+ description: field2.string({
1328
1165
  isOptional: true,
1329
1166
  description: "Permission description"
1330
1167
  }),
1331
- createdAt: field3.createdAt(),
1332
- updatedAt: field3.updatedAt()
1168
+ createdAt: field2.createdAt(),
1169
+ updatedAt: field2.updatedAt()
1333
1170
  }
1334
1171
  });
1335
- var PolicyBindingEntity = defineEntity3({
1172
+ var PolicyBindingEntity = defineEntity2({
1336
1173
  name: "PolicyBinding",
1337
1174
  description: "Binds roles to principals (users or organizations).",
1338
1175
  schema: "lssm_sigil",
1339
1176
  map: "policy_binding",
1340
1177
  fields: {
1341
- id: field3.id(),
1342
- roleId: field3.foreignKey(),
1343
- targetType: field3.string({ description: '"user" or "organization"' }),
1344
- targetId: field3.string({ description: "ID of User or Organization" }),
1345
- expiresAt: field3.dateTime({
1178
+ id: field2.id(),
1179
+ roleId: field2.foreignKey(),
1180
+ targetType: field2.string({ description: '"user" or "organization"' }),
1181
+ targetId: field2.string({ description: "ID of User or Organization" }),
1182
+ expiresAt: field2.dateTime({
1346
1183
  isOptional: true,
1347
1184
  description: "When binding expires"
1348
1185
  }),
1349
- createdAt: field3.createdAt(),
1350
- userId: field3.string({ isOptional: true }),
1351
- organizationId: field3.string({ isOptional: true }),
1352
- role: field3.belongsTo("Role", ["roleId"], ["id"], { onDelete: "Cascade" }),
1353
- user: field3.belongsTo("User", ["userId"], ["id"]),
1354
- organization: field3.belongsTo("Organization", ["organizationId"], ["id"])
1186
+ createdAt: field2.createdAt(),
1187
+ userId: field2.string({ isOptional: true }),
1188
+ organizationId: field2.string({ isOptional: true }),
1189
+ role: field2.belongsTo("Role", ["roleId"], ["id"], { onDelete: "Cascade" }),
1190
+ user: field2.belongsTo("User", ["userId"], ["id"]),
1191
+ organization: field2.belongsTo("Organization", ["organizationId"], ["id"])
1355
1192
  },
1356
- indexes: [index3.on(["targetType", "targetId"])]
1193
+ indexes: [index2.on(["targetType", "targetId"])]
1357
1194
  });
1358
- var ApiKeyEntity = defineEntity3({
1195
+ var ApiKeyEntity = defineEntity2({
1359
1196
  name: "ApiKey",
1360
1197
  description: "API keys for programmatic access.",
1361
1198
  schema: "lssm_sigil",
1362
1199
  map: "api_key",
1363
1200
  fields: {
1364
- id: field3.id(),
1365
- name: field3.string({ description: "API key name" }),
1366
- start: field3.string({
1201
+ id: field2.id(),
1202
+ name: field2.string({ description: "API key name" }),
1203
+ start: field2.string({
1367
1204
  description: "Starting characters for identification"
1368
1205
  }),
1369
- prefix: field3.string({ description: "API key prefix" }),
1370
- key: field3.string({ description: "Hashed API key" }),
1206
+ prefix: field2.string({ description: "API key prefix" }),
1207
+ key: field2.string({ description: "Hashed API key" }),
1208
+ userId: field2.foreignKey(),
1209
+ refillInterval: field2.int({ description: "Refill interval in ms" }),
1210
+ refillAmount: field2.int({ description: "Amount to refill" }),
1211
+ lastRefillAt: field2.dateTime(),
1212
+ remaining: field2.int({ description: "Remaining requests" }),
1213
+ requestCount: field2.int({ description: "Total requests made" }),
1214
+ lastRequest: field2.dateTime(),
1215
+ enabled: field2.boolean({ default: true }),
1216
+ rateLimitEnabled: field2.boolean({ default: true }),
1217
+ rateLimitTimeWindow: field2.int({ description: "Rate limit window in ms" }),
1218
+ rateLimitMax: field2.int({ description: "Max requests in window" }),
1219
+ expiresAt: field2.dateTime(),
1220
+ permissions: field2.string({ isArray: true }),
1221
+ metadata: field2.json({ isOptional: true }),
1222
+ createdAt: field2.createdAt(),
1223
+ updatedAt: field2.updatedAt(),
1224
+ user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1225
+ }
1226
+ });
1227
+ var PasskeyEntity = defineEntity2({
1228
+ name: "Passkey",
1229
+ description: "WebAuthn passkeys for passwordless authentication.",
1230
+ schema: "lssm_sigil",
1231
+ map: "passkey",
1232
+ fields: {
1233
+ id: field2.id(),
1234
+ name: field2.string({ description: "Passkey name" }),
1235
+ publicKey: field2.string({ description: "Public key" }),
1236
+ userId: field2.foreignKey(),
1237
+ credentialID: field2.string({ description: "Credential ID" }),
1238
+ counter: field2.int({ description: "Counter" }),
1239
+ deviceType: field2.string({ description: "Device type" }),
1240
+ backedUp: field2.boolean({ description: "Whether passkey is backed up" }),
1241
+ transports: field2.string({ description: "Transports" }),
1242
+ aaguid: field2.string({ description: "Authenticator GUID" }),
1243
+ createdAt: field2.createdAt(),
1244
+ user: field2.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1245
+ }
1246
+ });
1247
+
1248
+ // src/entities/user.ts
1249
+ import { defineEntity as defineEntity3, field as field3, index as index3 } from "@contractspec/lib.schema";
1250
+ var UserEntity = defineEntity3({
1251
+ name: "User",
1252
+ description: "A user of the platform. Users hold core profile information and authenticate via Account records.",
1253
+ schema: "lssm_sigil",
1254
+ map: "user",
1255
+ fields: {
1256
+ id: field3.id({ description: "Unique user identifier" }),
1257
+ email: field3.email({ isUnique: true, description: "User email address" }),
1258
+ emailVerified: field3.boolean({
1259
+ default: false,
1260
+ description: "Whether email has been verified"
1261
+ }),
1262
+ name: field3.string({ isOptional: true, description: "Display name" }),
1263
+ firstName: field3.string({ isOptional: true, description: "First name" }),
1264
+ lastName: field3.string({ isOptional: true, description: "Last name" }),
1265
+ locale: field3.string({
1266
+ isOptional: true,
1267
+ description: 'User locale (e.g., "en-US")'
1268
+ }),
1269
+ timezone: field3.string({
1270
+ isOptional: true,
1271
+ description: 'Olson timezone (e.g., "Europe/Paris")'
1272
+ }),
1273
+ imageUrl: field3.url({
1274
+ isOptional: true,
1275
+ description: "URL of avatar or profile picture"
1276
+ }),
1277
+ image: field3.string({
1278
+ isOptional: true,
1279
+ description: "Legacy image field"
1280
+ }),
1281
+ metadata: field3.json({
1282
+ isOptional: true,
1283
+ description: "Arbitrary user metadata"
1284
+ }),
1285
+ onboardingCompleted: field3.boolean({
1286
+ default: false,
1287
+ description: "Whether onboarding is complete"
1288
+ }),
1289
+ onboardingStep: field3.string({
1290
+ isOptional: true,
1291
+ description: "Current onboarding step"
1292
+ }),
1293
+ whitelistedAt: field3.dateTime({
1294
+ isOptional: true,
1295
+ description: "When user was whitelisted"
1296
+ }),
1297
+ role: field3.string({
1298
+ isOptional: true,
1299
+ default: '"user"',
1300
+ description: "User role (user, admin)"
1301
+ }),
1302
+ banned: field3.boolean({
1303
+ default: false,
1304
+ description: "Whether user is banned"
1305
+ }),
1306
+ banReason: field3.string({
1307
+ isOptional: true,
1308
+ description: "Reason for ban"
1309
+ }),
1310
+ banExpires: field3.dateTime({
1311
+ isOptional: true,
1312
+ description: "When ban expires"
1313
+ }),
1314
+ phoneNumber: field3.string({
1315
+ isOptional: true,
1316
+ isUnique: true,
1317
+ description: "Phone number"
1318
+ }),
1319
+ phoneNumberVerified: field3.boolean({
1320
+ default: false,
1321
+ description: "Whether phone is verified"
1322
+ }),
1323
+ createdAt: field3.createdAt(),
1324
+ updatedAt: field3.updatedAt(),
1325
+ sessions: field3.hasMany("Session"),
1326
+ accounts: field3.hasMany("Account"),
1327
+ memberships: field3.hasMany("Member"),
1328
+ invitations: field3.hasMany("Invitation"),
1329
+ teamMemberships: field3.hasMany("TeamMember"),
1330
+ policyBindings: field3.hasMany("PolicyBinding"),
1331
+ apiKeys: field3.hasMany("ApiKey"),
1332
+ passkeys: field3.hasMany("Passkey")
1333
+ }
1334
+ });
1335
+ var SessionEntity = defineEntity3({
1336
+ name: "Session",
1337
+ description: "Represents a login session (e.g., web session or API token).",
1338
+ schema: "lssm_sigil",
1339
+ map: "session",
1340
+ fields: {
1341
+ id: field3.id(),
1371
1342
  userId: field3.foreignKey(),
1372
- refillInterval: field3.int({ description: "Refill interval in ms" }),
1373
- refillAmount: field3.int({ description: "Amount to refill" }),
1374
- lastRefillAt: field3.dateTime(),
1375
- remaining: field3.int({ description: "Remaining requests" }),
1376
- requestCount: field3.int({ description: "Total requests made" }),
1377
- lastRequest: field3.dateTime(),
1378
- enabled: field3.boolean({ default: true }),
1379
- rateLimitEnabled: field3.boolean({ default: true }),
1380
- rateLimitTimeWindow: field3.int({ description: "Rate limit window in ms" }),
1381
- rateLimitMax: field3.int({ description: "Max requests in window" }),
1382
- expiresAt: field3.dateTime(),
1383
- permissions: field3.string({ isArray: true }),
1384
- metadata: field3.json({ isOptional: true }),
1343
+ expiresAt: field3.dateTime({ description: "Session expiration time" }),
1344
+ token: field3.string({ isUnique: true, description: "Session token" }),
1345
+ ipAddress: field3.string({
1346
+ isOptional: true,
1347
+ description: "Client IP address"
1348
+ }),
1349
+ userAgent: field3.string({
1350
+ isOptional: true,
1351
+ description: "Client user agent"
1352
+ }),
1353
+ impersonatedBy: field3.string({
1354
+ isOptional: true,
1355
+ description: "Admin impersonating this session"
1356
+ }),
1357
+ activeOrganizationId: field3.string({
1358
+ isOptional: true,
1359
+ description: "Active org context"
1360
+ }),
1361
+ activeTeamId: field3.string({
1362
+ isOptional: true,
1363
+ description: "Active team context"
1364
+ }),
1385
1365
  createdAt: field3.createdAt(),
1386
1366
  updatedAt: field3.updatedAt(),
1387
1367
  user: field3.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1388
1368
  }
1389
1369
  });
1390
- var PasskeyEntity = defineEntity3({
1391
- name: "Passkey",
1392
- description: "WebAuthn passkeys for passwordless authentication.",
1370
+ var AccountEntity = defineEntity3({
1371
+ name: "Account",
1372
+ description: "External authentication accounts (OAuth, password, etc.).",
1393
1373
  schema: "lssm_sigil",
1394
- map: "passkey",
1374
+ map: "account",
1395
1375
  fields: {
1396
1376
  id: field3.id(),
1397
- name: field3.string({ description: "Passkey name" }),
1398
- publicKey: field3.string({ description: "Public key" }),
1377
+ accountId: field3.string({ description: "Account ID from provider" }),
1378
+ providerId: field3.string({ description: "Provider identifier" }),
1399
1379
  userId: field3.foreignKey(),
1400
- credentialID: field3.string({ description: "Credential ID" }),
1401
- counter: field3.int({ description: "Counter" }),
1402
- deviceType: field3.string({ description: "Device type" }),
1403
- backedUp: field3.boolean({ description: "Whether passkey is backed up" }),
1404
- transports: field3.string({ description: "Transports" }),
1405
- aaguid: field3.string({ description: "Authenticator GUID" }),
1380
+ accessToken: field3.string({ isOptional: true }),
1381
+ refreshToken: field3.string({ isOptional: true }),
1382
+ idToken: field3.string({ isOptional: true }),
1383
+ accessTokenExpiresAt: field3.dateTime({ isOptional: true }),
1384
+ refreshTokenExpiresAt: field3.dateTime({ isOptional: true }),
1385
+ scope: field3.string({ isOptional: true }),
1386
+ password: field3.string({
1387
+ isOptional: true,
1388
+ description: "Hashed password for password providers"
1389
+ }),
1406
1390
  createdAt: field3.createdAt(),
1391
+ updatedAt: field3.updatedAt(),
1407
1392
  user: field3.belongsTo("User", ["userId"], ["id"], { onDelete: "Cascade" })
1393
+ },
1394
+ indexes: [index3.unique(["accountId", "providerId"])]
1395
+ });
1396
+ var VerificationEntity = defineEntity3({
1397
+ name: "Verification",
1398
+ description: "Verification tokens for email/phone confirmation.",
1399
+ schema: "lssm_sigil",
1400
+ map: "verification",
1401
+ fields: {
1402
+ id: field3.uuid(),
1403
+ identifier: field3.string({ description: "Email or phone being verified" }),
1404
+ value: field3.string({ description: "Verification code/token" }),
1405
+ expiresAt: field3.dateTime({ description: "Token expiration" }),
1406
+ createdAt: field3.createdAt(),
1407
+ updatedAt: field3.updatedAt()
1408
1408
  }
1409
1409
  });
1410
1410
  // src/entities/index.ts
@@ -1431,8 +1431,8 @@ var identityRbacSchemaContribution = {
1431
1431
  };
1432
1432
 
1433
1433
  // src/events.ts
1434
- import { SchemaModel as SchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
1435
1434
  import { defineEvent } from "@contractspec/lib.contracts-spec";
1435
+ import { ScalarTypeEnum as ScalarTypeEnum4, SchemaModel as SchemaModel4 } from "@contractspec/lib.schema";
1436
1436
  var UserCreatedPayload = new SchemaModel4({
1437
1437
  name: "UserCreatedPayload",
1438
1438
  description: "Payload for user created event",