@objectstack/plugin-auth 3.2.5 → 3.2.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/dist/index.mjs CHANGED
@@ -216,14 +216,16 @@ var AUTH_VERIFICATION_CONFIG = {
216
216
  }
217
217
  };
218
218
  var AUTH_ORGANIZATION_SCHEMA = {
219
- modelName: "sys_organization",
219
+ modelName: SystemObjectName2.ORGANIZATION,
220
+ // 'sys_organization'
220
221
  fields: {
221
222
  createdAt: "created_at",
222
223
  updatedAt: "updated_at"
223
224
  }
224
225
  };
225
226
  var AUTH_MEMBER_SCHEMA = {
226
- modelName: "sys_member",
227
+ modelName: SystemObjectName2.MEMBER,
228
+ // 'sys_member'
227
229
  fields: {
228
230
  organizationId: "organization_id",
229
231
  userId: "user_id",
@@ -231,7 +233,8 @@ var AUTH_MEMBER_SCHEMA = {
231
233
  }
232
234
  };
233
235
  var AUTH_INVITATION_SCHEMA = {
234
- modelName: "sys_invitation",
236
+ modelName: SystemObjectName2.INVITATION,
237
+ // 'sys_invitation'
235
238
  fields: {
236
239
  organizationId: "organization_id",
237
240
  inviterId: "inviter_id",
@@ -245,7 +248,8 @@ var AUTH_ORG_SESSION_FIELDS = {
245
248
  activeTeamId: "active_team_id"
246
249
  };
247
250
  var AUTH_TEAM_SCHEMA = {
248
- modelName: "sys_team",
251
+ modelName: SystemObjectName2.TEAM,
252
+ // 'sys_team'
249
253
  fields: {
250
254
  organizationId: "organization_id",
251
255
  createdAt: "created_at",
@@ -253,7 +257,8 @@ var AUTH_TEAM_SCHEMA = {
253
257
  }
254
258
  };
255
259
  var AUTH_TEAM_MEMBER_SCHEMA = {
256
- modelName: "sys_team_member",
260
+ modelName: SystemObjectName2.TEAM_MEMBER,
261
+ // 'sys_team_member'
257
262
  fields: {
258
263
  teamId: "team_id",
259
264
  userId: "user_id",
@@ -261,7 +266,8 @@ var AUTH_TEAM_MEMBER_SCHEMA = {
261
266
  }
262
267
  };
263
268
  var AUTH_TWO_FACTOR_SCHEMA = {
264
- modelName: "sys_two_factor",
269
+ modelName: SystemObjectName2.TWO_FACTOR,
270
+ // 'sys_two_factor'
265
271
  fields: {
266
272
  backupCodes: "backup_codes",
267
273
  userId: "user_id"
@@ -333,10 +339,28 @@ var AuthManager = class {
333
339
  verification: {
334
340
  ...AUTH_VERIFICATION_CONFIG
335
341
  },
336
- // Email configuration
342
+ // Social / OAuth providers
343
+ ...this.config.socialProviders ? { socialProviders: this.config.socialProviders } : {},
344
+ // Email and password configuration
337
345
  emailAndPassword: {
338
- enabled: true
346
+ enabled: this.config.emailAndPassword?.enabled ?? true,
347
+ ...this.config.emailAndPassword?.disableSignUp != null ? { disableSignUp: this.config.emailAndPassword.disableSignUp } : {},
348
+ ...this.config.emailAndPassword?.requireEmailVerification != null ? { requireEmailVerification: this.config.emailAndPassword.requireEmailVerification } : {},
349
+ ...this.config.emailAndPassword?.minPasswordLength != null ? { minPasswordLength: this.config.emailAndPassword.minPasswordLength } : {},
350
+ ...this.config.emailAndPassword?.maxPasswordLength != null ? { maxPasswordLength: this.config.emailAndPassword.maxPasswordLength } : {},
351
+ ...this.config.emailAndPassword?.resetPasswordTokenExpiresIn != null ? { resetPasswordTokenExpiresIn: this.config.emailAndPassword.resetPasswordTokenExpiresIn } : {},
352
+ ...this.config.emailAndPassword?.autoSignIn != null ? { autoSignIn: this.config.emailAndPassword.autoSignIn } : {},
353
+ ...this.config.emailAndPassword?.revokeSessionsOnPasswordReset != null ? { revokeSessionsOnPasswordReset: this.config.emailAndPassword.revokeSessionsOnPasswordReset } : {}
339
354
  },
355
+ // Email verification
356
+ ...this.config.emailVerification ? {
357
+ emailVerification: {
358
+ ...this.config.emailVerification.sendOnSignUp != null ? { sendOnSignUp: this.config.emailVerification.sendOnSignUp } : {},
359
+ ...this.config.emailVerification.sendOnSignIn != null ? { sendOnSignIn: this.config.emailVerification.sendOnSignIn } : {},
360
+ ...this.config.emailVerification.autoSignInAfterVerification != null ? { autoSignInAfterVerification: this.config.emailVerification.autoSignInAfterVerification } : {},
361
+ ...this.config.emailVerification.expiresIn != null ? { expiresIn: this.config.emailVerification.expiresIn } : {}
362
+ }
363
+ } : {},
340
364
  // Session configuration
341
365
  session: {
342
366
  ...AUTH_SESSION_CONFIG,
@@ -346,7 +370,18 @@ var AuthManager = class {
346
370
  // 1 day default
347
371
  },
348
372
  // better-auth plugins — registered based on AuthPluginConfig flags
349
- plugins: this.buildPluginList()
373
+ plugins: this.buildPluginList(),
374
+ // Trusted origins for CSRF protection (supports wildcards like "https://*.example.com")
375
+ ...this.config.trustedOrigins?.length ? { trustedOrigins: this.config.trustedOrigins } : {},
376
+ // Advanced options (cross-subdomain cookies, secure cookies, CSRF, etc.)
377
+ ...this.config.advanced ? {
378
+ advanced: {
379
+ ...this.config.advanced.crossSubDomainCookies ? { crossSubDomainCookies: this.config.advanced.crossSubDomainCookies } : {},
380
+ ...this.config.advanced.useSecureCookies != null ? { useSecureCookies: this.config.advanced.useSecureCookies } : {},
381
+ ...this.config.advanced.disableCSRFCheck != null ? { disableCSRFCheck: this.config.advanced.disableCSRFCheck } : {},
382
+ ...this.config.advanced.cookiePrefix != null ? { cookiePrefix: this.config.advanced.cookiePrefix } : {}
383
+ }
384
+ } : {}
350
385
  };
351
386
  return betterAuth(betterAuthConfig);
352
387
  }
@@ -416,6 +451,25 @@ var AuthManager = class {
416
451
  }
417
452
  return envSecret;
418
453
  }
454
+ /**
455
+ * Update the base URL at runtime.
456
+ *
457
+ * This **must** be called before the first request triggers lazy
458
+ * initialisation of the better-auth instance — typically from a
459
+ * `kernel:ready` hook where the actual server port is known.
460
+ *
461
+ * If the auth instance has already been created this is a no-op and
462
+ * a warning is emitted.
463
+ */
464
+ setRuntimeBaseUrl(url) {
465
+ if (this.auth) {
466
+ console.warn(
467
+ "[AuthManager] setRuntimeBaseUrl() called after the auth instance was already created \u2014 ignoring. Ensure this method is called before the first request."
468
+ );
469
+ return;
470
+ }
471
+ this.config = { ...this.config, baseUrl: url };
472
+ }
419
473
  /**
420
474
  * Get the underlying better-auth instance
421
475
  * Useful for advanced use cases
@@ -499,6 +553,21 @@ var AuthPlugin = class {
499
553
  } catch {
500
554
  }
501
555
  if (httpServer) {
556
+ const serverWithPort = httpServer;
557
+ if (this.authManager && typeof serverWithPort.getPort === "function") {
558
+ const actualPort = serverWithPort.getPort();
559
+ if (actualPort) {
560
+ const configuredUrl = this.options.baseUrl || "http://localhost:3000";
561
+ const configuredOrigin = new URL(configuredUrl).origin;
562
+ const actualUrl = `http://localhost:${actualPort}`;
563
+ if (configuredOrigin !== actualUrl) {
564
+ this.authManager.setRuntimeBaseUrl(actualUrl);
565
+ ctx.logger.info(
566
+ `Auth baseUrl auto-updated to ${actualUrl} (configured: ${configuredUrl})`
567
+ );
568
+ }
569
+ }
570
+ }
502
571
  this.registerAuthRoutes(httpServer, ctx);
503
572
  ctx.logger.info(`Auth routes registered at ${this.options.basePath}`);
504
573
  } else {
@@ -580,18 +649,19 @@ var AuthPlugin = class {
580
649
  }
581
650
  };
582
651
 
583
- // src/objects/auth-user.object.ts
652
+ // src/objects/sys-user.object.ts
584
653
  import { ObjectSchema, Field } from "@objectstack/spec/data";
585
- var AuthUser = ObjectSchema.create({
586
- name: "sys_user",
654
+ var SysUser = ObjectSchema.create({
655
+ namespace: "sys",
656
+ name: "user",
587
657
  label: "User",
588
658
  pluralLabel: "Users",
589
659
  icon: "user",
660
+ isSystem: true,
590
661
  description: "User accounts for authentication",
591
662
  titleFormat: "{name} ({email})",
592
663
  compactLayout: ["name", "email", "email_verified"],
593
664
  fields: {
594
- // ID is auto-generated by ObjectQL
595
665
  id: Field.text({
596
666
  label: "User ID",
597
667
  required: true,
@@ -627,12 +697,10 @@ var AuthUser = ObjectSchema.create({
627
697
  required: false
628
698
  })
629
699
  },
630
- // Database indexes for performance
631
700
  indexes: [
632
701
  { fields: ["email"], unique: true },
633
702
  { fields: ["created_at"], unique: false }
634
703
  ],
635
- // Enable features
636
704
  enable: {
637
705
  trackHistory: true,
638
706
  searchable: true,
@@ -641,7 +709,6 @@ var AuthUser = ObjectSchema.create({
641
709
  trash: true,
642
710
  mru: true
643
711
  },
644
- // Validation Rules
645
712
  validations: [
646
713
  {
647
714
  name: "email_unique",
@@ -654,13 +721,15 @@ var AuthUser = ObjectSchema.create({
654
721
  ]
655
722
  });
656
723
 
657
- // src/objects/auth-session.object.ts
724
+ // src/objects/sys-session.object.ts
658
725
  import { ObjectSchema as ObjectSchema2, Field as Field2 } from "@objectstack/spec/data";
659
- var AuthSession = ObjectSchema2.create({
660
- name: "sys_session",
726
+ var SysSession = ObjectSchema2.create({
727
+ namespace: "sys",
728
+ name: "session",
661
729
  label: "Session",
662
730
  pluralLabel: "Sessions",
663
731
  icon: "key",
732
+ isSystem: true,
664
733
  description: "Active user sessions",
665
734
  titleFormat: "Session {token}",
666
735
  compactLayout: ["user_id", "expires_at", "ip_address"],
@@ -703,33 +772,30 @@ var AuthSession = ObjectSchema2.create({
703
772
  required: false
704
773
  })
705
774
  },
706
- // Database indexes for performance
707
775
  indexes: [
708
776
  { fields: ["token"], unique: true },
709
777
  { fields: ["user_id"], unique: false },
710
778
  { fields: ["expires_at"], unique: false }
711
779
  ],
712
- // Enable features
713
780
  enable: {
714
781
  trackHistory: false,
715
- // Sessions don't need history tracking
716
782
  searchable: false,
717
783
  apiEnabled: true,
718
784
  apiMethods: ["get", "list", "create", "delete"],
719
- // No update for sessions
720
785
  trash: false,
721
- // Sessions should be hard deleted
722
786
  mru: false
723
787
  }
724
788
  });
725
789
 
726
- // src/objects/auth-account.object.ts
790
+ // src/objects/sys-account.object.ts
727
791
  import { ObjectSchema as ObjectSchema3, Field as Field3 } from "@objectstack/spec/data";
728
- var AuthAccount = ObjectSchema3.create({
729
- name: "sys_account",
792
+ var SysAccount = ObjectSchema3.create({
793
+ namespace: "sys",
794
+ name: "account",
730
795
  label: "Account",
731
796
  pluralLabel: "Accounts",
732
797
  icon: "link",
798
+ isSystem: true,
733
799
  description: "OAuth and authentication provider accounts",
734
800
  titleFormat: "{provider_id} - {account_id}",
735
801
  compactLayout: ["provider_id", "user_id", "account_id"],
@@ -794,12 +860,10 @@ var AuthAccount = ObjectSchema3.create({
794
860
  description: "Hashed password for email/password provider"
795
861
  })
796
862
  },
797
- // Database indexes for performance
798
863
  indexes: [
799
864
  { fields: ["user_id"], unique: false },
800
865
  { fields: ["provider_id", "account_id"], unique: true }
801
866
  ],
802
- // Enable features
803
867
  enable: {
804
868
  trackHistory: false,
805
869
  searchable: false,
@@ -810,13 +874,15 @@ var AuthAccount = ObjectSchema3.create({
810
874
  }
811
875
  });
812
876
 
813
- // src/objects/auth-verification.object.ts
877
+ // src/objects/sys-verification.object.ts
814
878
  import { ObjectSchema as ObjectSchema4, Field as Field4 } from "@objectstack/spec/data";
815
- var AuthVerification = ObjectSchema4.create({
816
- name: "sys_verification",
879
+ var SysVerification = ObjectSchema4.create({
880
+ namespace: "sys",
881
+ name: "verification",
817
882
  label: "Verification",
818
883
  pluralLabel: "Verifications",
819
884
  icon: "shield-check",
885
+ isSystem: true,
820
886
  description: "Email and phone verification tokens",
821
887
  titleFormat: "Verification for {identifier}",
822
888
  compactLayout: ["identifier", "expires_at", "created_at"],
@@ -851,21 +917,444 @@ var AuthVerification = ObjectSchema4.create({
851
917
  description: "Email address or phone number"
852
918
  })
853
919
  },
854
- // Database indexes for performance
855
920
  indexes: [
856
921
  { fields: ["value"], unique: true },
857
922
  { fields: ["identifier"], unique: false },
858
923
  { fields: ["expires_at"], unique: false }
859
924
  ],
860
- // Enable features
861
925
  enable: {
862
926
  trackHistory: false,
863
927
  searchable: false,
864
928
  apiEnabled: true,
865
929
  apiMethods: ["get", "create", "delete"],
866
- // No list or update
867
930
  trash: false,
868
- // Hard delete expired tokens
931
+ mru: false
932
+ }
933
+ });
934
+
935
+ // src/objects/sys-organization.object.ts
936
+ import { ObjectSchema as ObjectSchema5, Field as Field5 } from "@objectstack/spec/data";
937
+ var SysOrganization = ObjectSchema5.create({
938
+ namespace: "sys",
939
+ name: "organization",
940
+ label: "Organization",
941
+ pluralLabel: "Organizations",
942
+ icon: "building-2",
943
+ isSystem: true,
944
+ description: "Organizations for multi-tenant grouping",
945
+ titleFormat: "{name}",
946
+ compactLayout: ["name", "slug", "created_at"],
947
+ fields: {
948
+ id: Field5.text({
949
+ label: "Organization ID",
950
+ required: true,
951
+ readonly: true
952
+ }),
953
+ created_at: Field5.datetime({
954
+ label: "Created At",
955
+ defaultValue: "NOW()",
956
+ readonly: true
957
+ }),
958
+ updated_at: Field5.datetime({
959
+ label: "Updated At",
960
+ defaultValue: "NOW()",
961
+ readonly: true
962
+ }),
963
+ name: Field5.text({
964
+ label: "Name",
965
+ required: true,
966
+ searchable: true,
967
+ maxLength: 255
968
+ }),
969
+ slug: Field5.text({
970
+ label: "Slug",
971
+ required: false,
972
+ maxLength: 255,
973
+ description: "URL-friendly identifier"
974
+ }),
975
+ logo: Field5.url({
976
+ label: "Logo",
977
+ required: false
978
+ }),
979
+ metadata: Field5.textarea({
980
+ label: "Metadata",
981
+ required: false,
982
+ description: "JSON-serialized organization metadata"
983
+ })
984
+ },
985
+ indexes: [
986
+ { fields: ["slug"], unique: true },
987
+ { fields: ["name"] }
988
+ ],
989
+ enable: {
990
+ trackHistory: true,
991
+ searchable: true,
992
+ apiEnabled: true,
993
+ apiMethods: ["get", "list", "create", "update", "delete"],
994
+ trash: true,
995
+ mru: true
996
+ }
997
+ });
998
+
999
+ // src/objects/sys-member.object.ts
1000
+ import { ObjectSchema as ObjectSchema6, Field as Field6 } from "@objectstack/spec/data";
1001
+ var SysMember = ObjectSchema6.create({
1002
+ namespace: "sys",
1003
+ name: "member",
1004
+ label: "Member",
1005
+ pluralLabel: "Members",
1006
+ icon: "user-check",
1007
+ isSystem: true,
1008
+ description: "Organization membership records",
1009
+ titleFormat: "{user_id} in {organization_id}",
1010
+ compactLayout: ["user_id", "organization_id", "role"],
1011
+ fields: {
1012
+ id: Field6.text({
1013
+ label: "Member ID",
1014
+ required: true,
1015
+ readonly: true
1016
+ }),
1017
+ created_at: Field6.datetime({
1018
+ label: "Created At",
1019
+ defaultValue: "NOW()",
1020
+ readonly: true
1021
+ }),
1022
+ organization_id: Field6.text({
1023
+ label: "Organization ID",
1024
+ required: true
1025
+ }),
1026
+ user_id: Field6.text({
1027
+ label: "User ID",
1028
+ required: true
1029
+ }),
1030
+ role: Field6.text({
1031
+ label: "Role",
1032
+ required: false,
1033
+ description: "Member role within the organization (e.g. admin, member)",
1034
+ maxLength: 100
1035
+ })
1036
+ },
1037
+ indexes: [
1038
+ { fields: ["organization_id", "user_id"], unique: true },
1039
+ { fields: ["user_id"] }
1040
+ ],
1041
+ enable: {
1042
+ trackHistory: true,
1043
+ searchable: false,
1044
+ apiEnabled: true,
1045
+ apiMethods: ["get", "list", "create", "update", "delete"],
1046
+ trash: false,
1047
+ mru: false
1048
+ }
1049
+ });
1050
+
1051
+ // src/objects/sys-invitation.object.ts
1052
+ import { ObjectSchema as ObjectSchema7, Field as Field7 } from "@objectstack/spec/data";
1053
+ var SysInvitation = ObjectSchema7.create({
1054
+ namespace: "sys",
1055
+ name: "invitation",
1056
+ label: "Invitation",
1057
+ pluralLabel: "Invitations",
1058
+ icon: "mail",
1059
+ isSystem: true,
1060
+ description: "Organization invitations for user onboarding",
1061
+ titleFormat: "Invitation to {organization_id}",
1062
+ compactLayout: ["email", "organization_id", "status"],
1063
+ fields: {
1064
+ id: Field7.text({
1065
+ label: "Invitation ID",
1066
+ required: true,
1067
+ readonly: true
1068
+ }),
1069
+ created_at: Field7.datetime({
1070
+ label: "Created At",
1071
+ defaultValue: "NOW()",
1072
+ readonly: true
1073
+ }),
1074
+ organization_id: Field7.text({
1075
+ label: "Organization ID",
1076
+ required: true
1077
+ }),
1078
+ email: Field7.email({
1079
+ label: "Email",
1080
+ required: true,
1081
+ description: "Email address of the invited user"
1082
+ }),
1083
+ role: Field7.text({
1084
+ label: "Role",
1085
+ required: false,
1086
+ maxLength: 100,
1087
+ description: "Role to assign upon acceptance"
1088
+ }),
1089
+ status: Field7.select(["pending", "accepted", "rejected", "expired", "canceled"], {
1090
+ label: "Status",
1091
+ required: true,
1092
+ defaultValue: "pending"
1093
+ }),
1094
+ inviter_id: Field7.text({
1095
+ label: "Inviter ID",
1096
+ required: true,
1097
+ description: "User ID of the person who sent the invitation"
1098
+ }),
1099
+ expires_at: Field7.datetime({
1100
+ label: "Expires At",
1101
+ required: true
1102
+ }),
1103
+ team_id: Field7.text({
1104
+ label: "Team ID",
1105
+ required: false,
1106
+ description: "Optional team to assign upon acceptance"
1107
+ })
1108
+ },
1109
+ indexes: [
1110
+ { fields: ["organization_id"] },
1111
+ { fields: ["email"] },
1112
+ { fields: ["expires_at"] }
1113
+ ],
1114
+ enable: {
1115
+ trackHistory: true,
1116
+ searchable: false,
1117
+ apiEnabled: true,
1118
+ apiMethods: ["get", "list", "create", "update", "delete"],
1119
+ trash: false,
1120
+ mru: false
1121
+ }
1122
+ });
1123
+
1124
+ // src/objects/sys-team.object.ts
1125
+ import { ObjectSchema as ObjectSchema8, Field as Field8 } from "@objectstack/spec/data";
1126
+ var SysTeam = ObjectSchema8.create({
1127
+ namespace: "sys",
1128
+ name: "team",
1129
+ label: "Team",
1130
+ pluralLabel: "Teams",
1131
+ icon: "users",
1132
+ isSystem: true,
1133
+ description: "Teams within organizations for fine-grained grouping",
1134
+ titleFormat: "{name}",
1135
+ compactLayout: ["name", "organization_id", "created_at"],
1136
+ fields: {
1137
+ id: Field8.text({
1138
+ label: "Team ID",
1139
+ required: true,
1140
+ readonly: true
1141
+ }),
1142
+ created_at: Field8.datetime({
1143
+ label: "Created At",
1144
+ defaultValue: "NOW()",
1145
+ readonly: true
1146
+ }),
1147
+ updated_at: Field8.datetime({
1148
+ label: "Updated At",
1149
+ defaultValue: "NOW()",
1150
+ readonly: true
1151
+ }),
1152
+ name: Field8.text({
1153
+ label: "Name",
1154
+ required: true,
1155
+ searchable: true,
1156
+ maxLength: 255
1157
+ }),
1158
+ organization_id: Field8.text({
1159
+ label: "Organization ID",
1160
+ required: true
1161
+ })
1162
+ },
1163
+ indexes: [
1164
+ { fields: ["organization_id"] },
1165
+ { fields: ["name", "organization_id"], unique: true }
1166
+ ],
1167
+ enable: {
1168
+ trackHistory: true,
1169
+ searchable: true,
1170
+ apiEnabled: true,
1171
+ apiMethods: ["get", "list", "create", "update", "delete"],
1172
+ trash: true,
1173
+ mru: false
1174
+ }
1175
+ });
1176
+
1177
+ // src/objects/sys-team-member.object.ts
1178
+ import { ObjectSchema as ObjectSchema9, Field as Field9 } from "@objectstack/spec/data";
1179
+ var SysTeamMember = ObjectSchema9.create({
1180
+ namespace: "sys",
1181
+ name: "team_member",
1182
+ label: "Team Member",
1183
+ pluralLabel: "Team Members",
1184
+ icon: "user-plus",
1185
+ isSystem: true,
1186
+ description: "Team membership records linking users to teams",
1187
+ titleFormat: "{user_id} in {team_id}",
1188
+ compactLayout: ["user_id", "team_id", "created_at"],
1189
+ fields: {
1190
+ id: Field9.text({
1191
+ label: "Team Member ID",
1192
+ required: true,
1193
+ readonly: true
1194
+ }),
1195
+ created_at: Field9.datetime({
1196
+ label: "Created At",
1197
+ defaultValue: "NOW()",
1198
+ readonly: true
1199
+ }),
1200
+ team_id: Field9.text({
1201
+ label: "Team ID",
1202
+ required: true
1203
+ }),
1204
+ user_id: Field9.text({
1205
+ label: "User ID",
1206
+ required: true
1207
+ })
1208
+ },
1209
+ indexes: [
1210
+ { fields: ["team_id", "user_id"], unique: true },
1211
+ { fields: ["user_id"] }
1212
+ ],
1213
+ enable: {
1214
+ trackHistory: true,
1215
+ searchable: false,
1216
+ apiEnabled: true,
1217
+ apiMethods: ["get", "list", "create", "delete"],
1218
+ trash: false,
1219
+ mru: false
1220
+ }
1221
+ });
1222
+
1223
+ // src/objects/sys-api-key.object.ts
1224
+ import { ObjectSchema as ObjectSchema10, Field as Field10 } from "@objectstack/spec/data";
1225
+ var SysApiKey = ObjectSchema10.create({
1226
+ namespace: "sys",
1227
+ name: "api_key",
1228
+ label: "API Key",
1229
+ pluralLabel: "API Keys",
1230
+ icon: "key-round",
1231
+ isSystem: true,
1232
+ description: "API keys for programmatic access",
1233
+ titleFormat: "{name}",
1234
+ compactLayout: ["name", "user_id", "expires_at"],
1235
+ fields: {
1236
+ id: Field10.text({
1237
+ label: "API Key ID",
1238
+ required: true,
1239
+ readonly: true
1240
+ }),
1241
+ created_at: Field10.datetime({
1242
+ label: "Created At",
1243
+ defaultValue: "NOW()",
1244
+ readonly: true
1245
+ }),
1246
+ updated_at: Field10.datetime({
1247
+ label: "Updated At",
1248
+ defaultValue: "NOW()",
1249
+ readonly: true
1250
+ }),
1251
+ name: Field10.text({
1252
+ label: "Name",
1253
+ required: true,
1254
+ maxLength: 255,
1255
+ description: "Human-readable label for the API key"
1256
+ }),
1257
+ key: Field10.text({
1258
+ label: "Key",
1259
+ required: true,
1260
+ description: "Hashed API key value"
1261
+ }),
1262
+ prefix: Field10.text({
1263
+ label: "Prefix",
1264
+ required: false,
1265
+ maxLength: 16,
1266
+ description: 'Visible prefix for identifying the key (e.g., "osk_")'
1267
+ }),
1268
+ user_id: Field10.text({
1269
+ label: "User ID",
1270
+ required: true,
1271
+ description: "Owner user of this API key"
1272
+ }),
1273
+ scopes: Field10.textarea({
1274
+ label: "Scopes",
1275
+ required: false,
1276
+ description: "JSON array of permission scopes"
1277
+ }),
1278
+ expires_at: Field10.datetime({
1279
+ label: "Expires At",
1280
+ required: false
1281
+ }),
1282
+ last_used_at: Field10.datetime({
1283
+ label: "Last Used At",
1284
+ required: false
1285
+ }),
1286
+ revoked: Field10.boolean({
1287
+ label: "Revoked",
1288
+ defaultValue: false
1289
+ })
1290
+ },
1291
+ indexes: [
1292
+ { fields: ["key"], unique: true },
1293
+ { fields: ["user_id"] },
1294
+ { fields: ["prefix"] }
1295
+ ],
1296
+ enable: {
1297
+ trackHistory: true,
1298
+ searchable: false,
1299
+ apiEnabled: true,
1300
+ apiMethods: ["get", "list", "create", "update", "delete"],
1301
+ trash: false,
1302
+ mru: false
1303
+ }
1304
+ });
1305
+
1306
+ // src/objects/sys-two-factor.object.ts
1307
+ import { ObjectSchema as ObjectSchema11, Field as Field11 } from "@objectstack/spec/data";
1308
+ var SysTwoFactor = ObjectSchema11.create({
1309
+ namespace: "sys",
1310
+ name: "two_factor",
1311
+ label: "Two Factor",
1312
+ pluralLabel: "Two Factor Credentials",
1313
+ icon: "smartphone",
1314
+ isSystem: true,
1315
+ description: "Two-factor authentication credentials",
1316
+ titleFormat: "Two-factor for {user_id}",
1317
+ compactLayout: ["user_id", "created_at"],
1318
+ fields: {
1319
+ id: Field11.text({
1320
+ label: "Two Factor ID",
1321
+ required: true,
1322
+ readonly: true
1323
+ }),
1324
+ created_at: Field11.datetime({
1325
+ label: "Created At",
1326
+ defaultValue: "NOW()",
1327
+ readonly: true
1328
+ }),
1329
+ updated_at: Field11.datetime({
1330
+ label: "Updated At",
1331
+ defaultValue: "NOW()",
1332
+ readonly: true
1333
+ }),
1334
+ user_id: Field11.text({
1335
+ label: "User ID",
1336
+ required: true
1337
+ }),
1338
+ secret: Field11.text({
1339
+ label: "Secret",
1340
+ required: true,
1341
+ description: "TOTP secret key"
1342
+ }),
1343
+ backup_codes: Field11.textarea({
1344
+ label: "Backup Codes",
1345
+ required: false,
1346
+ description: "JSON-serialized backup recovery codes"
1347
+ })
1348
+ },
1349
+ indexes: [
1350
+ { fields: ["user_id"], unique: true }
1351
+ ],
1352
+ enable: {
1353
+ trackHistory: false,
1354
+ searchable: false,
1355
+ apiEnabled: true,
1356
+ apiMethods: ["get", "create", "update", "delete"],
1357
+ trash: false,
869
1358
  mru: false
870
1359
  }
871
1360
  });
@@ -883,12 +1372,23 @@ export {
883
1372
  AUTH_TWO_FACTOR_USER_FIELDS,
884
1373
  AUTH_USER_CONFIG,
885
1374
  AUTH_VERIFICATION_CONFIG,
886
- AuthAccount,
1375
+ SysAccount as AuthAccount,
887
1376
  AuthManager,
888
1377
  AuthPlugin,
889
- AuthSession,
890
- AuthUser,
891
- AuthVerification,
1378
+ SysSession as AuthSession,
1379
+ SysUser as AuthUser,
1380
+ SysVerification as AuthVerification,
1381
+ SysAccount,
1382
+ SysApiKey,
1383
+ SysInvitation,
1384
+ SysMember,
1385
+ SysOrganization,
1386
+ SysSession,
1387
+ SysTeam,
1388
+ SysTeamMember,
1389
+ SysTwoFactor,
1390
+ SysUser,
1391
+ SysVerification,
892
1392
  buildOrganizationPluginSchema,
893
1393
  buildTwoFactorPluginSchema,
894
1394
  createObjectQLAdapter,