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