@sonicjs-cms/core 2.11.0 → 2.12.0

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.
Files changed (76) hide show
  1. package/dist/{app-Ozl9agJG.d.cts → app-COElO4Rm.d.cts} +6 -1
  2. package/dist/{app-Ozl9agJG.d.ts → app-COElO4Rm.d.ts} +6 -1
  3. package/dist/{chunk-BUU2US2Z.js → chunk-6R6LAUR7.js} +3 -3
  4. package/dist/{chunk-BUU2US2Z.js.map → chunk-6R6LAUR7.js.map} +1 -1
  5. package/dist/{chunk-JJS7JZCH.js → chunk-76TX6XND.js} +4 -2
  6. package/dist/chunk-76TX6XND.js.map +1 -0
  7. package/dist/{chunk-DE5YTNCD.cjs → chunk-AG3SIPP7.cjs} +9 -2
  8. package/dist/chunk-AG3SIPP7.cjs.map +1 -0
  9. package/dist/{chunk-74XCYEI7.js → chunk-BWZBKLOC.js} +3 -3
  10. package/dist/{chunk-74XCYEI7.js.map → chunk-BWZBKLOC.js.map} +1 -1
  11. package/dist/{chunk-NMLFKXWW.js → chunk-H3XXBAMO.js} +15 -2
  12. package/dist/chunk-H3XXBAMO.js.map +1 -0
  13. package/dist/{chunk-LTKV7AE5.cjs → chunk-H4NHRZ6Y.cjs} +4 -2
  14. package/dist/chunk-H4NHRZ6Y.cjs.map +1 -0
  15. package/dist/{chunk-GKRGDJGG.js → chunk-HXIYYE57.js} +6 -6
  16. package/dist/{chunk-GKRGDJGG.js.map → chunk-HXIYYE57.js.map} +1 -1
  17. package/dist/{chunk-6BVLPACH.cjs → chunk-I6FFGQIT.cjs} +15 -2
  18. package/dist/chunk-I6FFGQIT.cjs.map +1 -0
  19. package/dist/{chunk-JTQBNSZX.js → chunk-NDFHQOPP.js} +4176 -3805
  20. package/dist/chunk-NDFHQOPP.js.map +1 -0
  21. package/dist/{chunk-LFAQUR7P.cjs → chunk-NZWFCUDA.cjs} +26 -2
  22. package/dist/chunk-NZWFCUDA.cjs.map +1 -0
  23. package/dist/{chunk-3G7XX4UI.cjs → chunk-RBXFXT7H.cjs} +9 -9
  24. package/dist/{chunk-3G7XX4UI.cjs.map → chunk-RBXFXT7H.cjs.map} +1 -1
  25. package/dist/{chunk-QLPFENZ2.cjs → chunk-RXNLGINR.cjs} +3 -3
  26. package/dist/{chunk-QLPFENZ2.cjs.map → chunk-RXNLGINR.cjs.map} +1 -1
  27. package/dist/{chunk-VJCLJH3X.js → chunk-TBJY2FF7.js} +26 -2
  28. package/dist/chunk-TBJY2FF7.js.map +1 -0
  29. package/dist/{chunk-H55AYIRI.js → chunk-U3ZMGBVC.js} +9 -2
  30. package/dist/chunk-U3ZMGBVC.js.map +1 -0
  31. package/dist/{chunk-B2ASV5RD.cjs → chunk-VHNTCB2X.cjs} +10 -10
  32. package/dist/{chunk-B2ASV5RD.cjs.map → chunk-VHNTCB2X.cjs.map} +1 -1
  33. package/dist/{chunk-ASAEJ4B7.cjs → chunk-ZV6ZCJ74.cjs} +4376 -4001
  34. package/dist/chunk-ZV6ZCJ74.cjs.map +1 -0
  35. package/dist/index.cjs +1828 -170
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +53 -5
  38. package/dist/index.d.ts +53 -5
  39. package/dist/index.js +1656 -13
  40. package/dist/index.js.map +1 -1
  41. package/dist/middleware.cjs +29 -29
  42. package/dist/middleware.d.cts +1 -1
  43. package/dist/middleware.d.ts +1 -1
  44. package/dist/middleware.js +3 -3
  45. package/dist/migrations-USSEHJC7.js +4 -0
  46. package/dist/{migrations-UFVJTPVT.js.map → migrations-USSEHJC7.js.map} +1 -1
  47. package/dist/migrations-ZE6IZNLB.cjs +13 -0
  48. package/dist/{migrations-VNYOSUNE.cjs.map → migrations-ZE6IZNLB.cjs.map} +1 -1
  49. package/dist/{plugin-bootstrap-DXBAYaqM.d.ts → plugin-bootstrap-CZ1GDum7.d.ts} +802 -1
  50. package/dist/{plugin-bootstrap-DCXpeQVb.d.cts → plugin-bootstrap-DVGLQrcO.d.cts} +802 -1
  51. package/dist/routes.cjs +30 -30
  52. package/dist/routes.d.cts +1 -1
  53. package/dist/routes.d.ts +1 -1
  54. package/dist/routes.js +7 -7
  55. package/dist/services.cjs +39 -39
  56. package/dist/services.d.cts +1 -1
  57. package/dist/services.d.ts +1 -1
  58. package/dist/services.js +3 -3
  59. package/dist/templates.cjs +19 -19
  60. package/dist/templates.js +2 -2
  61. package/dist/utils.cjs +11 -11
  62. package/dist/utils.js +1 -1
  63. package/migrations/034_security_audit_plugin.sql +27 -0
  64. package/package.json +1 -1
  65. package/dist/chunk-6BVLPACH.cjs.map +0 -1
  66. package/dist/chunk-ASAEJ4B7.cjs.map +0 -1
  67. package/dist/chunk-DE5YTNCD.cjs.map +0 -1
  68. package/dist/chunk-H55AYIRI.js.map +0 -1
  69. package/dist/chunk-JJS7JZCH.js.map +0 -1
  70. package/dist/chunk-JTQBNSZX.js.map +0 -1
  71. package/dist/chunk-LFAQUR7P.cjs.map +0 -1
  72. package/dist/chunk-LTKV7AE5.cjs.map +0 -1
  73. package/dist/chunk-NMLFKXWW.js.map +0 -1
  74. package/dist/chunk-VJCLJH3X.js.map +0 -1
  75. package/dist/migrations-UFVJTPVT.js +0 -4
  76. package/dist/migrations-VNYOSUNE.cjs +0 -13
package/dist/index.cjs CHANGED
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var chunkASAEJ4B7_cjs = require('./chunk-ASAEJ4B7.cjs');
4
- var chunkLFAQUR7P_cjs = require('./chunk-LFAQUR7P.cjs');
5
- var chunkB2ASV5RD_cjs = require('./chunk-B2ASV5RD.cjs');
6
- var chunk6BVLPACH_cjs = require('./chunk-6BVLPACH.cjs');
7
- var chunkDE5YTNCD_cjs = require('./chunk-DE5YTNCD.cjs');
8
- var chunk3G7XX4UI_cjs = require('./chunk-3G7XX4UI.cjs');
9
- var chunkLTKV7AE5_cjs = require('./chunk-LTKV7AE5.cjs');
3
+ var chunkZV6ZCJ74_cjs = require('./chunk-ZV6ZCJ74.cjs');
4
+ var chunkNZWFCUDA_cjs = require('./chunk-NZWFCUDA.cjs');
5
+ var chunkVHNTCB2X_cjs = require('./chunk-VHNTCB2X.cjs');
6
+ var chunkI6FFGQIT_cjs = require('./chunk-I6FFGQIT.cjs');
7
+ var chunkAG3SIPP7_cjs = require('./chunk-AG3SIPP7.cjs');
8
+ var chunkRBXFXT7H_cjs = require('./chunk-RBXFXT7H.cjs');
9
+ var chunkH4NHRZ6Y_cjs = require('./chunk-H4NHRZ6Y.cjs');
10
10
  var chunk56GUBLJE_cjs = require('./chunk-56GUBLJE.cjs');
11
11
  var chunk6FHNRRJ3_cjs = require('./chunk-6FHNRRJ3.cjs');
12
- var chunkQLPFENZ2_cjs = require('./chunk-QLPFENZ2.cjs');
12
+ var chunkRXNLGINR_cjs = require('./chunk-RXNLGINR.cjs');
13
13
  require('./chunk-P3XDZL6Q.cjs');
14
14
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
15
15
  var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
@@ -235,7 +235,7 @@ var DatabaseToolsService = class {
235
235
  };
236
236
 
237
237
  // src/templates/pages/admin-database-table.template.ts
238
- chunkLTKV7AE5_cjs.init_admin_layout_catalyst_template();
238
+ chunkH4NHRZ6Y_cjs.init_admin_layout_catalyst_template();
239
239
  function renderDatabaseTablePage(data) {
240
240
  const totalPages = Math.ceil(data.totalRows / data.pageSize);
241
241
  const startRow = (data.currentPage - 1) * data.pageSize + 1;
@@ -484,7 +484,7 @@ function renderDatabaseTablePage(data) {
484
484
  user: data.user,
485
485
  content: pageContent
486
486
  };
487
- return chunkLTKV7AE5_cjs.renderAdminLayoutCatalyst(layoutData);
487
+ return chunkH4NHRZ6Y_cjs.renderAdminLayoutCatalyst(layoutData);
488
488
  }
489
489
  function generatePageNumbers(currentPage, totalPages) {
490
490
  const pages = [];
@@ -559,7 +559,7 @@ function formatCellValue(value) {
559
559
  // src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
560
560
  function createDatabaseToolsAdminRoutes() {
561
561
  const router3 = new hono.Hono();
562
- router3.use("*", chunkB2ASV5RD_cjs.requireAuth());
562
+ router3.use("*", chunkVHNTCB2X_cjs.requireAuth());
563
563
  router3.get("/api/stats", async (c) => {
564
564
  try {
565
565
  const user = c.get("user");
@@ -1776,7 +1776,7 @@ function createOTPLoginPlugin() {
1776
1776
  console.warn("Failed to parse OTP plugin settings, using defaults");
1777
1777
  }
1778
1778
  }
1779
- const settingsService = new chunkLFAQUR7P_cjs.SettingsService(db);
1779
+ const settingsService = new chunkNZWFCUDA_cjs.SettingsService(db);
1780
1780
  const generalSettings = await settingsService.getGeneralSettings();
1781
1781
  const siteName = generalSettings.siteName;
1782
1782
  const canRequest = await otpService.checkRateLimit(normalizedEmail, settings);
@@ -1926,7 +1926,7 @@ function createOTPLoginPlugin() {
1926
1926
  error: "Account is deactivated"
1927
1927
  }, 403);
1928
1928
  }
1929
- const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
1929
+ const token = await chunkVHNTCB2X_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
1930
1930
  cookie.setCookie(c, "auth_token", token, {
1931
1931
  httpOnly: true,
1932
1932
  secure: true,
@@ -2396,13 +2396,13 @@ function createOAuthProvidersPlugin() {
2396
2396
  if (!user || !user.is_active) {
2397
2397
  return c.redirect("/auth/login?error=Account is deactivated");
2398
2398
  }
2399
- const jwt2 = await chunkB2ASV5RD_cjs.AuthManager.generateToken(
2399
+ const jwt2 = await chunkVHNTCB2X_cjs.AuthManager.generateToken(
2400
2400
  user.id,
2401
2401
  user.email,
2402
2402
  user.role,
2403
2403
  c.env.JWT_SECRET
2404
2404
  );
2405
- chunkB2ASV5RD_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
2405
+ chunkVHNTCB2X_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
2406
2406
  return c.redirect("/admin");
2407
2407
  }
2408
2408
  const existingUser = await oauthService.findUserByEmail(profile.email);
@@ -2419,13 +2419,13 @@ function createOAuthProvidersPlugin() {
2419
2419
  tokenExpiresAt: tokenExpiresAt ?? void 0,
2420
2420
  profileData: JSON.stringify(profile)
2421
2421
  });
2422
- const jwt2 = await chunkB2ASV5RD_cjs.AuthManager.generateToken(
2422
+ const jwt2 = await chunkVHNTCB2X_cjs.AuthManager.generateToken(
2423
2423
  existingUser.id,
2424
2424
  existingUser.email,
2425
2425
  existingUser.role,
2426
2426
  c.env.JWT_SECRET
2427
2427
  );
2428
- chunkB2ASV5RD_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
2428
+ chunkVHNTCB2X_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
2429
2429
  return c.redirect("/admin");
2430
2430
  }
2431
2431
  const newUserId = await oauthService.createUserFromOAuth(profile);
@@ -2438,13 +2438,13 @@ function createOAuthProvidersPlugin() {
2438
2438
  tokenExpiresAt: tokenExpiresAt ?? void 0,
2439
2439
  profileData: JSON.stringify(profile)
2440
2440
  });
2441
- const jwt = await chunkB2ASV5RD_cjs.AuthManager.generateToken(
2441
+ const jwt = await chunkVHNTCB2X_cjs.AuthManager.generateToken(
2442
2442
  newUserId,
2443
2443
  profile.email.toLowerCase(),
2444
2444
  "viewer",
2445
2445
  c.env.JWT_SECRET
2446
2446
  );
2447
- chunkB2ASV5RD_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax" });
2447
+ chunkVHNTCB2X_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax" });
2448
2448
  return c.redirect("/admin");
2449
2449
  } catch (error) {
2450
2450
  console.error("OAuth callback error:", error);
@@ -4126,7 +4126,7 @@ function renderSettingsPage(data) {
4126
4126
  }, 30000);
4127
4127
  </script>
4128
4128
  `;
4129
- return chunkLTKV7AE5_cjs.renderAdminLayout({
4129
+ return chunkH4NHRZ6Y_cjs.renderAdminLayout({
4130
4130
  title: "AI Search Settings",
4131
4131
  pageTitle: "AI Search Settings",
4132
4132
  currentPath: "/admin/plugins/ai-search/settings",
@@ -4137,7 +4137,7 @@ function renderSettingsPage(data) {
4137
4137
 
4138
4138
  // src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
4139
4139
  var adminRoutes = new hono.Hono();
4140
- adminRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
4140
+ adminRoutes.use("*", chunkVHNTCB2X_cjs.requireAuth());
4141
4141
  adminRoutes.get("/", async (c) => {
4142
4142
  try {
4143
4143
  const user = c.get("user");
@@ -4538,13 +4538,13 @@ function createMagicLinkAuthPlugin() {
4538
4538
  SET used = 1, used_at = ?
4539
4539
  WHERE id = ?
4540
4540
  `).bind(Date.now(), magicLink.id).run();
4541
- const jwtToken = await chunkB2ASV5RD_cjs.AuthManager.generateToken(
4541
+ const jwtToken = await chunkVHNTCB2X_cjs.AuthManager.generateToken(
4542
4542
  user.id,
4543
4543
  user.email,
4544
4544
  user.role,
4545
4545
  c.env.JWT_SECRET
4546
4546
  );
4547
- chunkB2ASV5RD_cjs.AuthManager.setAuthCookie(c, jwtToken);
4547
+ chunkVHNTCB2X_cjs.AuthManager.setAuthCookie(c, jwtToken);
4548
4548
  await db.prepare(`
4549
4549
  UPDATE users SET last_login_at = ? WHERE id = ?
4550
4550
  `).bind(Date.now(), user.id).run();
@@ -4689,6 +4689,1636 @@ function renderMagicLinkEmail(magicLink, expiryMinutes) {
4689
4689
  }
4690
4690
  createMagicLinkAuthPlugin();
4691
4691
 
4692
+ // src/plugins/core-plugins/security-audit-plugin/types.ts
4693
+ var DEFAULT_SETTINGS2 = {
4694
+ retention: {
4695
+ daysToKeep: 90,
4696
+ maxEvents: 1e5,
4697
+ autoPurge: true
4698
+ },
4699
+ bruteForce: {
4700
+ enabled: true,
4701
+ maxFailedAttemptsPerIP: 10,
4702
+ maxFailedAttemptsPerEmail: 5,
4703
+ windowMinutes: 15,
4704
+ lockoutDurationMinutes: 30,
4705
+ alertThreshold: 20
4706
+ },
4707
+ logging: {
4708
+ logSuccessfulLogins: true,
4709
+ logLogouts: true,
4710
+ logRegistrations: true,
4711
+ logPasswordResets: true,
4712
+ logPermissionDenied: true
4713
+ }
4714
+ };
4715
+
4716
+ // src/plugins/core-plugins/security-audit-plugin/services/security-audit-service.ts
4717
+ var SecurityAuditService = class {
4718
+ constructor(db, settings = DEFAULT_SETTINGS2) {
4719
+ this.db = db;
4720
+ this.settings = settings;
4721
+ }
4722
+ async logEvent(event) {
4723
+ const id = crypto.randomUUID();
4724
+ const now = Date.now();
4725
+ await this.db.prepare(`
4726
+ INSERT INTO security_events (id, event_type, severity, user_id, email, ip_address, user_agent, country_code, request_path, request_method, details, fingerprint, blocked, created_at)
4727
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
4728
+ `).bind(
4729
+ id,
4730
+ event.eventType,
4731
+ event.severity || "info",
4732
+ event.userId || null,
4733
+ event.email || null,
4734
+ event.ipAddress || null,
4735
+ event.userAgent || null,
4736
+ event.countryCode || null,
4737
+ event.requestPath || null,
4738
+ event.requestMethod || null,
4739
+ event.details ? JSON.stringify(event.details) : null,
4740
+ event.fingerprint || null,
4741
+ event.blocked ? 1 : 0,
4742
+ now
4743
+ ).run();
4744
+ return id;
4745
+ }
4746
+ async getEvents(filters = {}) {
4747
+ const conditions = [];
4748
+ const params = [];
4749
+ if (filters.eventType) {
4750
+ if (Array.isArray(filters.eventType)) {
4751
+ conditions.push(`event_type IN (${filters.eventType.map(() => "?").join(",")})`);
4752
+ params.push(...filters.eventType);
4753
+ } else {
4754
+ conditions.push("event_type = ?");
4755
+ params.push(filters.eventType);
4756
+ }
4757
+ }
4758
+ if (filters.severity) {
4759
+ if (Array.isArray(filters.severity)) {
4760
+ conditions.push(`severity IN (${filters.severity.map(() => "?").join(",")})`);
4761
+ params.push(...filters.severity);
4762
+ } else {
4763
+ conditions.push("severity = ?");
4764
+ params.push(filters.severity);
4765
+ }
4766
+ }
4767
+ if (filters.email) {
4768
+ conditions.push("email LIKE ?");
4769
+ params.push(`%${filters.email}%`);
4770
+ }
4771
+ if (filters.ipAddress) {
4772
+ conditions.push("ip_address LIKE ?");
4773
+ params.push(`%${filters.ipAddress}%`);
4774
+ }
4775
+ if (filters.search) {
4776
+ conditions.push("(email LIKE ? OR ip_address LIKE ? OR details LIKE ?)");
4777
+ params.push(`%${filters.search}%`, `%${filters.search}%`, `%${filters.search}%`);
4778
+ }
4779
+ if (filters.startDate) {
4780
+ conditions.push("created_at >= ?");
4781
+ params.push(filters.startDate);
4782
+ }
4783
+ if (filters.endDate) {
4784
+ conditions.push("created_at <= ?");
4785
+ params.push(filters.endDate);
4786
+ }
4787
+ if (filters.blocked !== void 0) {
4788
+ conditions.push("blocked = ?");
4789
+ params.push(filters.blocked ? 1 : 0);
4790
+ }
4791
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
4792
+ const sortBy = filters.sortBy || "created_at";
4793
+ const sortOrder = filters.sortOrder || "desc";
4794
+ const page = filters.page || 1;
4795
+ const limit = filters.limit || 50;
4796
+ const offset = (page - 1) * limit;
4797
+ const countResult = await this.db.prepare(
4798
+ `SELECT COUNT(*) as count FROM security_events ${where}`
4799
+ ).bind(...params).first();
4800
+ const total = countResult?.count || 0;
4801
+ const results = await this.db.prepare(
4802
+ `SELECT * FROM security_events ${where} ORDER BY ${sortBy} ${sortOrder} LIMIT ? OFFSET ?`
4803
+ ).bind(...params, limit, offset).all();
4804
+ const events = (results.results || []).map((row) => ({
4805
+ id: row.id,
4806
+ eventType: row.event_type,
4807
+ severity: row.severity,
4808
+ userId: row.user_id,
4809
+ email: row.email,
4810
+ ipAddress: row.ip_address,
4811
+ userAgent: row.user_agent,
4812
+ countryCode: row.country_code,
4813
+ requestPath: row.request_path,
4814
+ requestMethod: row.request_method,
4815
+ details: row.details ? JSON.parse(row.details) : null,
4816
+ fingerprint: row.fingerprint,
4817
+ blocked: !!row.blocked,
4818
+ createdAt: row.created_at
4819
+ }));
4820
+ return { events, total };
4821
+ }
4822
+ async getEvent(id) {
4823
+ const row = await this.db.prepare(
4824
+ "SELECT * FROM security_events WHERE id = ?"
4825
+ ).bind(id).first();
4826
+ if (!row) return null;
4827
+ return {
4828
+ id: row.id,
4829
+ eventType: row.event_type,
4830
+ severity: row.severity,
4831
+ userId: row.user_id,
4832
+ email: row.email,
4833
+ ipAddress: row.ip_address,
4834
+ userAgent: row.user_agent,
4835
+ countryCode: row.country_code,
4836
+ requestPath: row.request_path,
4837
+ requestMethod: row.request_method,
4838
+ details: row.details ? JSON.parse(row.details) : null,
4839
+ fingerprint: row.fingerprint,
4840
+ blocked: !!row.blocked,
4841
+ createdAt: row.created_at
4842
+ };
4843
+ }
4844
+ async getStats() {
4845
+ const now = Date.now();
4846
+ const h24 = now - 24 * 60 * 60 * 1e3;
4847
+ const h48 = now - 48 * 60 * 60 * 1e3;
4848
+ const totalResult = await this.db.prepare(
4849
+ "SELECT COUNT(*) as count FROM security_events"
4850
+ ).first();
4851
+ const failed24hResult = await this.db.prepare(
4852
+ "SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ?"
4853
+ ).bind(h24).first();
4854
+ const failedPrior24hResult = await this.db.prepare(
4855
+ "SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ? AND created_at < ?"
4856
+ ).bind(h48, h24).first();
4857
+ const failed24h = failed24hResult?.count || 0;
4858
+ const failedPrior24h = failedPrior24hResult?.count || 0;
4859
+ const trend = failedPrior24h > 0 ? Math.round((failed24h - failedPrior24h) / failedPrior24h * 100) : failed24h > 0 ? 100 : 0;
4860
+ const lockoutWindow = now - this.settings.bruteForce.lockoutDurationMinutes * 60 * 1e3;
4861
+ const lockoutsResult = await this.db.prepare(
4862
+ "SELECT COUNT(DISTINCT ip_address) as count FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?"
4863
+ ).bind(lockoutWindow).first();
4864
+ const windowStart = now - this.settings.bruteForce.windowMinutes * 60 * 1e3;
4865
+ const flaggedResult = await this.db.prepare(
4866
+ `SELECT COUNT(*) as count FROM (
4867
+ SELECT ip_address FROM security_events
4868
+ WHERE event_type = 'login_failure' AND created_at >= ?
4869
+ GROUP BY ip_address HAVING COUNT(*) >= ?
4870
+ )`
4871
+ ).bind(windowStart, this.settings.bruteForce.maxFailedAttemptsPerIP).first();
4872
+ const typeResults = await this.db.prepare(
4873
+ "SELECT event_type, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY event_type"
4874
+ ).bind(h24).all();
4875
+ const eventsByType = {};
4876
+ for (const row of typeResults.results || []) {
4877
+ eventsByType[row.event_type] = row.count;
4878
+ }
4879
+ const severityResults = await this.db.prepare(
4880
+ "SELECT severity, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY severity"
4881
+ ).bind(h24).all();
4882
+ const eventsBySeverity = {};
4883
+ for (const row of severityResults.results || []) {
4884
+ eventsBySeverity[row.severity] = row.count;
4885
+ }
4886
+ return {
4887
+ totalEvents: totalResult?.count || 0,
4888
+ failedLogins24h: failed24h,
4889
+ failedLoginsTrend: trend,
4890
+ activeLockouts: lockoutsResult?.count || 0,
4891
+ flaggedIPs: flaggedResult?.count || 0,
4892
+ eventsByType,
4893
+ eventsBySeverity
4894
+ };
4895
+ }
4896
+ async getTopIPs(limit = 10) {
4897
+ const now = Date.now();
4898
+ const h24 = now - 24 * 60 * 60 * 1e3;
4899
+ const results = await this.db.prepare(`
4900
+ SELECT
4901
+ ip_address,
4902
+ country_code,
4903
+ COUNT(*) as failed_attempts,
4904
+ MAX(created_at) as last_seen
4905
+ FROM security_events
4906
+ WHERE event_type = 'login_failure' AND created_at >= ?
4907
+ GROUP BY ip_address
4908
+ ORDER BY failed_attempts DESC
4909
+ LIMIT ?
4910
+ `).bind(h24, limit).all();
4911
+ const lockoutWindow = now - this.settings.bruteForce.lockoutDurationMinutes * 60 * 1e3;
4912
+ const lockoutResults = await this.db.prepare(
4913
+ "SELECT DISTINCT ip_address FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?"
4914
+ ).bind(lockoutWindow).all();
4915
+ const lockedIPs = new Set((lockoutResults.results || []).map((r) => r.ip_address));
4916
+ return (results.results || []).map((row) => ({
4917
+ ipAddress: row.ip_address,
4918
+ countryCode: row.country_code,
4919
+ failedAttempts: row.failed_attempts,
4920
+ lastSeen: row.last_seen,
4921
+ locked: lockedIPs.has(row.ip_address)
4922
+ }));
4923
+ }
4924
+ async getHourlyTrend(hours = 24) {
4925
+ const now = Date.now();
4926
+ const start = now - hours * 60 * 60 * 1e3;
4927
+ const buckets = [];
4928
+ for (let i = 0; i < hours; i++) {
4929
+ const bucketStart = start + i * 60 * 60 * 1e3;
4930
+ const date = new Date(bucketStart);
4931
+ buckets.push({
4932
+ hour: `${date.getUTCHours().toString().padStart(2, "0")}:00`,
4933
+ count: 0
4934
+ });
4935
+ }
4936
+ const results = await this.db.prepare(`
4937
+ SELECT
4938
+ CAST((created_at - ?) / 3600000 AS INTEGER) as bucket,
4939
+ COUNT(*) as count
4940
+ FROM security_events
4941
+ WHERE event_type = 'login_failure' AND created_at >= ?
4942
+ GROUP BY bucket
4943
+ ORDER BY bucket
4944
+ `).bind(start, start).all();
4945
+ for (const row of results.results || []) {
4946
+ const idx = row.bucket;
4947
+ if (idx >= 0 && idx < buckets.length) {
4948
+ buckets[idx].count = row.count;
4949
+ }
4950
+ }
4951
+ return buckets;
4952
+ }
4953
+ async purgeOldEvents(daysToKeep) {
4954
+ const days = daysToKeep || this.settings.retention.daysToKeep;
4955
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
4956
+ const result = await this.db.prepare(
4957
+ "DELETE FROM security_events WHERE created_at < ?"
4958
+ ).bind(cutoff).run();
4959
+ return result.meta?.changes || 0;
4960
+ }
4961
+ async getRecentCriticalEvents(limit = 20) {
4962
+ const results = await this.db.prepare(
4963
+ "SELECT * FROM security_events WHERE severity = 'critical' ORDER BY created_at DESC LIMIT ?"
4964
+ ).bind(limit).all();
4965
+ return (results.results || []).map((row) => ({
4966
+ id: row.id,
4967
+ eventType: row.event_type,
4968
+ severity: row.severity,
4969
+ userId: row.user_id,
4970
+ email: row.email,
4971
+ ipAddress: row.ip_address,
4972
+ userAgent: row.user_agent,
4973
+ countryCode: row.country_code,
4974
+ requestPath: row.request_path,
4975
+ requestMethod: row.request_method,
4976
+ details: row.details ? JSON.parse(row.details) : null,
4977
+ fingerprint: row.fingerprint,
4978
+ blocked: !!row.blocked,
4979
+ createdAt: row.created_at
4980
+ }));
4981
+ }
4982
+ };
4983
+
4984
+ // src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts
4985
+ chunkH4NHRZ6Y_cjs.init_admin_layout_catalyst_template();
4986
+ function formatTimestamp(ts) {
4987
+ const date = new Date(ts);
4988
+ const now = Date.now();
4989
+ const diff = now - ts;
4990
+ if (diff < 6e4) return "just now";
4991
+ if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
4992
+ if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
4993
+ return date.toLocaleDateString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
4994
+ }
4995
+ function severityBadge(severity) {
4996
+ const colors = {
4997
+ info: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
4998
+ warning: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400",
4999
+ critical: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
5000
+ };
5001
+ return `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}">${severity}</span>`;
5002
+ }
5003
+ function eventTypeBadge(type) {
5004
+ const labels = {
5005
+ login_success: "Login OK",
5006
+ login_failure: "Login Failed",
5007
+ registration: "Registration",
5008
+ account_lockout: "Lockout",
5009
+ suspicious_activity: "Suspicious",
5010
+ logout: "Logout",
5011
+ password_reset_request: "Password Reset",
5012
+ permission_denied: "Access Denied"
5013
+ };
5014
+ return labels[type] || type;
5015
+ }
5016
+ function trendArrow(trend) {
5017
+ if (trend > 0) return `<span class="text-red-500">+${trend}%</span>`;
5018
+ if (trend < 0) return `<span class="text-emerald-500">${trend}%</span>`;
5019
+ return `<span class="text-zinc-400">0%</span>`;
5020
+ }
5021
+ function renderBarChart(data) {
5022
+ if (data.length === 0) return '<p class="text-zinc-500 text-sm">No data available</p>';
5023
+ const max = Math.max(...data.map((d) => d.count), 1);
5024
+ const bars = data.map((d) => {
5025
+ const height = Math.max(d.count / max * 100, 2);
5026
+ const color = d.count === 0 ? "bg-zinc-200 dark:bg-zinc-700" : d.count >= max * 0.75 ? "bg-red-500" : d.count >= max * 0.5 ? "bg-amber-500" : "bg-cyan-500";
5027
+ return `
5028
+ <div class="flex flex-col items-center flex-1 min-w-0 group relative">
5029
+ <div class="w-full flex flex-col items-center justify-end" style="height: 120px">
5030
+ <div class="absolute bottom-8 hidden group-hover:block bg-zinc-900 text-white text-xs rounded px-2 py-1 whitespace-nowrap z-10">
5031
+ ${d.hour}: ${d.count} failed
5032
+ </div>
5033
+ <div class="${color} w-full max-w-[12px] rounded-t transition-all" style="height: ${height}%"></div>
5034
+ </div>
5035
+ <span class="text-[9px] text-zinc-400 mt-1 ${data.length > 12 ? "hidden sm:block" : ""}">${d.hour}</span>
5036
+ </div>
5037
+ `;
5038
+ }).join("");
5039
+ return `<div class="flex items-end gap-px">${bars}</div>`;
5040
+ }
5041
+ function renderSecurityDashboard(data) {
5042
+ const { stats, topIPs, hourlyTrend, recentCritical, user, version, dynamicMenuItems } = data;
5043
+ const content2 = `
5044
+ <div>
5045
+ <div class="sm:flex sm:items-center sm:justify-between mb-6">
5046
+ <div class="sm:flex-auto">
5047
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Security Dashboard</h1>
5048
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
5049
+ Monitor login attempts, brute-force detection, and security events.
5050
+ </p>
5051
+ </div>
5052
+ <div class="mt-4 sm:mt-0 sm:ml-16 flex gap-x-2">
5053
+ <a href="/admin/plugins/security-audit/events"
5054
+ class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm">
5055
+ View Event Log
5056
+ </a>
5057
+ <a href="/api/security-audit/export?format=csv"
5058
+ class="inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm">
5059
+ Export CSV
5060
+ </a>
5061
+ </div>
5062
+ </div>
5063
+
5064
+ <!-- Summary Cards -->
5065
+ <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-6">
5066
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5067
+ <p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Total Events</p>
5068
+ <p class="mt-2 text-3xl font-bold text-zinc-950 dark:text-white">${stats.totalEvents.toLocaleString()}</p>
5069
+ </div>
5070
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5071
+ <p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Failed Logins (24h)</p>
5072
+ <p class="mt-2 text-3xl font-bold text-zinc-950 dark:text-white">
5073
+ ${stats.failedLogins24h}
5074
+ <span class="ml-2 text-sm font-normal">${trendArrow(stats.failedLoginsTrend)}</span>
5075
+ </p>
5076
+ </div>
5077
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5078
+ <p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Active Lockouts</p>
5079
+ <p class="mt-2 text-3xl font-bold ${stats.activeLockouts > 0 ? "text-red-600 dark:text-red-400" : "text-zinc-950 dark:text-white"}">${stats.activeLockouts}</p>
5080
+ </div>
5081
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5082
+ <p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Flagged IPs</p>
5083
+ <p class="mt-2 text-3xl font-bold ${stats.flaggedIPs > 0 ? "text-amber-600 dark:text-amber-400" : "text-zinc-950 dark:text-white"}">${stats.flaggedIPs}</p>
5084
+ </div>
5085
+ </div>
5086
+
5087
+ <!-- Charts Row -->
5088
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
5089
+ <!-- Failed Login Trend -->
5090
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5091
+ <h2 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Failed Login Attempts (24h)</h2>
5092
+ ${renderBarChart(hourlyTrend)}
5093
+ </div>
5094
+
5095
+ <!-- Events by Type -->
5096
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5097
+ <h2 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Events by Type (24h)</h2>
5098
+ <div class="space-y-3">
5099
+ ${Object.entries(stats.eventsByType).length === 0 ? '<p class="text-zinc-500 text-sm">No events in the last 24 hours</p>' : Object.entries(stats.eventsByType).sort(([, a], [, b]) => b - a).map(([type, count]) => {
5100
+ const total = Object.values(stats.eventsByType).reduce((s, v) => s + v, 0);
5101
+ const pct = total > 0 ? Math.round(count / total * 100) : 0;
5102
+ return `
5103
+ <div>
5104
+ <div class="flex justify-between text-sm mb-1">
5105
+ <span class="text-zinc-600 dark:text-zinc-300">${eventTypeBadge(type)}</span>
5106
+ <span class="text-zinc-500 dark:text-zinc-400">${count}</span>
5107
+ </div>
5108
+ <div class="w-full bg-zinc-100 dark:bg-zinc-800 rounded-full h-1.5">
5109
+ <div class="h-1.5 rounded-full ${type === "login_failure" ? "bg-red-500" : type === "login_success" ? "bg-emerald-500" : "bg-cyan-500"}" style="width: ${pct}%"></div>
5110
+ </div>
5111
+ </div>
5112
+ `;
5113
+ }).join("")}
5114
+ </div>
5115
+ </div>
5116
+ </div>
5117
+
5118
+ <!-- Top IPs and Recent Critical -->
5119
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
5120
+ <!-- Top IPs -->
5121
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden">
5122
+ <div class="p-5 border-b border-zinc-100 dark:border-zinc-800">
5123
+ <h2 class="text-sm font-semibold text-zinc-950 dark:text-white">Top IPs by Failed Logins (24h)</h2>
5124
+ </div>
5125
+ ${topIPs.length === 0 ? '<div class="p-5"><p class="text-zinc-500 text-sm">No failed login attempts</p></div>' : `<table class="min-w-full">
5126
+ <thead>
5127
+ <tr class="border-b border-zinc-100 dark:border-zinc-800">
5128
+ <th class="px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase">IP Address</th>
5129
+ <th class="px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase">Country</th>
5130
+ <th class="px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase">Attempts</th>
5131
+ <th class="px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase">Status</th>
5132
+ </tr>
5133
+ </thead>
5134
+ <tbody>
5135
+ ${topIPs.map((ip) => `
5136
+ <tr class="border-b border-zinc-50 dark:border-zinc-800/50 hover:bg-zinc-50 dark:hover:bg-zinc-800/50">
5137
+ <td class="px-5 py-3 text-sm font-mono text-zinc-900 dark:text-zinc-100">${ip.ipAddress}</td>
5138
+ <td class="px-5 py-3 text-sm text-zinc-600 dark:text-zinc-400">${ip.countryCode || "-"}</td>
5139
+ <td class="px-5 py-3 text-sm text-right font-semibold ${ip.failedAttempts >= 10 ? "text-red-600 dark:text-red-400" : "text-zinc-900 dark:text-zinc-100"}">${ip.failedAttempts}</td>
5140
+ <td class="px-5 py-3 text-sm text-right">
5141
+ ${ip.locked ? '<span class="inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400">Locked</span>' : '<span class="inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400">Active</span>'}
5142
+ </td>
5143
+ </tr>
5144
+ `).join("")}
5145
+ </tbody>
5146
+ </table>`}
5147
+ </div>
5148
+
5149
+ <!-- Recent Critical Events -->
5150
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden">
5151
+ <div class="p-5 border-b border-zinc-100 dark:border-zinc-800">
5152
+ <h2 class="text-sm font-semibold text-zinc-950 dark:text-white">Recent Critical Events</h2>
5153
+ </div>
5154
+ ${recentCritical.length === 0 ? '<div class="p-5"><p class="text-zinc-500 text-sm">No critical events</p></div>' : `<div class="divide-y divide-zinc-100 dark:divide-zinc-800">
5155
+ ${recentCritical.slice(0, 10).map((event) => `
5156
+ <div class="px-5 py-3 hover:bg-zinc-50 dark:hover:bg-zinc-800/50">
5157
+ <div class="flex items-center justify-between">
5158
+ <div class="flex items-center gap-2">
5159
+ ${severityBadge(event.severity)}
5160
+ <span class="text-sm font-medium text-zinc-900 dark:text-zinc-100">${eventTypeBadge(event.eventType)}</span>
5161
+ </div>
5162
+ <span class="text-xs text-zinc-400">${formatTimestamp(event.createdAt)}</span>
5163
+ </div>
5164
+ <div class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">
5165
+ ${event.ipAddress ? `IP: ${event.ipAddress}` : ""}
5166
+ ${event.email ? ` | ${event.email}` : ""}
5167
+ </div>
5168
+ </div>
5169
+ `).join("")}
5170
+ </div>`}
5171
+ </div>
5172
+ </div>
5173
+ </div>
5174
+ `;
5175
+ const layoutData = {
5176
+ title: "Security Dashboard",
5177
+ pageTitle: "Security Dashboard",
5178
+ currentPath: "/admin/plugins/security-audit",
5179
+ user,
5180
+ content: content2,
5181
+ version,
5182
+ dynamicMenuItems
5183
+ };
5184
+ return chunkH4NHRZ6Y_cjs.renderAdminLayoutCatalyst(layoutData);
5185
+ }
5186
+
5187
+ // src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts
5188
+ chunkH4NHRZ6Y_cjs.init_admin_layout_catalyst_template();
5189
+ function formatTimestamp2(ts) {
5190
+ const date = new Date(ts);
5191
+ return date.toLocaleDateString("en-US", {
5192
+ month: "short",
5193
+ day: "numeric",
5194
+ year: "numeric",
5195
+ hour: "2-digit",
5196
+ minute: "2-digit",
5197
+ second: "2-digit"
5198
+ });
5199
+ }
5200
+ function severityBadge2(severity) {
5201
+ const colors = {
5202
+ info: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
5203
+ warning: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400",
5204
+ critical: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
5205
+ };
5206
+ return `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}">${severity}</span>`;
5207
+ }
5208
+ function eventTypeBadge2(type) {
5209
+ const colors = {
5210
+ login_success: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400",
5211
+ login_failure: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
5212
+ registration: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
5213
+ account_lockout: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
5214
+ suspicious_activity: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400",
5215
+ logout: "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400",
5216
+ password_reset_request: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400",
5217
+ permission_denied: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400"
5218
+ };
5219
+ const labels = {
5220
+ login_success: "Login OK",
5221
+ login_failure: "Login Failed",
5222
+ registration: "Registration",
5223
+ account_lockout: "Lockout",
5224
+ suspicious_activity: "Suspicious",
5225
+ logout: "Logout",
5226
+ password_reset_request: "Password Reset",
5227
+ permission_denied: "Access Denied"
5228
+ };
5229
+ const color = colors[type] || "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400";
5230
+ return `<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${color}">${labels[type] || type}</span>`;
5231
+ }
5232
+ function buildFilterUrl(filters, overrides = {}) {
5233
+ const params = new URLSearchParams();
5234
+ if (filters.eventType && !overrides.type) params.set("type", String(filters.eventType));
5235
+ if (filters.severity && !overrides.severity) params.set("severity", String(filters.severity));
5236
+ if (filters.email && !overrides.email) params.set("email", filters.email);
5237
+ if (filters.ipAddress && !overrides.ip) params.set("ip", filters.ipAddress);
5238
+ if (filters.search && !overrides.search) params.set("search", filters.search);
5239
+ for (const [key, value] of Object.entries(overrides)) {
5240
+ if (value) params.set(key, value);
5241
+ }
5242
+ const qs = params.toString();
5243
+ return `/admin/plugins/security-audit/events${qs ? "?" + qs : ""}`;
5244
+ }
5245
+ function renderEventLogPage(data) {
5246
+ const { events, pagination, filters, user, version, dynamicMenuItems } = data;
5247
+ const content2 = `
5248
+ <div>
5249
+ <div class="sm:flex sm:items-center sm:justify-between mb-6">
5250
+ <div class="sm:flex-auto">
5251
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Security Event Log</h1>
5252
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
5253
+ Browse and filter all security events. Showing ${pagination.startItem}-${pagination.endItem} of ${pagination.totalItems}.
5254
+ </p>
5255
+ </div>
5256
+ <div class="mt-4 sm:mt-0 sm:ml-16 flex gap-x-2">
5257
+ <a href="/admin/plugins/security-audit"
5258
+ class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm">
5259
+ Dashboard
5260
+ </a>
5261
+ </div>
5262
+ </div>
5263
+
5264
+ <!-- Filters -->
5265
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm mb-6">
5266
+ <form method="GET" action="/admin/plugins/security-audit/events" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4">
5267
+ <div>
5268
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Event Type</label>
5269
+ <select name="type" class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5270
+ <option value="">All Types</option>
5271
+ <option value="login_success" ${filters.eventType === "login_success" ? "selected" : ""}>Login Success</option>
5272
+ <option value="login_failure" ${filters.eventType === "login_failure" ? "selected" : ""}>Login Failure</option>
5273
+ <option value="registration" ${filters.eventType === "registration" ? "selected" : ""}>Registration</option>
5274
+ <option value="account_lockout" ${filters.eventType === "account_lockout" ? "selected" : ""}>Account Lockout</option>
5275
+ <option value="suspicious_activity" ${filters.eventType === "suspicious_activity" ? "selected" : ""}>Suspicious Activity</option>
5276
+ <option value="logout" ${filters.eventType === "logout" ? "selected" : ""}>Logout</option>
5277
+ </select>
5278
+ </div>
5279
+ <div>
5280
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Severity</label>
5281
+ <select name="severity" class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5282
+ <option value="">All Severities</option>
5283
+ <option value="info" ${filters.severity === "info" ? "selected" : ""}>Info</option>
5284
+ <option value="warning" ${filters.severity === "warning" ? "selected" : ""}>Warning</option>
5285
+ <option value="critical" ${filters.severity === "critical" ? "selected" : ""}>Critical</option>
5286
+ </select>
5287
+ </div>
5288
+ <div>
5289
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Email</label>
5290
+ <input type="text" name="email" value="${filters.email || ""}" placeholder="Filter by email"
5291
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400">
5292
+ </div>
5293
+ <div>
5294
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">IP Address</label>
5295
+ <input type="text" name="ip" value="${filters.ipAddress || ""}" placeholder="Filter by IP"
5296
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400">
5297
+ </div>
5298
+ <div class="flex items-end gap-2">
5299
+ <button type="submit"
5300
+ class="flex-1 rounded-lg bg-cyan-600 px-3 py-2 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm">
5301
+ Filter
5302
+ </button>
5303
+ <a href="/admin/plugins/security-audit/events"
5304
+ class="rounded-lg bg-zinc-100 dark:bg-zinc-800 px-3 py-2 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors">
5305
+ Clear
5306
+ </a>
5307
+ </div>
5308
+ </form>
5309
+ </div>
5310
+
5311
+ <!-- Events Table -->
5312
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden">
5313
+ ${events.length === 0 ? `<div class="p-12 text-center">
5314
+ <svg class="mx-auto h-12 w-12 text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5315
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
5316
+ </svg>
5317
+ <h3 class="mt-2 text-sm font-semibold text-zinc-900 dark:text-white">No events found</h3>
5318
+ <p class="mt-1 text-sm text-zinc-500">No security events match your current filters.</p>
5319
+ </div>` : `<div class="overflow-x-auto">
5320
+ <table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
5321
+ <thead>
5322
+ <tr>
5323
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Time</th>
5324
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Type</th>
5325
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Severity</th>
5326
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Email</th>
5327
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">IP Address</th>
5328
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Country</th>
5329
+ <th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider">Status</th>
5330
+ </tr>
5331
+ </thead>
5332
+ <tbody class="divide-y divide-zinc-100 dark:divide-zinc-800">
5333
+ ${events.map((event) => `
5334
+ <tr class="hover:bg-zinc-50 dark:hover:bg-zinc-800/50 cursor-pointer" onclick="this.querySelector('.event-details').classList.toggle('hidden')">
5335
+ <td class="px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 whitespace-nowrap">${formatTimestamp2(event.createdAt)}</td>
5336
+ <td class="px-4 py-3">${eventTypeBadge2(event.eventType)}</td>
5337
+ <td class="px-4 py-3">${severityBadge2(event.severity)}</td>
5338
+ <td class="px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 max-w-[200px] truncate">${event.email || "-"}</td>
5339
+ <td class="px-4 py-3 text-sm font-mono text-zinc-600 dark:text-zinc-300">${event.ipAddress || "-"}</td>
5340
+ <td class="px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300">${event.countryCode || "-"}</td>
5341
+ <td class="px-4 py-3">
5342
+ ${event.blocked ? '<span class="inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400">Blocked</span>' : '<span class="inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400">Allowed</span>'}
5343
+ </td>
5344
+ </tr>
5345
+ <tr class="event-details hidden">
5346
+ <td colspan="7" class="px-4 py-3 bg-zinc-50 dark:bg-zinc-800/30">
5347
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4 text-xs">
5348
+ <div><span class="font-medium text-zinc-500">Event ID:</span> <span class="text-zinc-700 dark:text-zinc-300 font-mono">${event.id.substring(0, 8)}...</span></div>
5349
+ <div><span class="font-medium text-zinc-500">User Agent:</span> <span class="text-zinc-700 dark:text-zinc-300 truncate block max-w-[300px]">${event.userAgent || "-"}</span></div>
5350
+ <div><span class="font-medium text-zinc-500">Path:</span> <span class="text-zinc-700 dark:text-zinc-300">${event.requestPath || "-"}</span></div>
5351
+ <div><span class="font-medium text-zinc-500">Fingerprint:</span> <span class="text-zinc-700 dark:text-zinc-300 font-mono">${event.fingerprint || "-"}</span></div>
5352
+ ${event.details ? `<div class="col-span-full"><span class="font-medium text-zinc-500">Details:</span> <pre class="text-zinc-700 dark:text-zinc-300 mt-1 bg-zinc-100 dark:bg-zinc-900 rounded p-2 overflow-x-auto">${JSON.stringify(event.details, null, 2)}</pre></div>` : ""}
5353
+ </div>
5354
+ </td>
5355
+ </tr>
5356
+ `).join("")}
5357
+ </tbody>
5358
+ </table>
5359
+ </div>`}
5360
+
5361
+ <!-- Pagination -->
5362
+ ${pagination.totalPages > 1 ? `
5363
+ <div class="flex items-center justify-between border-t border-zinc-200 dark:border-zinc-800 px-4 py-3">
5364
+ <div class="text-sm text-zinc-500">
5365
+ Page ${pagination.currentPage} of ${pagination.totalPages}
5366
+ </div>
5367
+ <div class="flex gap-1">
5368
+ ${pagination.currentPage > 1 ? `
5369
+ <a href="${buildFilterUrl(filters, { page: String(pagination.currentPage - 1) })}"
5370
+ class="rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors">
5371
+ Previous
5372
+ </a>
5373
+ ` : ""}
5374
+ ${pagination.currentPage < pagination.totalPages ? `
5375
+ <a href="${buildFilterUrl(filters, { page: String(pagination.currentPage + 1) })}"
5376
+ class="rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors">
5377
+ Next
5378
+ </a>
5379
+ ` : ""}
5380
+ </div>
5381
+ </div>
5382
+ ` : ""}
5383
+ </div>
5384
+ </div>
5385
+ `;
5386
+ const layoutData = {
5387
+ title: "Security Event Log",
5388
+ pageTitle: "Security Event Log",
5389
+ currentPath: "/admin/plugins/security-audit/events",
5390
+ user,
5391
+ content: content2,
5392
+ version,
5393
+ dynamicMenuItems
5394
+ };
5395
+ return chunkH4NHRZ6Y_cjs.renderAdminLayoutCatalyst(layoutData);
5396
+ }
5397
+
5398
+ // src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts
5399
+ chunkH4NHRZ6Y_cjs.init_admin_layout_catalyst_template();
5400
+ function renderSecuritySettingsPage(data) {
5401
+ const { settings, user, version, message, dynamicMenuItems } = data;
5402
+ const content2 = `
5403
+ <div>
5404
+ <div class="sm:flex sm:items-center sm:justify-between mb-6">
5405
+ <div class="sm:flex-auto">
5406
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Security Audit Settings</h1>
5407
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
5408
+ Configure brute-force detection thresholds, event logging, and data retention.
5409
+ </p>
5410
+ </div>
5411
+ <div class="mt-4 sm:mt-0 sm:ml-16 flex gap-x-2">
5412
+ <a href="/admin/plugins/security-audit"
5413
+ class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm">
5414
+ Dashboard
5415
+ </a>
5416
+ </div>
5417
+ </div>
5418
+
5419
+ ${message ? `
5420
+ <div class="mb-6 rounded-lg bg-emerald-50 dark:bg-emerald-900/20 p-4 ring-1 ring-emerald-200 dark:ring-emerald-800">
5421
+ <p class="text-sm text-emerald-800 dark:text-emerald-300">${message}</p>
5422
+ </div>
5423
+ ` : ""}
5424
+
5425
+ <form method="POST" action="/admin/plugins/security-audit/settings"
5426
+ class="space-y-6"
5427
+ hx-post="/admin/plugins/security-audit/settings"
5428
+ hx-swap="none"
5429
+ hx-on::after-request="if(event.detail.successful) { window.showNotification && window.showNotification('Settings saved', 'success'); } else { window.showNotification && window.showNotification('Failed to save', 'error'); }">
5430
+
5431
+ <!-- Brute Force Detection -->
5432
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5433
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Brute-Force Detection</h2>
5434
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
5435
+ <div>
5436
+ <label class="flex items-center gap-2 mb-4">
5437
+ <input type="checkbox" name="bruteForce.enabled" value="true" ${settings.bruteForce.enabled ? "checked" : ""}
5438
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5439
+ <span class="text-sm font-medium text-zinc-700 dark:text-zinc-300">Enable brute-force detection</span>
5440
+ </label>
5441
+ </div>
5442
+ <div></div><div></div>
5443
+ <div>
5444
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Max Failed Attempts per IP</label>
5445
+ <input type="number" name="bruteForce.maxFailedAttemptsPerIP" value="${settings.bruteForce.maxFailedAttemptsPerIP}" min="1" max="100"
5446
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5447
+ </div>
5448
+ <div>
5449
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Max Failed Attempts per Email</label>
5450
+ <input type="number" name="bruteForce.maxFailedAttemptsPerEmail" value="${settings.bruteForce.maxFailedAttemptsPerEmail}" min="1" max="100"
5451
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5452
+ </div>
5453
+ <div>
5454
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Window (minutes)</label>
5455
+ <input type="number" name="bruteForce.windowMinutes" value="${settings.bruteForce.windowMinutes}" min="1" max="1440"
5456
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5457
+ </div>
5458
+ <div>
5459
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Lockout Duration (minutes)</label>
5460
+ <input type="number" name="bruteForce.lockoutDurationMinutes" value="${settings.bruteForce.lockoutDurationMinutes}" min="1" max="1440"
5461
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5462
+ </div>
5463
+ <div>
5464
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Alert Threshold</label>
5465
+ <input type="number" name="bruteForce.alertThreshold" value="${settings.bruteForce.alertThreshold}" min="1" max="1000"
5466
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5467
+ <p class="mt-1 text-xs text-zinc-400">Events above this count trigger critical severity</p>
5468
+ </div>
5469
+ </div>
5470
+ </div>
5471
+
5472
+ <!-- Event Logging -->
5473
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5474
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Event Logging</h2>
5475
+ <div class="space-y-3">
5476
+ <label class="flex items-center gap-2">
5477
+ <input type="checkbox" name="logging.logSuccessfulLogins" value="true" ${settings.logging.logSuccessfulLogins ? "checked" : ""}
5478
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5479
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Log successful logins</span>
5480
+ </label>
5481
+ <label class="flex items-center gap-2">
5482
+ <input type="checkbox" name="logging.logLogouts" value="true" ${settings.logging.logLogouts ? "checked" : ""}
5483
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5484
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Log logouts</span>
5485
+ </label>
5486
+ <label class="flex items-center gap-2">
5487
+ <input type="checkbox" name="logging.logRegistrations" value="true" ${settings.logging.logRegistrations ? "checked" : ""}
5488
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5489
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Log registrations</span>
5490
+ </label>
5491
+ <label class="flex items-center gap-2">
5492
+ <input type="checkbox" name="logging.logPasswordResets" value="true" ${settings.logging.logPasswordResets ? "checked" : ""}
5493
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5494
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Log password resets</span>
5495
+ </label>
5496
+ <label class="flex items-center gap-2">
5497
+ <input type="checkbox" name="logging.logPermissionDenied" value="true" ${settings.logging.logPermissionDenied ? "checked" : ""}
5498
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5499
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Log permission denied events</span>
5500
+ </label>
5501
+ </div>
5502
+ </div>
5503
+
5504
+ <!-- Data Retention -->
5505
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
5506
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Data Retention</h2>
5507
+ <div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
5508
+ <div>
5509
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Days to Keep</label>
5510
+ <input type="number" name="retention.daysToKeep" value="${settings.retention.daysToKeep}" min="1" max="365"
5511
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5512
+ </div>
5513
+ <div>
5514
+ <label class="block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1">Max Events</label>
5515
+ <input type="number" name="retention.maxEvents" value="${settings.retention.maxEvents}" min="1000" max="1000000"
5516
+ class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500">
5517
+ </div>
5518
+ <div>
5519
+ <label class="flex items-center gap-2 mt-5">
5520
+ <input type="checkbox" name="retention.autoPurge" value="true" ${settings.retention.autoPurge ? "checked" : ""}
5521
+ class="rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500">
5522
+ <span class="text-sm text-zinc-700 dark:text-zinc-300">Auto-purge old events</span>
5523
+ </label>
5524
+ </div>
5525
+ </div>
5526
+ </div>
5527
+
5528
+ <!-- Actions -->
5529
+ <div class="flex items-center justify-between">
5530
+ <button type="button"
5531
+ onclick="if(confirm('Purge events older than retention period?')) fetch('/api/security-audit/events/purge', {method:'POST',headers:{'Content-Type':'application/json'}}).then(r=>r.json()).then(d=>window.showNotification && window.showNotification('Purged '+d.deleted+' events','success'))"
5532
+ class="rounded-lg bg-red-50 dark:bg-red-900/20 px-4 py-2.5 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 ring-1 ring-red-200 dark:ring-red-800 transition-colors">
5533
+ Purge Old Events
5534
+ </button>
5535
+ <button type="submit"
5536
+ class="rounded-lg bg-cyan-600 px-6 py-2.5 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm">
5537
+ Save Settings
5538
+ </button>
5539
+ </div>
5540
+ </form>
5541
+ </div>
5542
+ `;
5543
+ const layoutData = {
5544
+ title: "Security Audit Settings",
5545
+ pageTitle: "Security Audit Settings",
5546
+ currentPath: "/admin/plugins/security-audit/settings",
5547
+ user,
5548
+ content: content2,
5549
+ version,
5550
+ dynamicMenuItems
5551
+ };
5552
+ return chunkH4NHRZ6Y_cjs.renderAdminLayoutCatalyst(layoutData);
5553
+ }
5554
+
5555
+ // src/plugins/core-plugins/security-audit-plugin/routes/admin.ts
5556
+ var adminRoutes2 = new hono.Hono();
5557
+ adminRoutes2.use("*", chunkVHNTCB2X_cjs.requireAuth());
5558
+ adminRoutes2.use("*", async (c, next) => {
5559
+ const user = c.get("user");
5560
+ if (user?.role !== "admin") {
5561
+ return c.text("Access denied", 403);
5562
+ }
5563
+ return next();
5564
+ });
5565
+ async function getSettings(db) {
5566
+ try {
5567
+ const pluginService = new chunkI6FFGQIT_cjs.PluginService(db);
5568
+ const plugin2 = await pluginService.getPlugin("security-audit");
5569
+ if (plugin2?.settings) {
5570
+ const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
5571
+ return { ...DEFAULT_SETTINGS2, ...settings };
5572
+ }
5573
+ } catch {
5574
+ }
5575
+ return DEFAULT_SETTINGS2;
5576
+ }
5577
+ adminRoutes2.get("/", async (c) => {
5578
+ const db = c.env.DB;
5579
+ const user = c.get("user");
5580
+ const settings = await getSettings(db);
5581
+ const service = new SecurityAuditService(db, settings);
5582
+ const [stats, topIPs, hourlyTrend, recentCritical] = await Promise.all([
5583
+ service.getStats(),
5584
+ service.getTopIPs(10),
5585
+ service.getHourlyTrend(24),
5586
+ service.getRecentCriticalEvents(20)
5587
+ ]);
5588
+ const pageData = {
5589
+ stats,
5590
+ topIPs,
5591
+ hourlyTrend,
5592
+ recentCritical,
5593
+ user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
5594
+ version: c.get("appVersion"),
5595
+ dynamicMenuItems: c.get("pluginMenuItems")
5596
+ };
5597
+ return c.html(renderSecurityDashboard(pageData));
5598
+ });
5599
+ adminRoutes2.get("/events", async (c) => {
5600
+ const db = c.env.DB;
5601
+ const user = c.get("user");
5602
+ const settings = await getSettings(db);
5603
+ const service = new SecurityAuditService(db, settings);
5604
+ const page = parseInt(c.req.query("page") || "1");
5605
+ const limit = 50;
5606
+ const filters = {
5607
+ eventType: c.req.query("type") || void 0,
5608
+ severity: c.req.query("severity") || void 0,
5609
+ email: c.req.query("email") || void 0,
5610
+ ipAddress: c.req.query("ip") || void 0,
5611
+ search: c.req.query("search") || void 0,
5612
+ page,
5613
+ limit
5614
+ };
5615
+ const { events, total } = await service.getEvents(filters);
5616
+ const totalPages = Math.ceil(total / limit);
5617
+ const pageData = {
5618
+ events,
5619
+ pagination: {
5620
+ currentPage: page,
5621
+ totalPages,
5622
+ totalItems: total,
5623
+ itemsPerPage: limit,
5624
+ startItem: total === 0 ? 0 : (page - 1) * limit + 1,
5625
+ endItem: Math.min(page * limit, total)
5626
+ },
5627
+ filters,
5628
+ user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
5629
+ version: c.get("appVersion"),
5630
+ dynamicMenuItems: c.get("pluginMenuItems")
5631
+ };
5632
+ return c.html(renderEventLogPage(pageData));
5633
+ });
5634
+ adminRoutes2.get("/settings", async (c) => {
5635
+ const db = c.env.DB;
5636
+ const user = c.get("user");
5637
+ const settings = await getSettings(db);
5638
+ const pageData = {
5639
+ settings,
5640
+ user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
5641
+ version: c.get("appVersion"),
5642
+ message: c.req.query("message") || void 0,
5643
+ dynamicMenuItems: c.get("pluginMenuItems")
5644
+ };
5645
+ return c.html(renderSecuritySettingsPage(pageData));
5646
+ });
5647
+ adminRoutes2.post("/settings", async (c) => {
5648
+ const db = c.env.DB;
5649
+ const body = await c.req.parseBody();
5650
+ const settings = {
5651
+ bruteForce: {
5652
+ enabled: body["bruteForce.enabled"] === "true",
5653
+ maxFailedAttemptsPerIP: parseInt(body["bruteForce.maxFailedAttemptsPerIP"]) || 10,
5654
+ maxFailedAttemptsPerEmail: parseInt(body["bruteForce.maxFailedAttemptsPerEmail"]) || 5,
5655
+ windowMinutes: parseInt(body["bruteForce.windowMinutes"]) || 15,
5656
+ lockoutDurationMinutes: parseInt(body["bruteForce.lockoutDurationMinutes"]) || 30,
5657
+ alertThreshold: parseInt(body["bruteForce.alertThreshold"]) || 20
5658
+ },
5659
+ logging: {
5660
+ logSuccessfulLogins: body["logging.logSuccessfulLogins"] === "true",
5661
+ logLogouts: body["logging.logLogouts"] === "true",
5662
+ logRegistrations: body["logging.logRegistrations"] === "true",
5663
+ logPasswordResets: body["logging.logPasswordResets"] === "true",
5664
+ logPermissionDenied: body["logging.logPermissionDenied"] === "true"
5665
+ },
5666
+ retention: {
5667
+ daysToKeep: parseInt(body["retention.daysToKeep"]) || 90,
5668
+ maxEvents: parseInt(body["retention.maxEvents"]) || 1e5,
5669
+ autoPurge: body["retention.autoPurge"] === "true"
5670
+ }
5671
+ };
5672
+ const pluginService = new chunkI6FFGQIT_cjs.PluginService(db);
5673
+ await pluginService.updatePluginSettings("security-audit", settings);
5674
+ if (c.req.header("HX-Request")) {
5675
+ return c.json({ success: true });
5676
+ }
5677
+ return c.redirect("/admin/plugins/security-audit/settings?message=Settings saved successfully");
5678
+ });
5679
+
5680
+ // src/plugins/core-plugins/security-audit-plugin/services/brute-force-detector.ts
5681
+ var KV_PREFIX = "security:bf:";
5682
+ var LOCK_PREFIX = "security:locked:";
5683
+ var BruteForceDetector = class {
5684
+ constructor(kv, settings) {
5685
+ this.kv = kv;
5686
+ this.settings = settings || DEFAULT_SETTINGS2.bruteForce;
5687
+ }
5688
+ settings;
5689
+ async recordFailedAttempt(ip, email) {
5690
+ if (!this.settings.enabled) {
5691
+ return { ipCount: 0, emailCount: 0, shouldLockIP: false, shouldLockEmail: false, isSuspicious: false };
5692
+ }
5693
+ const windowMs = this.settings.windowMinutes * 60 * 1e3;
5694
+ const ipKey = `${KV_PREFIX}ip:${ip}`;
5695
+ const ipCount = await this.incrementCounter(ipKey, windowMs);
5696
+ const emailKey = `${KV_PREFIX}email:${email}`;
5697
+ const emailCount = await this.incrementCounter(emailKey, windowMs);
5698
+ const ipEmailsKey = `${KV_PREFIX}ip-emails:${ip}`;
5699
+ await this.addToSet(ipEmailsKey, email, windowMs);
5700
+ const emailsFromIP = await this.getSetSize(ipEmailsKey);
5701
+ const isSuspicious = emailsFromIP >= 5;
5702
+ const shouldLockIP = ipCount >= this.settings.maxFailedAttemptsPerIP;
5703
+ const shouldLockEmail = emailCount >= this.settings.maxFailedAttemptsPerEmail;
5704
+ return { ipCount, emailCount, shouldLockIP, shouldLockEmail, isSuspicious };
5705
+ }
5706
+ async isLocked(ip, email) {
5707
+ if (!this.settings.enabled) {
5708
+ return { locked: false };
5709
+ }
5710
+ const ipLocked = await this.kv.get(`${LOCK_PREFIX}ip:${ip}`);
5711
+ if (ipLocked) {
5712
+ return { locked: true, reason: "IP address temporarily locked due to excessive failed login attempts" };
5713
+ }
5714
+ const emailLocked = await this.kv.get(`${LOCK_PREFIX}email:${email}`);
5715
+ if (emailLocked) {
5716
+ return { locked: true, reason: "Account temporarily locked due to excessive failed login attempts" };
5717
+ }
5718
+ return { locked: false };
5719
+ }
5720
+ async lockIP(ip) {
5721
+ const ttl = this.settings.lockoutDurationMinutes * 60;
5722
+ await this.kv.put(`${LOCK_PREFIX}ip:${ip}`, JSON.stringify({
5723
+ lockedAt: Date.now(),
5724
+ reason: "brute_force_ip"
5725
+ }), { expirationTtl: ttl });
5726
+ }
5727
+ async lockEmail(email) {
5728
+ const ttl = this.settings.lockoutDurationMinutes * 60;
5729
+ await this.kv.put(`${LOCK_PREFIX}email:${email}`, JSON.stringify({
5730
+ lockedAt: Date.now(),
5731
+ reason: "brute_force_email"
5732
+ }), { expirationTtl: ttl });
5733
+ }
5734
+ async unlockIP(ip) {
5735
+ await this.kv.delete(`${LOCK_PREFIX}ip:${ip}`);
5736
+ }
5737
+ async unlockEmail(email) {
5738
+ await this.kv.delete(`${LOCK_PREFIX}email:${email}`);
5739
+ }
5740
+ async getActiveLockouts() {
5741
+ const ipLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}ip:` });
5742
+ const emailLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}email:` });
5743
+ const lockouts = [];
5744
+ for (const key of ipLocks.keys) {
5745
+ const data = await this.kv.get(key.name);
5746
+ if (data) {
5747
+ const parsed = JSON.parse(data);
5748
+ lockouts.push({
5749
+ key: key.name,
5750
+ type: "ip",
5751
+ value: key.name.replace(`${LOCK_PREFIX}ip:`, ""),
5752
+ lockedAt: parsed.lockedAt
5753
+ });
5754
+ }
5755
+ }
5756
+ for (const key of emailLocks.keys) {
5757
+ const data = await this.kv.get(key.name);
5758
+ if (data) {
5759
+ const parsed = JSON.parse(data);
5760
+ lockouts.push({
5761
+ key: key.name,
5762
+ type: "email",
5763
+ value: key.name.replace(`${LOCK_PREFIX}email:`, ""),
5764
+ lockedAt: parsed.lockedAt
5765
+ });
5766
+ }
5767
+ }
5768
+ return lockouts;
5769
+ }
5770
+ async releaseLockout(key) {
5771
+ await this.kv.delete(key);
5772
+ }
5773
+ isAboveAlertThreshold(count) {
5774
+ return count >= this.settings.alertThreshold;
5775
+ }
5776
+ async incrementCounter(key, windowMs) {
5777
+ const existing = await this.kv.get(key);
5778
+ const now = Date.now();
5779
+ let entries = [];
5780
+ if (existing) {
5781
+ try {
5782
+ entries = JSON.parse(existing);
5783
+ } catch {
5784
+ entries = [];
5785
+ }
5786
+ }
5787
+ const cutoff = now - windowMs;
5788
+ entries = entries.filter((ts) => ts > cutoff);
5789
+ entries.push(now);
5790
+ const ttlSeconds = Math.ceil(windowMs / 1e3);
5791
+ await this.kv.put(key, JSON.stringify(entries), { expirationTtl: ttlSeconds });
5792
+ return entries.length;
5793
+ }
5794
+ async addToSet(key, value, windowMs) {
5795
+ const existing = await this.kv.get(key);
5796
+ let set = {};
5797
+ const now = Date.now();
5798
+ const cutoff = now - windowMs;
5799
+ if (existing) {
5800
+ try {
5801
+ set = JSON.parse(existing);
5802
+ } catch {
5803
+ set = {};
5804
+ }
5805
+ }
5806
+ for (const [k, ts] of Object.entries(set)) {
5807
+ if (ts < cutoff) delete set[k];
5808
+ }
5809
+ set[value] = now;
5810
+ const ttlSeconds = Math.ceil(windowMs / 1e3);
5811
+ await this.kv.put(key, JSON.stringify(set), { expirationTtl: ttlSeconds });
5812
+ }
5813
+ async getSetSize(key) {
5814
+ const existing = await this.kv.get(key);
5815
+ if (!existing) return 0;
5816
+ try {
5817
+ const set = JSON.parse(existing);
5818
+ return Object.keys(set).length;
5819
+ } catch {
5820
+ return 0;
5821
+ }
5822
+ }
5823
+ };
5824
+
5825
+ // src/plugins/core-plugins/security-audit-plugin/routes/api.ts
5826
+ var apiRoutes2 = new hono.Hono();
5827
+ apiRoutes2.use("*", chunkVHNTCB2X_cjs.requireAuth());
5828
+ apiRoutes2.use("*", async (c, next) => {
5829
+ const user = c.get("user");
5830
+ if (user?.role !== "admin") {
5831
+ return c.json({ error: "Access denied" }, 403);
5832
+ }
5833
+ return next();
5834
+ });
5835
+ async function getSettings2(db) {
5836
+ try {
5837
+ const pluginService = new chunkI6FFGQIT_cjs.PluginService(db);
5838
+ const plugin2 = await pluginService.getPlugin("security-audit");
5839
+ if (plugin2?.settings) {
5840
+ const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
5841
+ return { ...DEFAULT_SETTINGS2, ...settings };
5842
+ }
5843
+ } catch {
5844
+ }
5845
+ return DEFAULT_SETTINGS2;
5846
+ }
5847
+ apiRoutes2.get("/events", async (c) => {
5848
+ const db = c.env.DB;
5849
+ const settings = await getSettings2(db);
5850
+ const service = new SecurityAuditService(db, settings);
5851
+ const filters = {
5852
+ eventType: c.req.query("type"),
5853
+ severity: c.req.query("severity"),
5854
+ email: c.req.query("email") || void 0,
5855
+ ipAddress: c.req.query("ip") || void 0,
5856
+ search: c.req.query("search") || void 0,
5857
+ startDate: c.req.query("start") ? parseInt(c.req.query("start")) : void 0,
5858
+ endDate: c.req.query("end") ? parseInt(c.req.query("end")) : void 0,
5859
+ page: c.req.query("page") ? parseInt(c.req.query("page")) : 1,
5860
+ limit: c.req.query("limit") ? Math.min(parseInt(c.req.query("limit")), 100) : 50,
5861
+ sortBy: c.req.query("sortBy") || "created_at",
5862
+ sortOrder: c.req.query("sortOrder") || "desc"
5863
+ };
5864
+ const result = await service.getEvents(filters);
5865
+ return c.json(result);
5866
+ });
5867
+ apiRoutes2.get("/events/:id", async (c) => {
5868
+ const db = c.env.DB;
5869
+ const settings = await getSettings2(db);
5870
+ const service = new SecurityAuditService(db, settings);
5871
+ const event = await service.getEvent(c.req.param("id"));
5872
+ if (!event) {
5873
+ return c.json({ error: "Event not found" }, 404);
5874
+ }
5875
+ return c.json(event);
5876
+ });
5877
+ apiRoutes2.get("/stats", async (c) => {
5878
+ const db = c.env.DB;
5879
+ const settings = await getSettings2(db);
5880
+ const service = new SecurityAuditService(db, settings);
5881
+ const stats = await service.getStats();
5882
+ return c.json(stats);
5883
+ });
5884
+ apiRoutes2.get("/stats/ips", async (c) => {
5885
+ const db = c.env.DB;
5886
+ const settings = await getSettings2(db);
5887
+ const service = new SecurityAuditService(db, settings);
5888
+ const limit = c.req.query("limit") ? parseInt(c.req.query("limit")) : 10;
5889
+ const ips = await service.getTopIPs(limit);
5890
+ return c.json(ips);
5891
+ });
5892
+ apiRoutes2.get("/stats/trend", async (c) => {
5893
+ const db = c.env.DB;
5894
+ const settings = await getSettings2(db);
5895
+ const service = new SecurityAuditService(db, settings);
5896
+ const hours = c.req.query("hours") ? parseInt(c.req.query("hours")) : 24;
5897
+ const trend = await service.getHourlyTrend(hours);
5898
+ return c.json(trend);
5899
+ });
5900
+ apiRoutes2.get("/lockouts", async (c) => {
5901
+ const kv = c.env.CACHE_KV;
5902
+ const db = c.env.DB;
5903
+ const settings = await getSettings2(db);
5904
+ const detector = new BruteForceDetector(kv, settings.bruteForce);
5905
+ const lockouts = await detector.getActiveLockouts();
5906
+ return c.json(lockouts);
5907
+ });
5908
+ apiRoutes2.delete("/lockouts/:key", async (c) => {
5909
+ const kv = c.env.CACHE_KV;
5910
+ const key = decodeURIComponent(c.req.param("key"));
5911
+ const db = c.env.DB;
5912
+ const settings = await getSettings2(db);
5913
+ const detector = new BruteForceDetector(kv, settings.bruteForce);
5914
+ await detector.releaseLockout(key);
5915
+ return c.json({ success: true });
5916
+ });
5917
+ apiRoutes2.post("/events/purge", async (c) => {
5918
+ const db = c.env.DB;
5919
+ const settings = await getSettings2(db);
5920
+ const service = new SecurityAuditService(db, settings);
5921
+ const body = await c.req.json().catch(() => ({}));
5922
+ const deleted = await service.purgeOldEvents(body.daysToKeep);
5923
+ return c.json({ success: true, deleted });
5924
+ });
5925
+ apiRoutes2.get("/export", async (c) => {
5926
+ const db = c.env.DB;
5927
+ const settings = await getSettings2(db);
5928
+ const service = new SecurityAuditService(db, settings);
5929
+ const format = c.req.query("format") || "json";
5930
+ const filters = {
5931
+ eventType: c.req.query("type"),
5932
+ severity: c.req.query("severity"),
5933
+ startDate: c.req.query("start") ? parseInt(c.req.query("start")) : void 0,
5934
+ endDate: c.req.query("end") ? parseInt(c.req.query("end")) : void 0,
5935
+ limit: 1e4,
5936
+ page: 1
5937
+ };
5938
+ const { events } = await service.getEvents(filters);
5939
+ if (format === "csv") {
5940
+ const headers = ["id", "event_type", "severity", "email", "ip_address", "country_code", "blocked", "created_at"];
5941
+ const csvRows = [headers.join(",")];
5942
+ for (const event of events) {
5943
+ csvRows.push([
5944
+ event.id,
5945
+ event.eventType,
5946
+ event.severity,
5947
+ event.email || "",
5948
+ event.ipAddress || "",
5949
+ event.countryCode || "",
5950
+ event.blocked ? "1" : "0",
5951
+ new Date(event.createdAt).toISOString()
5952
+ ].map((v) => `"${String(v).replace(/"/g, '""')}"`).join(","));
5953
+ }
5954
+ return new Response(csvRows.join("\n"), {
5955
+ headers: {
5956
+ "Content-Type": "text/csv",
5957
+ "Content-Disposition": `attachment; filename="security-events-${Date.now()}.csv"`
5958
+ }
5959
+ });
5960
+ }
5961
+ return c.json(events);
5962
+ });
5963
+
5964
+ // src/plugins/core-plugins/security-audit-plugin/middleware/audit-middleware.ts
5965
+ function extractRequestInfo(c) {
5966
+ const ip = c.req.header("cf-connecting-ip") || c.req.header("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
5967
+ const userAgent = c.req.header("user-agent") || "unknown";
5968
+ const countryCode = c.req.header("cf-ipcountry") || null;
5969
+ const path = new URL(c.req.url).pathname;
5970
+ const method = c.req.method;
5971
+ return { ip, userAgent, countryCode, path, method };
5972
+ }
5973
+ function generateFingerprint(ip, userAgent) {
5974
+ const str = `${ip}:${userAgent}`;
5975
+ let hash = 0;
5976
+ for (let i = 0; i < str.length; i++) {
5977
+ const char = str.charCodeAt(i);
5978
+ hash = (hash << 5) - hash + char;
5979
+ hash |= 0;
5980
+ }
5981
+ return Math.abs(hash).toString(36);
5982
+ }
5983
+ async function getPluginSettings(db) {
5984
+ try {
5985
+ const pluginService = new chunkI6FFGQIT_cjs.PluginService(db);
5986
+ const plugin2 = await pluginService.getPlugin("security-audit");
5987
+ if (plugin2?.settings) {
5988
+ const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
5989
+ return { ...DEFAULT_SETTINGS2, ...settings };
5990
+ }
5991
+ } catch {
5992
+ }
5993
+ return DEFAULT_SETTINGS2;
5994
+ }
5995
+ async function isPluginActive2(db) {
5996
+ try {
5997
+ const result = await db.prepare(
5998
+ "SELECT status FROM plugins WHERE id = 'security-audit'"
5999
+ ).first();
6000
+ return result?.status === "active";
6001
+ } catch {
6002
+ return false;
6003
+ }
6004
+ }
6005
+ function securityAuditMiddleware() {
6006
+ return async (c, next) => {
6007
+ const path = new URL(c.req.url).pathname;
6008
+ if (!path.startsWith("/auth/")) {
6009
+ return next();
6010
+ }
6011
+ const db = c.env.DB;
6012
+ if (!await isPluginActive2(db)) {
6013
+ return next();
6014
+ }
6015
+ const settings = await getPluginSettings(db);
6016
+ const { ip, userAgent, countryCode, method } = extractRequestInfo(c);
6017
+ const fingerprint = generateFingerprint(ip, userAgent);
6018
+ const isLoginPost = (path === "/auth/login" || path === "/auth/login/form") && method === "POST";
6019
+ let preExtractedEmail = "";
6020
+ if (isLoginPost) {
6021
+ try {
6022
+ if (path === "/auth/login/form") {
6023
+ const clonedReq = c.req.raw.clone();
6024
+ const formData = await clonedReq.formData();
6025
+ preExtractedEmail = (formData.get("email") || "").toLowerCase();
6026
+ } else {
6027
+ const body = await c.req.json();
6028
+ preExtractedEmail = body?.email?.toLowerCase() || "";
6029
+ }
6030
+ } catch {
6031
+ }
6032
+ if (preExtractedEmail && settings.bruteForce.enabled) {
6033
+ const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce);
6034
+ const lockStatus = await detector.isLocked(ip, preExtractedEmail);
6035
+ if (lockStatus.locked) {
6036
+ const service = new SecurityAuditService(db, settings);
6037
+ const logPromise2 = service.logEvent({
6038
+ eventType: "login_failure",
6039
+ severity: "warning",
6040
+ email: preExtractedEmail,
6041
+ ipAddress: ip,
6042
+ userAgent,
6043
+ countryCode: countryCode || void 0,
6044
+ requestPath: path,
6045
+ requestMethod: method,
6046
+ fingerprint,
6047
+ blocked: true,
6048
+ details: { reason: lockStatus.reason }
6049
+ });
6050
+ if (c.executionCtx?.waitUntil) {
6051
+ c.executionCtx.waitUntil(logPromise2);
6052
+ }
6053
+ return c.json({
6054
+ error: lockStatus.reason || "Too many failed attempts. Please try again later."
6055
+ }, 429);
6056
+ }
6057
+ }
6058
+ }
6059
+ await next();
6060
+ const logPromise = logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerprint, path, method, preExtractedEmail);
6061
+ if (c.executionCtx?.waitUntil) {
6062
+ c.executionCtx.waitUntil(logPromise);
6063
+ }
6064
+ };
6065
+ }
6066
+ async function logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerprint, path, method, preExtractedEmail = "") {
6067
+ try {
6068
+ const service = new SecurityAuditService(db, settings);
6069
+ const status = c.res.status;
6070
+ const isLoginPost = (path === "/auth/login" || path === "/auth/login/form") && method === "POST";
6071
+ const isFormLogin = path === "/auth/login/form";
6072
+ if (isLoginPost) {
6073
+ let loginSucceeded;
6074
+ if (isFormLogin) {
6075
+ const hxRedirect = c.res.headers.get("HX-Redirect");
6076
+ const setCookieHeader = c.res.headers.get("set-cookie") || "";
6077
+ loginSucceeded = !!(hxRedirect?.includes("/admin") || setCookieHeader.includes("auth_token"));
6078
+ } else {
6079
+ loginSucceeded = status === 200;
6080
+ }
6081
+ if (loginSucceeded) {
6082
+ if (!settings.logging.logSuccessfulLogins) return;
6083
+ let email = preExtractedEmail;
6084
+ let userId = "";
6085
+ if (!isFormLogin) {
6086
+ try {
6087
+ const cloned = c.res.clone();
6088
+ const body = await cloned.json();
6089
+ email = body?.user?.email || email;
6090
+ userId = body?.user?.id || "";
6091
+ } catch {
6092
+ }
6093
+ }
6094
+ await service.logEvent({
6095
+ eventType: "login_success",
6096
+ severity: "info",
6097
+ userId: userId || void 0,
6098
+ email: email || void 0,
6099
+ ipAddress: ip,
6100
+ userAgent,
6101
+ countryCode: countryCode || void 0,
6102
+ requestPath: path,
6103
+ requestMethod: method,
6104
+ fingerprint
6105
+ });
6106
+ } else {
6107
+ const email = preExtractedEmail;
6108
+ await service.logEvent({
6109
+ eventType: "login_failure",
6110
+ severity: "warning",
6111
+ email: email || void 0,
6112
+ ipAddress: ip,
6113
+ userAgent,
6114
+ countryCode: countryCode || void 0,
6115
+ requestPath: path,
6116
+ requestMethod: method,
6117
+ fingerprint,
6118
+ details: { statusCode: status }
6119
+ });
6120
+ if (email && settings.bruteForce.enabled) {
6121
+ const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce);
6122
+ const result = await detector.recordFailedAttempt(ip, email);
6123
+ if (result.shouldLockIP) {
6124
+ await detector.lockIP(ip);
6125
+ await service.logEvent({
6126
+ eventType: "account_lockout",
6127
+ severity: "critical",
6128
+ email,
6129
+ ipAddress: ip,
6130
+ userAgent,
6131
+ countryCode: countryCode || void 0,
6132
+ requestPath: path,
6133
+ requestMethod: method,
6134
+ fingerprint,
6135
+ details: { reason: "brute_force_ip", attemptCount: result.ipCount }
6136
+ });
6137
+ }
6138
+ if (result.shouldLockEmail) {
6139
+ await detector.lockEmail(email);
6140
+ await service.logEvent({
6141
+ eventType: "account_lockout",
6142
+ severity: "critical",
6143
+ email,
6144
+ ipAddress: ip,
6145
+ userAgent,
6146
+ countryCode: countryCode || void 0,
6147
+ requestPath: path,
6148
+ requestMethod: method,
6149
+ fingerprint,
6150
+ details: { reason: "brute_force_email", attemptCount: result.emailCount }
6151
+ });
6152
+ }
6153
+ if (result.isSuspicious) {
6154
+ await service.logEvent({
6155
+ eventType: "suspicious_activity",
6156
+ severity: "critical",
6157
+ ipAddress: ip,
6158
+ userAgent,
6159
+ countryCode: countryCode || void 0,
6160
+ requestPath: path,
6161
+ requestMethod: method,
6162
+ fingerprint,
6163
+ details: { reason: "multiple_emails_from_ip", ipCount: result.ipCount }
6164
+ });
6165
+ }
6166
+ }
6167
+ }
6168
+ }
6169
+ if (path === "/auth/register" && method === "POST" && settings.logging.logRegistrations) {
6170
+ if (status === 201 || status === 200) {
6171
+ let email = "";
6172
+ let userId = "";
6173
+ try {
6174
+ const cloned = c.res.clone();
6175
+ const body = await cloned.json();
6176
+ email = body?.user?.email || "";
6177
+ userId = body?.user?.id || "";
6178
+ } catch {
6179
+ }
6180
+ await service.logEvent({
6181
+ eventType: "registration",
6182
+ severity: "info",
6183
+ userId: userId || void 0,
6184
+ email: email || void 0,
6185
+ ipAddress: ip,
6186
+ userAgent,
6187
+ countryCode: countryCode || void 0,
6188
+ requestPath: path,
6189
+ requestMethod: method,
6190
+ fingerprint
6191
+ });
6192
+ }
6193
+ }
6194
+ if (path === "/auth/logout" && settings.logging.logLogouts) {
6195
+ const user = c.get("user");
6196
+ await service.logEvent({
6197
+ eventType: "logout",
6198
+ severity: "info",
6199
+ userId: user?.userId,
6200
+ email: user?.email,
6201
+ ipAddress: ip,
6202
+ userAgent,
6203
+ countryCode: countryCode || void 0,
6204
+ requestPath: path,
6205
+ requestMethod: method,
6206
+ fingerprint
6207
+ });
6208
+ }
6209
+ } catch (error) {
6210
+ console.error("[SecurityAudit] Error logging auth event:", error);
6211
+ }
6212
+ }
6213
+
6214
+ // src/plugins/core-plugins/security-audit-plugin/index.ts
6215
+ function createSecurityAuditPlugin() {
6216
+ const builder = chunk6FHNRRJ3_cjs.PluginBuilder.create({
6217
+ name: "security-audit",
6218
+ version: "1.0.0-beta.1",
6219
+ description: "Security event logging, brute-force detection, and analytics dashboard"
6220
+ });
6221
+ builder.metadata({
6222
+ author: { name: "SonicJS Team" },
6223
+ license: "MIT"
6224
+ });
6225
+ builder.addRoute("/admin/plugins/security-audit", adminRoutes2, {
6226
+ description: "Security audit dashboard and admin pages",
6227
+ requiresAuth: true,
6228
+ priority: 50
6229
+ });
6230
+ builder.addRoute("/api/security-audit", apiRoutes2, {
6231
+ description: "Security audit API endpoints",
6232
+ requiresAuth: true,
6233
+ priority: 50
6234
+ });
6235
+ builder.addMenuItem("Security", "/admin/plugins/security-audit", {
6236
+ icon: `<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg>`,
6237
+ order: 85
6238
+ });
6239
+ builder.lifecycle({
6240
+ install: async (context) => {
6241
+ console.log("[SecurityAudit] Plugin installed");
6242
+ },
6243
+ activate: async (context) => {
6244
+ console.log("[SecurityAudit] Plugin activated");
6245
+ },
6246
+ deactivate: async (context) => {
6247
+ console.log("[SecurityAudit] Plugin deactivated");
6248
+ },
6249
+ uninstall: async (context) => {
6250
+ console.log("[SecurityAudit] Plugin uninstalled");
6251
+ }
6252
+ });
6253
+ return builder.build();
6254
+ }
6255
+ var securityAuditPlugin = createSecurityAuditPlugin();
6256
+
6257
+ // src/middleware/plugin-menu.ts
6258
+ var MENU_PLUGINS = [
6259
+ securityAuditPlugin
6260
+ ];
6261
+ var MARKER = "<!-- DYNAMIC_PLUGIN_MENU -->";
6262
+ function renderMenuItem(item, currentPath) {
6263
+ const isActive = currentPath === item.path || currentPath.startsWith(item.path);
6264
+ const fallbackIcon = `<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>`;
6265
+ return `
6266
+ <span class="relative">
6267
+ ${isActive ? '<span class="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400"></span>' : ""}
6268
+ <a
6269
+ href="${item.path}"
6270
+ class="flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-sm/5 font-medium ${isActive ? "text-zinc-950 dark:text-white" : "text-zinc-950 hover:bg-zinc-950/5 dark:text-white dark:hover:bg-white/5"}"
6271
+ ${isActive ? 'data-current="true"' : ""}
6272
+ >
6273
+ <span class="shrink-0 ${isActive ? "fill-zinc-950 dark:fill-white" : "fill-zinc-500 dark:fill-zinc-400"}">
6274
+ ${item.icon || fallbackIcon}
6275
+ </span>
6276
+ <span class="truncate">${item.label}</span>
6277
+ </a>
6278
+ </span>`;
6279
+ }
6280
+ function pluginMenuMiddleware() {
6281
+ return async (c, next) => {
6282
+ const path = new URL(c.req.url).pathname;
6283
+ if (!path.startsWith("/admin")) {
6284
+ return next();
6285
+ }
6286
+ let activeMenuItems = [];
6287
+ try {
6288
+ const db = c.env.DB;
6289
+ const pluginNames = MENU_PLUGINS.map((p) => p.name);
6290
+ if (pluginNames.length > 0) {
6291
+ const placeholders = pluginNames.map(() => "?").join(",");
6292
+ const result = await db.prepare(
6293
+ `SELECT name FROM plugins WHERE name IN (${placeholders}) AND status = 'active'`
6294
+ ).bind(...pluginNames).all();
6295
+ const activeNames = new Set((result.results || []).map((r) => r.name));
6296
+ for (const plugin2 of MENU_PLUGINS) {
6297
+ if (activeNames.has(plugin2.name) && plugin2.menuItems) {
6298
+ activeMenuItems.push(...plugin2.menuItems);
6299
+ }
6300
+ }
6301
+ activeMenuItems.sort((a, b) => (a.order || 0) - (b.order || 0));
6302
+ }
6303
+ } catch {
6304
+ }
6305
+ c.set("pluginMenuItems", activeMenuItems.map((m) => ({ label: m.label, path: m.path, icon: m.icon || "" })));
6306
+ await next();
6307
+ if (activeMenuItems.length > 0 && c.res.headers.get("content-type")?.includes("text/html")) {
6308
+ const status = c.res.status;
6309
+ const headers = new Headers(c.res.headers);
6310
+ const html = await c.res.text();
6311
+ if (html.includes(MARKER)) {
6312
+ const renderedItems = activeMenuItems.map((item) => renderMenuItem(item, path)).join("");
6313
+ const newHtml = html.split(MARKER).join(renderedItems);
6314
+ c.res = new Response(newHtml, { status, headers });
6315
+ } else {
6316
+ c.res = new Response(html, { status, headers });
6317
+ }
6318
+ }
6319
+ };
6320
+ }
6321
+
4692
6322
  // src/plugins/cache/services/cache-config.ts
4693
6323
  var CACHE_CONFIGS = {
4694
6324
  // Content (high read, low write)
@@ -5651,7 +7281,7 @@ async function warmNamespace(namespace, entries) {
5651
7281
  }
5652
7282
 
5653
7283
  // src/templates/pages/admin-cache.template.ts
5654
- chunkLTKV7AE5_cjs.init_admin_layout_catalyst_template();
7284
+ chunkH4NHRZ6Y_cjs.init_admin_layout_catalyst_template();
5655
7285
  function renderCacheDashboard(data) {
5656
7286
  const pageContent = `
5657
7287
  <div class="space-y-6">
@@ -5830,7 +7460,7 @@ function renderCacheDashboard(data) {
5830
7460
  </script>
5831
7461
 
5832
7462
  <!-- Confirmation Dialogs -->
5833
- ${chunkASAEJ4B7_cjs.renderConfirmationDialog({
7463
+ ${chunkZV6ZCJ74_cjs.renderConfirmationDialog({
5834
7464
  id: "clear-all-cache-confirm",
5835
7465
  title: "Clear All Cache",
5836
7466
  message: "Are you sure you want to clear all cache entries? This cannot be undone.",
@@ -5841,7 +7471,7 @@ function renderCacheDashboard(data) {
5841
7471
  onConfirm: "performClearAllCaches()"
5842
7472
  })}
5843
7473
 
5844
- ${chunkASAEJ4B7_cjs.renderConfirmationDialog({
7474
+ ${chunkZV6ZCJ74_cjs.renderConfirmationDialog({
5845
7475
  id: "clear-namespace-cache-confirm",
5846
7476
  title: "Clear Namespace Cache",
5847
7477
  message: "Clear cache for this namespace?",
@@ -5852,7 +7482,7 @@ function renderCacheDashboard(data) {
5852
7482
  onConfirm: "performClearNamespaceCache()"
5853
7483
  })}
5854
7484
 
5855
- ${chunkASAEJ4B7_cjs.getConfirmationDialogScript()}
7485
+ ${chunkZV6ZCJ74_cjs.getConfirmationDialogScript()}
5856
7486
  `;
5857
7487
  const layoutData = {
5858
7488
  title: "Cache System",
@@ -5862,7 +7492,7 @@ function renderCacheDashboard(data) {
5862
7492
  version: data.version,
5863
7493
  content: pageContent
5864
7494
  };
5865
- return chunkLTKV7AE5_cjs.renderAdminLayoutCatalyst(layoutData);
7495
+ return chunkH4NHRZ6Y_cjs.renderAdminLayoutCatalyst(layoutData);
5866
7496
  }
5867
7497
  function renderStatCard(label, value, color, icon, colorOverride) {
5868
7498
  const finalColor = colorOverride || color;
@@ -6538,14 +8168,14 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
6538
8168
  // src/app.ts
6539
8169
  function createSonicJSApp(config = {}) {
6540
8170
  const app2 = new hono.Hono();
6541
- const appVersion = config.version || chunkQLPFENZ2_cjs.getCoreVersion();
8171
+ const appVersion = config.version || chunkRXNLGINR_cjs.getCoreVersion();
6542
8172
  const appName = config.name || "SonicJS AI";
6543
8173
  app2.use("*", async (c, next) => {
6544
8174
  c.set("appVersion", appVersion);
6545
8175
  await next();
6546
8176
  });
6547
- app2.use("*", chunkB2ASV5RD_cjs.metricsMiddleware());
6548
- app2.use("*", chunkB2ASV5RD_cjs.bootstrapMiddleware(config));
8177
+ app2.use("*", chunkVHNTCB2X_cjs.metricsMiddleware());
8178
+ app2.use("*", chunkVHNTCB2X_cjs.bootstrapMiddleware(config));
6549
8179
  if (config.middleware?.beforeAuth) {
6550
8180
  for (const middleware of config.middleware.beforeAuth) {
6551
8181
  app2.use("*", middleware);
@@ -6554,28 +8184,35 @@ function createSonicJSApp(config = {}) {
6554
8184
  app2.use("*", async (_c, next) => {
6555
8185
  await next();
6556
8186
  });
6557
- app2.use("*", chunkB2ASV5RD_cjs.securityHeadersMiddleware());
6558
- app2.use("*", chunkB2ASV5RD_cjs.csrfProtection());
8187
+ app2.use("*", chunkVHNTCB2X_cjs.securityHeadersMiddleware());
8188
+ app2.use("*", chunkVHNTCB2X_cjs.csrfProtection());
6559
8189
  if (config.middleware?.afterAuth) {
6560
8190
  for (const middleware of config.middleware.afterAuth) {
6561
8191
  app2.use("*", middleware);
6562
8192
  }
6563
8193
  }
6564
- app2.route("/api", chunkASAEJ4B7_cjs.api_default);
6565
- app2.route("/api/media", chunkASAEJ4B7_cjs.api_media_default);
6566
- app2.route("/api/system", chunkASAEJ4B7_cjs.api_system_default);
6567
- app2.route("/admin/api", chunkASAEJ4B7_cjs.admin_api_default);
6568
- app2.route("/admin/dashboard", chunkASAEJ4B7_cjs.router);
6569
- app2.route("/admin/collections", chunkASAEJ4B7_cjs.adminCollectionsRoutes);
6570
- app2.route("/admin/forms", chunkASAEJ4B7_cjs.adminFormsRoutes);
6571
- app2.route("/admin/settings", chunkASAEJ4B7_cjs.adminSettingsRoutes);
6572
- app2.route("/forms", chunkASAEJ4B7_cjs.public_forms_default);
6573
- app2.route("/api/forms", chunkASAEJ4B7_cjs.public_forms_default);
6574
- app2.route("/admin/api-reference", chunkASAEJ4B7_cjs.router2);
8194
+ app2.use("/admin/*", pluginMenuMiddleware());
8195
+ app2.route("/api", chunkZV6ZCJ74_cjs.api_default);
8196
+ app2.route("/api/media", chunkZV6ZCJ74_cjs.api_media_default);
8197
+ app2.route("/api/system", chunkZV6ZCJ74_cjs.api_system_default);
8198
+ app2.route("/admin/api", chunkZV6ZCJ74_cjs.admin_api_default);
8199
+ app2.route("/admin/dashboard", chunkZV6ZCJ74_cjs.router);
8200
+ app2.route("/admin/collections", chunkZV6ZCJ74_cjs.adminCollectionsRoutes);
8201
+ app2.route("/admin/forms", chunkZV6ZCJ74_cjs.adminFormsRoutes);
8202
+ app2.route("/admin/settings", chunkZV6ZCJ74_cjs.adminSettingsRoutes);
8203
+ app2.route("/forms", chunkZV6ZCJ74_cjs.public_forms_default);
8204
+ app2.route("/api/forms", chunkZV6ZCJ74_cjs.public_forms_default);
8205
+ app2.route("/admin/api-reference", chunkZV6ZCJ74_cjs.router2);
6575
8206
  app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
6576
8207
  app2.route("/admin/seed-data", createSeedDataAdminRoutes());
6577
- app2.route("/admin/content", chunkASAEJ4B7_cjs.admin_content_default);
6578
- app2.route("/admin/media", chunkASAEJ4B7_cjs.adminMediaRoutes);
8208
+ app2.route("/admin/content", chunkZV6ZCJ74_cjs.admin_content_default);
8209
+ app2.route("/admin/media", chunkZV6ZCJ74_cjs.adminMediaRoutes);
8210
+ app2.use("/auth/*", securityAuditMiddleware());
8211
+ if (securityAuditPlugin.routes && securityAuditPlugin.routes.length > 0) {
8212
+ for (const route of securityAuditPlugin.routes) {
8213
+ app2.route(route.path, route.handler);
8214
+ }
8215
+ }
6579
8216
  if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {
6580
8217
  for (const route of aiSearchPlugin.routes) {
6581
8218
  app2.route(route.path, route.handler);
@@ -6587,16 +8224,21 @@ function createSonicJSApp(config = {}) {
6587
8224
  app2.route(route.path, route.handler);
6588
8225
  }
6589
8226
  }
8227
+ if (chunkZV6ZCJ74_cjs.userProfilesPlugin.routes && chunkZV6ZCJ74_cjs.userProfilesPlugin.routes.length > 0) {
8228
+ for (const route of chunkZV6ZCJ74_cjs.userProfilesPlugin.routes) {
8229
+ app2.route(route.path, route.handler);
8230
+ }
8231
+ }
6590
8232
  if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {
6591
8233
  for (const route of otpLoginPlugin.routes) {
6592
8234
  app2.route(route.path, route.handler);
6593
8235
  }
6594
8236
  }
6595
- app2.route("/admin/plugins", chunkASAEJ4B7_cjs.adminPluginRoutes);
6596
- app2.route("/admin/logs", chunkASAEJ4B7_cjs.adminLogsRoutes);
6597
- app2.route("/admin", chunkASAEJ4B7_cjs.userRoutes);
6598
- app2.route("/auth", chunkASAEJ4B7_cjs.auth_default);
6599
- app2.route("/", chunkASAEJ4B7_cjs.test_cleanup_default);
8237
+ app2.route("/admin/plugins", chunkZV6ZCJ74_cjs.adminPluginRoutes);
8238
+ app2.route("/admin/logs", chunkZV6ZCJ74_cjs.adminLogsRoutes);
8239
+ app2.route("/admin", chunkZV6ZCJ74_cjs.userRoutes);
8240
+ app2.route("/auth", chunkZV6ZCJ74_cjs.auth_default);
8241
+ app2.route("/", chunkZV6ZCJ74_cjs.test_cleanup_default);
6600
8242
  if (emailPlugin.routes && emailPlugin.routes.length > 0) {
6601
8243
  for (const route of emailPlugin.routes) {
6602
8244
  app2.route(route.path, route.handler);
@@ -6659,7 +8301,7 @@ function createSonicJSApp(config = {}) {
6659
8301
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6660
8302
  });
6661
8303
  });
6662
- chunkLFAQUR7P_cjs.setAppInstance(app2);
8304
+ chunkNZWFCUDA_cjs.setAppInstance(app2);
6663
8305
  app2.notFound((c) => {
6664
8306
  return c.json({ error: "Not Found", status: 404 }, 404);
6665
8307
  });
@@ -6676,447 +8318,463 @@ function setupCoreRoutes(_app) {
6676
8318
  console.warn("setupCoreRoutes is deprecated. Use createSonicJSApp() instead.");
6677
8319
  }
6678
8320
  function createDb(d1$1) {
6679
- return d1.drizzle(d1$1, { schema: chunkLFAQUR7P_cjs.schema_exports });
8321
+ return d1.drizzle(d1$1, { schema: chunkNZWFCUDA_cjs.schema_exports });
6680
8322
  }
6681
8323
 
6682
8324
  // src/index.ts
6683
- var VERSION = chunkQLPFENZ2_cjs.package_default.version;
8325
+ var VERSION = chunkRXNLGINR_cjs.package_default.version;
6684
8326
 
6685
8327
  Object.defineProperty(exports, "ROUTES_INFO", {
6686
8328
  enumerable: true,
6687
- get: function () { return chunkASAEJ4B7_cjs.ROUTES_INFO; }
8329
+ get: function () { return chunkZV6ZCJ74_cjs.ROUTES_INFO; }
6688
8330
  });
6689
8331
  Object.defineProperty(exports, "adminApiRoutes", {
6690
8332
  enumerable: true,
6691
- get: function () { return chunkASAEJ4B7_cjs.admin_api_default; }
8333
+ get: function () { return chunkZV6ZCJ74_cjs.admin_api_default; }
6692
8334
  });
6693
8335
  Object.defineProperty(exports, "adminCheckboxRoutes", {
6694
8336
  enumerable: true,
6695
- get: function () { return chunkASAEJ4B7_cjs.adminCheckboxRoutes; }
8337
+ get: function () { return chunkZV6ZCJ74_cjs.adminCheckboxRoutes; }
6696
8338
  });
6697
8339
  Object.defineProperty(exports, "adminCodeExamplesRoutes", {
6698
8340
  enumerable: true,
6699
- get: function () { return chunkASAEJ4B7_cjs.admin_code_examples_default; }
8341
+ get: function () { return chunkZV6ZCJ74_cjs.admin_code_examples_default; }
6700
8342
  });
6701
8343
  Object.defineProperty(exports, "adminCollectionsRoutes", {
6702
8344
  enumerable: true,
6703
- get: function () { return chunkASAEJ4B7_cjs.adminCollectionsRoutes; }
8345
+ get: function () { return chunkZV6ZCJ74_cjs.adminCollectionsRoutes; }
6704
8346
  });
6705
8347
  Object.defineProperty(exports, "adminContentRoutes", {
6706
8348
  enumerable: true,
6707
- get: function () { return chunkASAEJ4B7_cjs.admin_content_default; }
8349
+ get: function () { return chunkZV6ZCJ74_cjs.admin_content_default; }
6708
8350
  });
6709
8351
  Object.defineProperty(exports, "adminDashboardRoutes", {
6710
8352
  enumerable: true,
6711
- get: function () { return chunkASAEJ4B7_cjs.router; }
8353
+ get: function () { return chunkZV6ZCJ74_cjs.router; }
6712
8354
  });
6713
8355
  Object.defineProperty(exports, "adminDesignRoutes", {
6714
8356
  enumerable: true,
6715
- get: function () { return chunkASAEJ4B7_cjs.adminDesignRoutes; }
8357
+ get: function () { return chunkZV6ZCJ74_cjs.adminDesignRoutes; }
6716
8358
  });
6717
8359
  Object.defineProperty(exports, "adminLogsRoutes", {
6718
8360
  enumerable: true,
6719
- get: function () { return chunkASAEJ4B7_cjs.adminLogsRoutes; }
8361
+ get: function () { return chunkZV6ZCJ74_cjs.adminLogsRoutes; }
6720
8362
  });
6721
8363
  Object.defineProperty(exports, "adminMediaRoutes", {
6722
8364
  enumerable: true,
6723
- get: function () { return chunkASAEJ4B7_cjs.adminMediaRoutes; }
8365
+ get: function () { return chunkZV6ZCJ74_cjs.adminMediaRoutes; }
6724
8366
  });
6725
8367
  Object.defineProperty(exports, "adminPluginRoutes", {
6726
8368
  enumerable: true,
6727
- get: function () { return chunkASAEJ4B7_cjs.adminPluginRoutes; }
8369
+ get: function () { return chunkZV6ZCJ74_cjs.adminPluginRoutes; }
6728
8370
  });
6729
8371
  Object.defineProperty(exports, "adminSettingsRoutes", {
6730
8372
  enumerable: true,
6731
- get: function () { return chunkASAEJ4B7_cjs.adminSettingsRoutes; }
8373
+ get: function () { return chunkZV6ZCJ74_cjs.adminSettingsRoutes; }
6732
8374
  });
6733
8375
  Object.defineProperty(exports, "adminTestimonialsRoutes", {
6734
8376
  enumerable: true,
6735
- get: function () { return chunkASAEJ4B7_cjs.admin_testimonials_default; }
8377
+ get: function () { return chunkZV6ZCJ74_cjs.admin_testimonials_default; }
6736
8378
  });
6737
8379
  Object.defineProperty(exports, "adminUsersRoutes", {
6738
8380
  enumerable: true,
6739
- get: function () { return chunkASAEJ4B7_cjs.userRoutes; }
8381
+ get: function () { return chunkZV6ZCJ74_cjs.userRoutes; }
6740
8382
  });
6741
8383
  Object.defineProperty(exports, "apiContentCrudRoutes", {
6742
8384
  enumerable: true,
6743
- get: function () { return chunkASAEJ4B7_cjs.api_content_crud_default; }
8385
+ get: function () { return chunkZV6ZCJ74_cjs.api_content_crud_default; }
6744
8386
  });
6745
8387
  Object.defineProperty(exports, "apiMediaRoutes", {
6746
8388
  enumerable: true,
6747
- get: function () { return chunkASAEJ4B7_cjs.api_media_default; }
8389
+ get: function () { return chunkZV6ZCJ74_cjs.api_media_default; }
6748
8390
  });
6749
8391
  Object.defineProperty(exports, "apiRoutes", {
6750
8392
  enumerable: true,
6751
- get: function () { return chunkASAEJ4B7_cjs.api_default; }
8393
+ get: function () { return chunkZV6ZCJ74_cjs.api_default; }
6752
8394
  });
6753
8395
  Object.defineProperty(exports, "apiSystemRoutes", {
6754
8396
  enumerable: true,
6755
- get: function () { return chunkASAEJ4B7_cjs.api_system_default; }
8397
+ get: function () { return chunkZV6ZCJ74_cjs.api_system_default; }
6756
8398
  });
6757
8399
  Object.defineProperty(exports, "authRoutes", {
6758
8400
  enumerable: true,
6759
- get: function () { return chunkASAEJ4B7_cjs.auth_default; }
8401
+ get: function () { return chunkZV6ZCJ74_cjs.auth_default; }
8402
+ });
8403
+ Object.defineProperty(exports, "createUserProfilesPlugin", {
8404
+ enumerable: true,
8405
+ get: function () { return chunkZV6ZCJ74_cjs.createUserProfilesPlugin; }
8406
+ });
8407
+ Object.defineProperty(exports, "defineUserProfile", {
8408
+ enumerable: true,
8409
+ get: function () { return chunkZV6ZCJ74_cjs.defineUserProfile; }
8410
+ });
8411
+ Object.defineProperty(exports, "getUserProfileConfig", {
8412
+ enumerable: true,
8413
+ get: function () { return chunkZV6ZCJ74_cjs.getUserProfileConfig; }
8414
+ });
8415
+ Object.defineProperty(exports, "userProfilesPlugin", {
8416
+ enumerable: true,
8417
+ get: function () { return chunkZV6ZCJ74_cjs.userProfilesPlugin; }
6760
8418
  });
6761
8419
  Object.defineProperty(exports, "Logger", {
6762
8420
  enumerable: true,
6763
- get: function () { return chunkLFAQUR7P_cjs.Logger; }
8421
+ get: function () { return chunkNZWFCUDA_cjs.Logger; }
6764
8422
  });
6765
8423
  Object.defineProperty(exports, "apiTokens", {
6766
8424
  enumerable: true,
6767
- get: function () { return chunkLFAQUR7P_cjs.apiTokens; }
8425
+ get: function () { return chunkNZWFCUDA_cjs.apiTokens; }
6768
8426
  });
6769
8427
  Object.defineProperty(exports, "collections", {
6770
8428
  enumerable: true,
6771
- get: function () { return chunkLFAQUR7P_cjs.collections; }
8429
+ get: function () { return chunkNZWFCUDA_cjs.collections; }
6772
8430
  });
6773
8431
  Object.defineProperty(exports, "content", {
6774
8432
  enumerable: true,
6775
- get: function () { return chunkLFAQUR7P_cjs.content; }
8433
+ get: function () { return chunkNZWFCUDA_cjs.content; }
6776
8434
  });
6777
8435
  Object.defineProperty(exports, "contentVersions", {
6778
8436
  enumerable: true,
6779
- get: function () { return chunkLFAQUR7P_cjs.contentVersions; }
8437
+ get: function () { return chunkNZWFCUDA_cjs.contentVersions; }
6780
8438
  });
6781
8439
  Object.defineProperty(exports, "getLogger", {
6782
8440
  enumerable: true,
6783
- get: function () { return chunkLFAQUR7P_cjs.getLogger; }
8441
+ get: function () { return chunkNZWFCUDA_cjs.getLogger; }
6784
8442
  });
6785
8443
  Object.defineProperty(exports, "initLogger", {
6786
8444
  enumerable: true,
6787
- get: function () { return chunkLFAQUR7P_cjs.initLogger; }
8445
+ get: function () { return chunkNZWFCUDA_cjs.initLogger; }
6788
8446
  });
6789
8447
  Object.defineProperty(exports, "insertCollectionSchema", {
6790
8448
  enumerable: true,
6791
- get: function () { return chunkLFAQUR7P_cjs.insertCollectionSchema; }
8449
+ get: function () { return chunkNZWFCUDA_cjs.insertCollectionSchema; }
6792
8450
  });
6793
8451
  Object.defineProperty(exports, "insertContentSchema", {
6794
8452
  enumerable: true,
6795
- get: function () { return chunkLFAQUR7P_cjs.insertContentSchema; }
8453
+ get: function () { return chunkNZWFCUDA_cjs.insertContentSchema; }
6796
8454
  });
6797
8455
  Object.defineProperty(exports, "insertLogConfigSchema", {
6798
8456
  enumerable: true,
6799
- get: function () { return chunkLFAQUR7P_cjs.insertLogConfigSchema; }
8457
+ get: function () { return chunkNZWFCUDA_cjs.insertLogConfigSchema; }
6800
8458
  });
6801
8459
  Object.defineProperty(exports, "insertMediaSchema", {
6802
8460
  enumerable: true,
6803
- get: function () { return chunkLFAQUR7P_cjs.insertMediaSchema; }
8461
+ get: function () { return chunkNZWFCUDA_cjs.insertMediaSchema; }
6804
8462
  });
6805
8463
  Object.defineProperty(exports, "insertPluginActivityLogSchema", {
6806
8464
  enumerable: true,
6807
- get: function () { return chunkLFAQUR7P_cjs.insertPluginActivityLogSchema; }
8465
+ get: function () { return chunkNZWFCUDA_cjs.insertPluginActivityLogSchema; }
6808
8466
  });
6809
8467
  Object.defineProperty(exports, "insertPluginAssetSchema", {
6810
8468
  enumerable: true,
6811
- get: function () { return chunkLFAQUR7P_cjs.insertPluginAssetSchema; }
8469
+ get: function () { return chunkNZWFCUDA_cjs.insertPluginAssetSchema; }
6812
8470
  });
6813
8471
  Object.defineProperty(exports, "insertPluginHookSchema", {
6814
8472
  enumerable: true,
6815
- get: function () { return chunkLFAQUR7P_cjs.insertPluginHookSchema; }
8473
+ get: function () { return chunkNZWFCUDA_cjs.insertPluginHookSchema; }
6816
8474
  });
6817
8475
  Object.defineProperty(exports, "insertPluginRouteSchema", {
6818
8476
  enumerable: true,
6819
- get: function () { return chunkLFAQUR7P_cjs.insertPluginRouteSchema; }
8477
+ get: function () { return chunkNZWFCUDA_cjs.insertPluginRouteSchema; }
6820
8478
  });
6821
8479
  Object.defineProperty(exports, "insertPluginSchema", {
6822
8480
  enumerable: true,
6823
- get: function () { return chunkLFAQUR7P_cjs.insertPluginSchema; }
8481
+ get: function () { return chunkNZWFCUDA_cjs.insertPluginSchema; }
6824
8482
  });
6825
8483
  Object.defineProperty(exports, "insertSystemLogSchema", {
6826
8484
  enumerable: true,
6827
- get: function () { return chunkLFAQUR7P_cjs.insertSystemLogSchema; }
8485
+ get: function () { return chunkNZWFCUDA_cjs.insertSystemLogSchema; }
6828
8486
  });
6829
8487
  Object.defineProperty(exports, "insertUserSchema", {
6830
8488
  enumerable: true,
6831
- get: function () { return chunkLFAQUR7P_cjs.insertUserSchema; }
8489
+ get: function () { return chunkNZWFCUDA_cjs.insertUserSchema; }
6832
8490
  });
6833
8491
  Object.defineProperty(exports, "insertWorkflowHistorySchema", {
6834
8492
  enumerable: true,
6835
- get: function () { return chunkLFAQUR7P_cjs.insertWorkflowHistorySchema; }
8493
+ get: function () { return chunkNZWFCUDA_cjs.insertWorkflowHistorySchema; }
6836
8494
  });
6837
8495
  Object.defineProperty(exports, "logConfig", {
6838
8496
  enumerable: true,
6839
- get: function () { return chunkLFAQUR7P_cjs.logConfig; }
8497
+ get: function () { return chunkNZWFCUDA_cjs.logConfig; }
6840
8498
  });
6841
8499
  Object.defineProperty(exports, "media", {
6842
8500
  enumerable: true,
6843
- get: function () { return chunkLFAQUR7P_cjs.media; }
8501
+ get: function () { return chunkNZWFCUDA_cjs.media; }
6844
8502
  });
6845
8503
  Object.defineProperty(exports, "pluginActivityLog", {
6846
8504
  enumerable: true,
6847
- get: function () { return chunkLFAQUR7P_cjs.pluginActivityLog; }
8505
+ get: function () { return chunkNZWFCUDA_cjs.pluginActivityLog; }
6848
8506
  });
6849
8507
  Object.defineProperty(exports, "pluginAssets", {
6850
8508
  enumerable: true,
6851
- get: function () { return chunkLFAQUR7P_cjs.pluginAssets; }
8509
+ get: function () { return chunkNZWFCUDA_cjs.pluginAssets; }
6852
8510
  });
6853
8511
  Object.defineProperty(exports, "pluginHooks", {
6854
8512
  enumerable: true,
6855
- get: function () { return chunkLFAQUR7P_cjs.pluginHooks; }
8513
+ get: function () { return chunkNZWFCUDA_cjs.pluginHooks; }
6856
8514
  });
6857
8515
  Object.defineProperty(exports, "pluginRoutes", {
6858
8516
  enumerable: true,
6859
- get: function () { return chunkLFAQUR7P_cjs.pluginRoutes; }
8517
+ get: function () { return chunkNZWFCUDA_cjs.pluginRoutes; }
6860
8518
  });
6861
8519
  Object.defineProperty(exports, "plugins", {
6862
8520
  enumerable: true,
6863
- get: function () { return chunkLFAQUR7P_cjs.plugins; }
8521
+ get: function () { return chunkNZWFCUDA_cjs.plugins; }
6864
8522
  });
6865
8523
  Object.defineProperty(exports, "selectCollectionSchema", {
6866
8524
  enumerable: true,
6867
- get: function () { return chunkLFAQUR7P_cjs.selectCollectionSchema; }
8525
+ get: function () { return chunkNZWFCUDA_cjs.selectCollectionSchema; }
6868
8526
  });
6869
8527
  Object.defineProperty(exports, "selectContentSchema", {
6870
8528
  enumerable: true,
6871
- get: function () { return chunkLFAQUR7P_cjs.selectContentSchema; }
8529
+ get: function () { return chunkNZWFCUDA_cjs.selectContentSchema; }
6872
8530
  });
6873
8531
  Object.defineProperty(exports, "selectLogConfigSchema", {
6874
8532
  enumerable: true,
6875
- get: function () { return chunkLFAQUR7P_cjs.selectLogConfigSchema; }
8533
+ get: function () { return chunkNZWFCUDA_cjs.selectLogConfigSchema; }
6876
8534
  });
6877
8535
  Object.defineProperty(exports, "selectMediaSchema", {
6878
8536
  enumerable: true,
6879
- get: function () { return chunkLFAQUR7P_cjs.selectMediaSchema; }
8537
+ get: function () { return chunkNZWFCUDA_cjs.selectMediaSchema; }
6880
8538
  });
6881
8539
  Object.defineProperty(exports, "selectPluginActivityLogSchema", {
6882
8540
  enumerable: true,
6883
- get: function () { return chunkLFAQUR7P_cjs.selectPluginActivityLogSchema; }
8541
+ get: function () { return chunkNZWFCUDA_cjs.selectPluginActivityLogSchema; }
6884
8542
  });
6885
8543
  Object.defineProperty(exports, "selectPluginAssetSchema", {
6886
8544
  enumerable: true,
6887
- get: function () { return chunkLFAQUR7P_cjs.selectPluginAssetSchema; }
8545
+ get: function () { return chunkNZWFCUDA_cjs.selectPluginAssetSchema; }
6888
8546
  });
6889
8547
  Object.defineProperty(exports, "selectPluginHookSchema", {
6890
8548
  enumerable: true,
6891
- get: function () { return chunkLFAQUR7P_cjs.selectPluginHookSchema; }
8549
+ get: function () { return chunkNZWFCUDA_cjs.selectPluginHookSchema; }
6892
8550
  });
6893
8551
  Object.defineProperty(exports, "selectPluginRouteSchema", {
6894
8552
  enumerable: true,
6895
- get: function () { return chunkLFAQUR7P_cjs.selectPluginRouteSchema; }
8553
+ get: function () { return chunkNZWFCUDA_cjs.selectPluginRouteSchema; }
6896
8554
  });
6897
8555
  Object.defineProperty(exports, "selectPluginSchema", {
6898
8556
  enumerable: true,
6899
- get: function () { return chunkLFAQUR7P_cjs.selectPluginSchema; }
8557
+ get: function () { return chunkNZWFCUDA_cjs.selectPluginSchema; }
6900
8558
  });
6901
8559
  Object.defineProperty(exports, "selectSystemLogSchema", {
6902
8560
  enumerable: true,
6903
- get: function () { return chunkLFAQUR7P_cjs.selectSystemLogSchema; }
8561
+ get: function () { return chunkNZWFCUDA_cjs.selectSystemLogSchema; }
6904
8562
  });
6905
8563
  Object.defineProperty(exports, "selectUserSchema", {
6906
8564
  enumerable: true,
6907
- get: function () { return chunkLFAQUR7P_cjs.selectUserSchema; }
8565
+ get: function () { return chunkNZWFCUDA_cjs.selectUserSchema; }
6908
8566
  });
6909
8567
  Object.defineProperty(exports, "selectWorkflowHistorySchema", {
6910
8568
  enumerable: true,
6911
- get: function () { return chunkLFAQUR7P_cjs.selectWorkflowHistorySchema; }
8569
+ get: function () { return chunkNZWFCUDA_cjs.selectWorkflowHistorySchema; }
6912
8570
  });
6913
8571
  Object.defineProperty(exports, "systemLogs", {
6914
8572
  enumerable: true,
6915
- get: function () { return chunkLFAQUR7P_cjs.systemLogs; }
8573
+ get: function () { return chunkNZWFCUDA_cjs.systemLogs; }
6916
8574
  });
6917
8575
  Object.defineProperty(exports, "users", {
6918
8576
  enumerable: true,
6919
- get: function () { return chunkLFAQUR7P_cjs.users; }
8577
+ get: function () { return chunkNZWFCUDA_cjs.users; }
6920
8578
  });
6921
8579
  Object.defineProperty(exports, "workflowHistory", {
6922
8580
  enumerable: true,
6923
- get: function () { return chunkLFAQUR7P_cjs.workflowHistory; }
8581
+ get: function () { return chunkNZWFCUDA_cjs.workflowHistory; }
6924
8582
  });
6925
8583
  Object.defineProperty(exports, "AuthManager", {
6926
8584
  enumerable: true,
6927
- get: function () { return chunkB2ASV5RD_cjs.AuthManager; }
8585
+ get: function () { return chunkVHNTCB2X_cjs.AuthManager; }
6928
8586
  });
6929
8587
  Object.defineProperty(exports, "PermissionManager", {
6930
8588
  enumerable: true,
6931
- get: function () { return chunkB2ASV5RD_cjs.PermissionManager; }
8589
+ get: function () { return chunkVHNTCB2X_cjs.PermissionManager; }
6932
8590
  });
6933
8591
  Object.defineProperty(exports, "bootstrapMiddleware", {
6934
8592
  enumerable: true,
6935
- get: function () { return chunkB2ASV5RD_cjs.bootstrapMiddleware; }
8593
+ get: function () { return chunkVHNTCB2X_cjs.bootstrapMiddleware; }
6936
8594
  });
6937
8595
  Object.defineProperty(exports, "cacheHeaders", {
6938
8596
  enumerable: true,
6939
- get: function () { return chunkB2ASV5RD_cjs.cacheHeaders; }
8597
+ get: function () { return chunkVHNTCB2X_cjs.cacheHeaders; }
6940
8598
  });
6941
8599
  Object.defineProperty(exports, "compressionMiddleware", {
6942
8600
  enumerable: true,
6943
- get: function () { return chunkB2ASV5RD_cjs.compressionMiddleware; }
8601
+ get: function () { return chunkVHNTCB2X_cjs.compressionMiddleware; }
6944
8602
  });
6945
8603
  Object.defineProperty(exports, "detailedLoggingMiddleware", {
6946
8604
  enumerable: true,
6947
- get: function () { return chunkB2ASV5RD_cjs.detailedLoggingMiddleware; }
8605
+ get: function () { return chunkVHNTCB2X_cjs.detailedLoggingMiddleware; }
6948
8606
  });
6949
8607
  Object.defineProperty(exports, "getActivePlugins", {
6950
8608
  enumerable: true,
6951
- get: function () { return chunkB2ASV5RD_cjs.getActivePlugins; }
8609
+ get: function () { return chunkVHNTCB2X_cjs.getActivePlugins; }
6952
8610
  });
6953
8611
  Object.defineProperty(exports, "isPluginActive", {
6954
8612
  enumerable: true,
6955
- get: function () { return chunkB2ASV5RD_cjs.isPluginActive; }
8613
+ get: function () { return chunkVHNTCB2X_cjs.isPluginActive; }
6956
8614
  });
6957
8615
  Object.defineProperty(exports, "logActivity", {
6958
8616
  enumerable: true,
6959
- get: function () { return chunkB2ASV5RD_cjs.logActivity; }
8617
+ get: function () { return chunkVHNTCB2X_cjs.logActivity; }
6960
8618
  });
6961
8619
  Object.defineProperty(exports, "loggingMiddleware", {
6962
8620
  enumerable: true,
6963
- get: function () { return chunkB2ASV5RD_cjs.loggingMiddleware; }
8621
+ get: function () { return chunkVHNTCB2X_cjs.loggingMiddleware; }
6964
8622
  });
6965
8623
  Object.defineProperty(exports, "optionalAuth", {
6966
8624
  enumerable: true,
6967
- get: function () { return chunkB2ASV5RD_cjs.optionalAuth; }
8625
+ get: function () { return chunkVHNTCB2X_cjs.optionalAuth; }
6968
8626
  });
6969
8627
  Object.defineProperty(exports, "performanceLoggingMiddleware", {
6970
8628
  enumerable: true,
6971
- get: function () { return chunkB2ASV5RD_cjs.performanceLoggingMiddleware; }
8629
+ get: function () { return chunkVHNTCB2X_cjs.performanceLoggingMiddleware; }
6972
8630
  });
6973
8631
  Object.defineProperty(exports, "requireActivePlugin", {
6974
8632
  enumerable: true,
6975
- get: function () { return chunkB2ASV5RD_cjs.requireActivePlugin; }
8633
+ get: function () { return chunkVHNTCB2X_cjs.requireActivePlugin; }
6976
8634
  });
6977
8635
  Object.defineProperty(exports, "requireActivePlugins", {
6978
8636
  enumerable: true,
6979
- get: function () { return chunkB2ASV5RD_cjs.requireActivePlugins; }
8637
+ get: function () { return chunkVHNTCB2X_cjs.requireActivePlugins; }
6980
8638
  });
6981
8639
  Object.defineProperty(exports, "requireAnyPermission", {
6982
8640
  enumerable: true,
6983
- get: function () { return chunkB2ASV5RD_cjs.requireAnyPermission; }
8641
+ get: function () { return chunkVHNTCB2X_cjs.requireAnyPermission; }
6984
8642
  });
6985
8643
  Object.defineProperty(exports, "requireAuth", {
6986
8644
  enumerable: true,
6987
- get: function () { return chunkB2ASV5RD_cjs.requireAuth; }
8645
+ get: function () { return chunkVHNTCB2X_cjs.requireAuth; }
6988
8646
  });
6989
8647
  Object.defineProperty(exports, "requirePermission", {
6990
8648
  enumerable: true,
6991
- get: function () { return chunkB2ASV5RD_cjs.requirePermission; }
8649
+ get: function () { return chunkVHNTCB2X_cjs.requirePermission; }
6992
8650
  });
6993
8651
  Object.defineProperty(exports, "requireRole", {
6994
8652
  enumerable: true,
6995
- get: function () { return chunkB2ASV5RD_cjs.requireRole; }
8653
+ get: function () { return chunkVHNTCB2X_cjs.requireRole; }
6996
8654
  });
6997
8655
  Object.defineProperty(exports, "securityHeaders", {
6998
8656
  enumerable: true,
6999
- get: function () { return chunkB2ASV5RD_cjs.securityHeadersMiddleware; }
8657
+ get: function () { return chunkVHNTCB2X_cjs.securityHeadersMiddleware; }
7000
8658
  });
7001
8659
  Object.defineProperty(exports, "securityLoggingMiddleware", {
7002
8660
  enumerable: true,
7003
- get: function () { return chunkB2ASV5RD_cjs.securityLoggingMiddleware; }
8661
+ get: function () { return chunkVHNTCB2X_cjs.securityLoggingMiddleware; }
7004
8662
  });
7005
8663
  Object.defineProperty(exports, "PluginBootstrapService", {
7006
8664
  enumerable: true,
7007
- get: function () { return chunk6BVLPACH_cjs.PluginBootstrapService; }
8665
+ get: function () { return chunkI6FFGQIT_cjs.PluginBootstrapService; }
7008
8666
  });
7009
8667
  Object.defineProperty(exports, "PluginServiceClass", {
7010
8668
  enumerable: true,
7011
- get: function () { return chunk6BVLPACH_cjs.PluginService; }
8669
+ get: function () { return chunkI6FFGQIT_cjs.PluginService; }
7012
8670
  });
7013
8671
  Object.defineProperty(exports, "backfillFormSubmissions", {
7014
8672
  enumerable: true,
7015
- get: function () { return chunk6BVLPACH_cjs.backfillFormSubmissions; }
8673
+ get: function () { return chunkI6FFGQIT_cjs.backfillFormSubmissions; }
7016
8674
  });
7017
8675
  Object.defineProperty(exports, "cleanupRemovedCollections", {
7018
8676
  enumerable: true,
7019
- get: function () { return chunk6BVLPACH_cjs.cleanupRemovedCollections; }
8677
+ get: function () { return chunkI6FFGQIT_cjs.cleanupRemovedCollections; }
7020
8678
  });
7021
8679
  Object.defineProperty(exports, "createContentFromSubmission", {
7022
8680
  enumerable: true,
7023
- get: function () { return chunk6BVLPACH_cjs.createContentFromSubmission; }
8681
+ get: function () { return chunkI6FFGQIT_cjs.createContentFromSubmission; }
7024
8682
  });
7025
8683
  Object.defineProperty(exports, "deriveCollectionSchemaFromFormio", {
7026
8684
  enumerable: true,
7027
- get: function () { return chunk6BVLPACH_cjs.deriveCollectionSchemaFromFormio; }
8685
+ get: function () { return chunkI6FFGQIT_cjs.deriveCollectionSchemaFromFormio; }
7028
8686
  });
7029
8687
  Object.defineProperty(exports, "deriveSubmissionTitle", {
7030
8688
  enumerable: true,
7031
- get: function () { return chunk6BVLPACH_cjs.deriveSubmissionTitle; }
8689
+ get: function () { return chunkI6FFGQIT_cjs.deriveSubmissionTitle; }
7032
8690
  });
7033
8691
  Object.defineProperty(exports, "fullCollectionSync", {
7034
8692
  enumerable: true,
7035
- get: function () { return chunk6BVLPACH_cjs.fullCollectionSync; }
8693
+ get: function () { return chunkI6FFGQIT_cjs.fullCollectionSync; }
7036
8694
  });
7037
8695
  Object.defineProperty(exports, "getAvailableCollectionNames", {
7038
8696
  enumerable: true,
7039
- get: function () { return chunk6BVLPACH_cjs.getAvailableCollectionNames; }
8697
+ get: function () { return chunkI6FFGQIT_cjs.getAvailableCollectionNames; }
7040
8698
  });
7041
8699
  Object.defineProperty(exports, "getManagedCollections", {
7042
8700
  enumerable: true,
7043
- get: function () { return chunk6BVLPACH_cjs.getManagedCollections; }
8701
+ get: function () { return chunkI6FFGQIT_cjs.getManagedCollections; }
7044
8702
  });
7045
8703
  Object.defineProperty(exports, "isCollectionManaged", {
7046
8704
  enumerable: true,
7047
- get: function () { return chunk6BVLPACH_cjs.isCollectionManaged; }
8705
+ get: function () { return chunkI6FFGQIT_cjs.isCollectionManaged; }
7048
8706
  });
7049
8707
  Object.defineProperty(exports, "loadCollectionConfig", {
7050
8708
  enumerable: true,
7051
- get: function () { return chunk6BVLPACH_cjs.loadCollectionConfig; }
8709
+ get: function () { return chunkI6FFGQIT_cjs.loadCollectionConfig; }
7052
8710
  });
7053
8711
  Object.defineProperty(exports, "loadCollectionConfigs", {
7054
8712
  enumerable: true,
7055
- get: function () { return chunk6BVLPACH_cjs.loadCollectionConfigs; }
8713
+ get: function () { return chunkI6FFGQIT_cjs.loadCollectionConfigs; }
7056
8714
  });
7057
8715
  Object.defineProperty(exports, "mapFormStatusToContentStatus", {
7058
8716
  enumerable: true,
7059
- get: function () { return chunk6BVLPACH_cjs.mapFormStatusToContentStatus; }
8717
+ get: function () { return chunkI6FFGQIT_cjs.mapFormStatusToContentStatus; }
7060
8718
  });
7061
8719
  Object.defineProperty(exports, "registerCollections", {
7062
8720
  enumerable: true,
7063
- get: function () { return chunk6BVLPACH_cjs.registerCollections; }
8721
+ get: function () { return chunkI6FFGQIT_cjs.registerCollections; }
7064
8722
  });
7065
8723
  Object.defineProperty(exports, "syncAllFormCollections", {
7066
8724
  enumerable: true,
7067
- get: function () { return chunk6BVLPACH_cjs.syncAllFormCollections; }
8725
+ get: function () { return chunkI6FFGQIT_cjs.syncAllFormCollections; }
7068
8726
  });
7069
8727
  Object.defineProperty(exports, "syncCollection", {
7070
8728
  enumerable: true,
7071
- get: function () { return chunk6BVLPACH_cjs.syncCollection; }
8729
+ get: function () { return chunkI6FFGQIT_cjs.syncCollection; }
7072
8730
  });
7073
8731
  Object.defineProperty(exports, "syncCollections", {
7074
8732
  enumerable: true,
7075
- get: function () { return chunk6BVLPACH_cjs.syncCollections; }
8733
+ get: function () { return chunkI6FFGQIT_cjs.syncCollections; }
7076
8734
  });
7077
8735
  Object.defineProperty(exports, "syncFormCollection", {
7078
8736
  enumerable: true,
7079
- get: function () { return chunk6BVLPACH_cjs.syncFormCollection; }
8737
+ get: function () { return chunkI6FFGQIT_cjs.syncFormCollection; }
7080
8738
  });
7081
8739
  Object.defineProperty(exports, "validateCollectionConfig", {
7082
8740
  enumerable: true,
7083
- get: function () { return chunk6BVLPACH_cjs.validateCollectionConfig; }
8741
+ get: function () { return chunkI6FFGQIT_cjs.validateCollectionConfig; }
7084
8742
  });
7085
8743
  Object.defineProperty(exports, "MigrationService", {
7086
8744
  enumerable: true,
7087
- get: function () { return chunkDE5YTNCD_cjs.MigrationService; }
8745
+ get: function () { return chunkAG3SIPP7_cjs.MigrationService; }
7088
8746
  });
7089
8747
  Object.defineProperty(exports, "renderFilterBar", {
7090
8748
  enumerable: true,
7091
- get: function () { return chunk3G7XX4UI_cjs.renderFilterBar; }
8749
+ get: function () { return chunkRBXFXT7H_cjs.renderFilterBar; }
7092
8750
  });
7093
8751
  Object.defineProperty(exports, "getConfirmationDialogScript", {
7094
8752
  enumerable: true,
7095
- get: function () { return chunkLTKV7AE5_cjs.getConfirmationDialogScript; }
8753
+ get: function () { return chunkH4NHRZ6Y_cjs.getConfirmationDialogScript; }
7096
8754
  });
7097
8755
  Object.defineProperty(exports, "renderAlert", {
7098
8756
  enumerable: true,
7099
- get: function () { return chunkLTKV7AE5_cjs.renderAlert; }
8757
+ get: function () { return chunkH4NHRZ6Y_cjs.renderAlert; }
7100
8758
  });
7101
8759
  Object.defineProperty(exports, "renderConfirmationDialog", {
7102
8760
  enumerable: true,
7103
- get: function () { return chunkLTKV7AE5_cjs.renderConfirmationDialog; }
8761
+ get: function () { return chunkH4NHRZ6Y_cjs.renderConfirmationDialog; }
7104
8762
  });
7105
8763
  Object.defineProperty(exports, "renderForm", {
7106
8764
  enumerable: true,
7107
- get: function () { return chunkLTKV7AE5_cjs.renderForm; }
8765
+ get: function () { return chunkH4NHRZ6Y_cjs.renderForm; }
7108
8766
  });
7109
8767
  Object.defineProperty(exports, "renderFormField", {
7110
8768
  enumerable: true,
7111
- get: function () { return chunkLTKV7AE5_cjs.renderFormField; }
8769
+ get: function () { return chunkH4NHRZ6Y_cjs.renderFormField; }
7112
8770
  });
7113
8771
  Object.defineProperty(exports, "renderPagination", {
7114
8772
  enumerable: true,
7115
- get: function () { return chunkLTKV7AE5_cjs.renderPagination; }
8773
+ get: function () { return chunkH4NHRZ6Y_cjs.renderPagination; }
7116
8774
  });
7117
8775
  Object.defineProperty(exports, "renderTable", {
7118
8776
  enumerable: true,
7119
- get: function () { return chunkLTKV7AE5_cjs.renderTable; }
8777
+ get: function () { return chunkH4NHRZ6Y_cjs.renderTable; }
7120
8778
  });
7121
8779
  Object.defineProperty(exports, "HookSystemImpl", {
7122
8780
  enumerable: true,
@@ -7152,31 +8810,31 @@ Object.defineProperty(exports, "PluginHelpers", {
7152
8810
  });
7153
8811
  Object.defineProperty(exports, "QueryFilterBuilder", {
7154
8812
  enumerable: true,
7155
- get: function () { return chunkQLPFENZ2_cjs.QueryFilterBuilder; }
8813
+ get: function () { return chunkRXNLGINR_cjs.QueryFilterBuilder; }
7156
8814
  });
7157
8815
  Object.defineProperty(exports, "SONICJS_VERSION", {
7158
8816
  enumerable: true,
7159
- get: function () { return chunkQLPFENZ2_cjs.SONICJS_VERSION; }
8817
+ get: function () { return chunkRXNLGINR_cjs.SONICJS_VERSION; }
7160
8818
  });
7161
8819
  Object.defineProperty(exports, "TemplateRenderer", {
7162
8820
  enumerable: true,
7163
- get: function () { return chunkQLPFENZ2_cjs.TemplateRenderer; }
8821
+ get: function () { return chunkRXNLGINR_cjs.TemplateRenderer; }
7164
8822
  });
7165
8823
  Object.defineProperty(exports, "buildQuery", {
7166
8824
  enumerable: true,
7167
- get: function () { return chunkQLPFENZ2_cjs.buildQuery; }
8825
+ get: function () { return chunkRXNLGINR_cjs.buildQuery; }
7168
8826
  });
7169
8827
  Object.defineProperty(exports, "getCoreVersion", {
7170
8828
  enumerable: true,
7171
- get: function () { return chunkQLPFENZ2_cjs.getCoreVersion; }
8829
+ get: function () { return chunkRXNLGINR_cjs.getCoreVersion; }
7172
8830
  });
7173
8831
  Object.defineProperty(exports, "renderTemplate", {
7174
8832
  enumerable: true,
7175
- get: function () { return chunkQLPFENZ2_cjs.renderTemplate; }
8833
+ get: function () { return chunkRXNLGINR_cjs.renderTemplate; }
7176
8834
  });
7177
8835
  Object.defineProperty(exports, "templateRenderer", {
7178
8836
  enumerable: true,
7179
- get: function () { return chunkQLPFENZ2_cjs.templateRenderer; }
8837
+ get: function () { return chunkRXNLGINR_cjs.templateRenderer; }
7180
8838
  });
7181
8839
  Object.defineProperty(exports, "metricsTracker", {
7182
8840
  enumerable: true,