@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/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/browser/index.js
CHANGED
|
@@ -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
|
|
989
|
+
defineEntity,
|
|
1153
990
|
defineEntityEnum,
|
|
1154
|
-
field
|
|
1155
|
-
index
|
|
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 =
|
|
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:
|
|
1170
|
-
name:
|
|
1171
|
-
slug:
|
|
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:
|
|
1177
|
-
description:
|
|
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:
|
|
1018
|
+
metadata: field.json({
|
|
1182
1019
|
isOptional: true,
|
|
1183
1020
|
description: "Arbitrary organization metadata"
|
|
1184
1021
|
}),
|
|
1185
|
-
type:
|
|
1186
|
-
onboardingCompleted:
|
|
1187
|
-
onboardingStep:
|
|
1188
|
-
referralCode:
|
|
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:
|
|
1030
|
+
referredBy: field.string({
|
|
1194
1031
|
isOptional: true,
|
|
1195
1032
|
description: "ID of referring user"
|
|
1196
1033
|
}),
|
|
1197
|
-
createdAt:
|
|
1198
|
-
updatedAt:
|
|
1199
|
-
members:
|
|
1200
|
-
invitations:
|
|
1201
|
-
teams:
|
|
1202
|
-
policyBindings:
|
|
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 =
|
|
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:
|
|
1213
|
-
userId:
|
|
1214
|
-
organizationId:
|
|
1215
|
-
role:
|
|
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:
|
|
1219
|
-
user:
|
|
1220
|
-
organization:
|
|
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: [
|
|
1061
|
+
indexes: [index.unique(["userId", "organizationId"])]
|
|
1225
1062
|
});
|
|
1226
|
-
var InvitationEntity =
|
|
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:
|
|
1233
|
-
organizationId:
|
|
1234
|
-
email:
|
|
1235
|
-
role:
|
|
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:
|
|
1076
|
+
status: field.string({
|
|
1240
1077
|
default: '"pending"',
|
|
1241
1078
|
description: "Invitation status"
|
|
1242
1079
|
}),
|
|
1243
|
-
acceptedAt:
|
|
1244
|
-
expiresAt:
|
|
1245
|
-
inviterId:
|
|
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:
|
|
1249
|
-
createdAt:
|
|
1250
|
-
updatedAt:
|
|
1251
|
-
organization:
|
|
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:
|
|
1091
|
+
inviter: field.belongsTo("User", ["inviterId"], ["id"], {
|
|
1255
1092
|
onDelete: "Cascade"
|
|
1256
1093
|
}),
|
|
1257
|
-
team:
|
|
1094
|
+
team: field.belongsTo("Team", ["teamId"], ["id"], { onDelete: "Cascade" })
|
|
1258
1095
|
}
|
|
1259
1096
|
});
|
|
1260
|
-
var TeamEntity =
|
|
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:
|
|
1267
|
-
name:
|
|
1268
|
-
organizationId:
|
|
1269
|
-
createdAt:
|
|
1270
|
-
updatedAt:
|
|
1271
|
-
organization:
|
|
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:
|
|
1275
|
-
invitations:
|
|
1111
|
+
members: field.hasMany("TeamMember"),
|
|
1112
|
+
invitations: field.hasMany("Invitation")
|
|
1276
1113
|
}
|
|
1277
1114
|
});
|
|
1278
|
-
var TeamMemberEntity =
|
|
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:
|
|
1285
|
-
teamId:
|
|
1286
|
-
userId:
|
|
1287
|
-
createdAt:
|
|
1288
|
-
team:
|
|
1289
|
-
user:
|
|
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
|
|
1295
|
-
var RoleEntity =
|
|
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:
|
|
1302
|
-
name:
|
|
1303
|
-
description:
|
|
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:
|
|
1144
|
+
permissions: field2.string({
|
|
1308
1145
|
isArray: true,
|
|
1309
1146
|
description: "Array of permission names"
|
|
1310
1147
|
}),
|
|
1311
|
-
createdAt:
|
|
1312
|
-
updatedAt:
|
|
1313
|
-
policyBindings:
|
|
1148
|
+
createdAt: field2.createdAt(),
|
|
1149
|
+
updatedAt: field2.updatedAt(),
|
|
1150
|
+
policyBindings: field2.hasMany("PolicyBinding")
|
|
1314
1151
|
}
|
|
1315
1152
|
});
|
|
1316
|
-
var PermissionEntity =
|
|
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:
|
|
1323
|
-
name:
|
|
1159
|
+
id: field2.id(),
|
|
1160
|
+
name: field2.string({
|
|
1324
1161
|
isUnique: true,
|
|
1325
1162
|
description: "Unique permission name"
|
|
1326
1163
|
}),
|
|
1327
|
-
description:
|
|
1164
|
+
description: field2.string({
|
|
1328
1165
|
isOptional: true,
|
|
1329
1166
|
description: "Permission description"
|
|
1330
1167
|
}),
|
|
1331
|
-
createdAt:
|
|
1332
|
-
updatedAt:
|
|
1168
|
+
createdAt: field2.createdAt(),
|
|
1169
|
+
updatedAt: field2.updatedAt()
|
|
1333
1170
|
}
|
|
1334
1171
|
});
|
|
1335
|
-
var PolicyBindingEntity =
|
|
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:
|
|
1342
|
-
roleId:
|
|
1343
|
-
targetType:
|
|
1344
|
-
targetId:
|
|
1345
|
-
expiresAt:
|
|
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:
|
|
1350
|
-
userId:
|
|
1351
|
-
organizationId:
|
|
1352
|
-
role:
|
|
1353
|
-
user:
|
|
1354
|
-
organization:
|
|
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: [
|
|
1193
|
+
indexes: [index2.on(["targetType", "targetId"])]
|
|
1357
1194
|
});
|
|
1358
|
-
var ApiKeyEntity =
|
|
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:
|
|
1365
|
-
name:
|
|
1366
|
-
start:
|
|
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:
|
|
1370
|
-
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
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
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
|
|
1391
|
-
name: "
|
|
1392
|
-
description: "
|
|
1370
|
+
var AccountEntity = defineEntity3({
|
|
1371
|
+
name: "Account",
|
|
1372
|
+
description: "External authentication accounts (OAuth, password, etc.).",
|
|
1393
1373
|
schema: "lssm_sigil",
|
|
1394
|
-
map: "
|
|
1374
|
+
map: "account",
|
|
1395
1375
|
fields: {
|
|
1396
1376
|
id: field3.id(),
|
|
1397
|
-
|
|
1398
|
-
|
|
1377
|
+
accountId: field3.string({ description: "Account ID from provider" }),
|
|
1378
|
+
providerId: field3.string({ description: "Provider identifier" }),
|
|
1399
1379
|
userId: field3.foreignKey(),
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
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",
|