@contractspec/lib.identity-rbac 3.7.5 → 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.
- package/README.md +62 -90
- package/dist/browser/contracts/index.js +3 -3
- package/dist/browser/contracts/organization.js +2 -2
- package/dist/browser/contracts/rbac.js +2 -2
- package/dist/browser/contracts/user.js +1 -1
- package/dist/browser/entities/index.js +283 -283
- package/dist/browser/events.js +1 -1
- package/dist/browser/index.js +287 -287
- package/dist/contracts/index.d.ts +3 -3
- package/dist/contracts/index.js +3 -3
- package/dist/contracts/organization.js +2 -2
- package/dist/contracts/rbac.js +2 -2
- package/dist/contracts/user.js +1 -1
- package/dist/entities/index.d.ts +69 -69
- package/dist/entities/index.js +283 -283
- package/dist/events.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +287 -287
- package/dist/node/contracts/index.js +3 -3
- package/dist/node/contracts/organization.js +2 -2
- package/dist/node/contracts/rbac.js +2 -2
- package/dist/node/contracts/user.js +1 -1
- package/dist/node/entities/index.js +283 -283
- package/dist/node/events.js +1 -1
- package/dist/node/index.js +287 -287
- package/dist/policies/index.d.ts +1 -1
- package/package.json +7 -7
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
|
|
990
|
+
defineEntity,
|
|
1154
991
|
defineEntityEnum,
|
|
1155
|
-
field
|
|
1156
|
-
index
|
|
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 =
|
|
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:
|
|
1171
|
-
name:
|
|
1172
|
-
slug:
|
|
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:
|
|
1178
|
-
description:
|
|
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:
|
|
1019
|
+
metadata: field.json({
|
|
1183
1020
|
isOptional: true,
|
|
1184
1021
|
description: "Arbitrary organization metadata"
|
|
1185
1022
|
}),
|
|
1186
|
-
type:
|
|
1187
|
-
onboardingCompleted:
|
|
1188
|
-
onboardingStep:
|
|
1189
|
-
referralCode:
|
|
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:
|
|
1031
|
+
referredBy: field.string({
|
|
1195
1032
|
isOptional: true,
|
|
1196
1033
|
description: "ID of referring user"
|
|
1197
1034
|
}),
|
|
1198
|
-
createdAt:
|
|
1199
|
-
updatedAt:
|
|
1200
|
-
members:
|
|
1201
|
-
invitations:
|
|
1202
|
-
teams:
|
|
1203
|
-
policyBindings:
|
|
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 =
|
|
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:
|
|
1214
|
-
userId:
|
|
1215
|
-
organizationId:
|
|
1216
|
-
role:
|
|
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:
|
|
1220
|
-
user:
|
|
1221
|
-
organization:
|
|
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: [
|
|
1062
|
+
indexes: [index.unique(["userId", "organizationId"])]
|
|
1226
1063
|
});
|
|
1227
|
-
var InvitationEntity =
|
|
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:
|
|
1234
|
-
organizationId:
|
|
1235
|
-
email:
|
|
1236
|
-
role:
|
|
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:
|
|
1077
|
+
status: field.string({
|
|
1241
1078
|
default: '"pending"',
|
|
1242
1079
|
description: "Invitation status"
|
|
1243
1080
|
}),
|
|
1244
|
-
acceptedAt:
|
|
1245
|
-
expiresAt:
|
|
1246
|
-
inviterId:
|
|
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:
|
|
1250
|
-
createdAt:
|
|
1251
|
-
updatedAt:
|
|
1252
|
-
organization:
|
|
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:
|
|
1092
|
+
inviter: field.belongsTo("User", ["inviterId"], ["id"], {
|
|
1256
1093
|
onDelete: "Cascade"
|
|
1257
1094
|
}),
|
|
1258
|
-
team:
|
|
1095
|
+
team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
|
|
1259
1096
|
}
|
|
1260
1097
|
});
|
|
1261
|
-
var TeamEntity =
|
|
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:
|
|
1268
|
-
name:
|
|
1269
|
-
organizationId:
|
|
1270
|
-
createdAt:
|
|
1271
|
-
updatedAt:
|
|
1272
|
-
organization:
|
|
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:
|
|
1276
|
-
invitations:
|
|
1112
|
+
members: field.hasMany("TeamMember"),
|
|
1113
|
+
invitations: field.hasMany("Invitation")
|
|
1277
1114
|
}
|
|
1278
1115
|
});
|
|
1279
|
-
var TeamMemberEntity =
|
|
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:
|
|
1286
|
-
teamId:
|
|
1287
|
-
userId:
|
|
1288
|
-
createdAt:
|
|
1289
|
-
team:
|
|
1290
|
-
user:
|
|
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
|
|
1296
|
-
var RoleEntity =
|
|
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:
|
|
1303
|
-
name:
|
|
1304
|
-
description:
|
|
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:
|
|
1145
|
+
permissions: field2.string({
|
|
1309
1146
|
isArray: true,
|
|
1310
1147
|
description: "Array of permission names"
|
|
1311
1148
|
}),
|
|
1312
|
-
createdAt:
|
|
1313
|
-
updatedAt:
|
|
1314
|
-
policyBindings:
|
|
1149
|
+
createdAt: field2.createdAt(),
|
|
1150
|
+
updatedAt: field2.updatedAt(),
|
|
1151
|
+
policyBindings: field2.hasMany("PolicyBinding")
|
|
1315
1152
|
}
|
|
1316
1153
|
});
|
|
1317
|
-
var PermissionEntity =
|
|
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:
|
|
1324
|
-
name:
|
|
1160
|
+
id: field2.id(),
|
|
1161
|
+
name: field2.string({
|
|
1325
1162
|
isUnique: true,
|
|
1326
1163
|
description: "Unique permission name"
|
|
1327
1164
|
}),
|
|
1328
|
-
description:
|
|
1165
|
+
description: field2.string({
|
|
1329
1166
|
isOptional: true,
|
|
1330
1167
|
description: "Permission description"
|
|
1331
1168
|
}),
|
|
1332
|
-
createdAt:
|
|
1333
|
-
updatedAt:
|
|
1169
|
+
createdAt: field2.createdAt(),
|
|
1170
|
+
updatedAt: field2.updatedAt()
|
|
1334
1171
|
}
|
|
1335
1172
|
});
|
|
1336
|
-
var PolicyBindingEntity =
|
|
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:
|
|
1343
|
-
roleId:
|
|
1344
|
-
targetType:
|
|
1345
|
-
targetId:
|
|
1346
|
-
expiresAt:
|
|
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:
|
|
1351
|
-
userId:
|
|
1352
|
-
organizationId:
|
|
1353
|
-
role:
|
|
1354
|
-
user:
|
|
1355
|
-
organization:
|
|
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: [
|
|
1194
|
+
indexes: [index2.on(["targetType", "targetId"])]
|
|
1358
1195
|
});
|
|
1359
|
-
var ApiKeyEntity =
|
|
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:
|
|
1366
|
-
name:
|
|
1367
|
-
start:
|
|
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:
|
|
1371
|
-
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
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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
|
|
1392
|
-
name: "
|
|
1393
|
-
description: "
|
|
1371
|
+
var AccountEntity = defineEntity3({
|
|
1372
|
+
name: "Account",
|
|
1373
|
+
description: "External authentication accounts (OAuth, password, etc.).",
|
|
1394
1374
|
schema: "lssm_sigil",
|
|
1395
|
-
map: "
|
|
1375
|
+
map: "account",
|
|
1396
1376
|
fields: {
|
|
1397
1377
|
id: field3.id(),
|
|
1398
|
-
|
|
1399
|
-
|
|
1378
|
+
accountId: field3.string({ description: "Account ID from provider" }),
|
|
1379
|
+
providerId: field3.string({ description: "Provider identifier" }),
|
|
1400
1380
|
userId: field3.foreignKey(),
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
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",
|