openlearn-next 0.2.3 → 0.2.6

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 (55) hide show
  1. package/README.md +34 -136
  2. package/dist/assets/AdminDirectoryView-Cai0cQqi.js +1 -0
  3. package/dist/assets/BatchPickerModal-CKQyeY6R.js +1 -0
  4. package/dist/assets/ClassesView-Cxgfcrx1.js +19 -0
  5. package/dist/assets/CloudDriveModal-DgDurUBT.js +1 -0
  6. package/dist/assets/ComputerLabView-CUCO2VIV.js +1 -0
  7. package/dist/assets/CourseManagement-DSCOjuIC.js +1 -0
  8. package/dist/assets/CourseWizardModal-B3QnFxvj.js +3 -0
  9. package/dist/assets/CoursewareHubPanel-CAaf22Qm.js +1 -0
  10. package/dist/assets/Dashboard-Xly67TyD.js +8 -0
  11. package/dist/assets/ExportWeightModal-BlS2auLs.js +1 -0
  12. package/dist/assets/HelpTour-ZgEkRnin.js +1 -0
  13. package/dist/assets/HelpView-DgFLEuso.js +204 -0
  14. package/dist/assets/ImportLessonsModal-BZZRDBRU.js +1 -0
  15. package/dist/assets/ImportModal-mkWuDoAN.js +1 -0
  16. package/dist/assets/InteractiveCoursewareViewer-EIRNulEo.js +1 -0
  17. package/dist/assets/InteractiveWhiteboard-DDOKVrHd.js +102 -0
  18. package/dist/assets/LazyCourseware-qE4CY67E.js +1 -0
  19. package/dist/assets/LazyWhiteboard-C9fzRtzL.js +2 -0
  20. package/dist/assets/LessonEditorView-D1nhlQon.js +1 -0
  21. package/dist/assets/LiveClassroomView-C1lI4lFd.js +1 -0
  22. package/dist/assets/NotificationDetailModal-dndFrE7p.js +1 -0
  23. package/dist/assets/PluginView-5TYIP1ze.js +65 -0
  24. package/dist/assets/ProcessLogsModal-8mVp07ic.js +1 -0
  25. package/dist/assets/QuizGeneratorModal-DpTFYbVJ.js +1 -0
  26. package/dist/assets/StudentAssignmentView-CCGWFVqD.js +1 -0
  27. package/dist/assets/StudentLessonView-yhRHP8e8.js +1 -0
  28. package/dist/assets/StudentPreviewModal-UpNg1yl0.js +1 -0
  29. package/dist/assets/StudentView-C1cc6RuC.js +1 -0
  30. package/dist/assets/SystemResourceLibraryModal-Dnh7F5Vm.js +1 -0
  31. package/dist/assets/TeacherView-CWjbV0x-.js +2 -0
  32. package/dist/assets/TimetableView-zce3okQn.js +6 -0
  33. package/dist/assets/index-B9cwmoaG.js +129 -0
  34. package/dist/assets/index-BrEBeWAQ.js +14 -0
  35. package/dist/assets/index-CATki2cp.css +1 -0
  36. package/dist/assets/index-Cq_aKTfc.js +1 -0
  37. package/dist/assets/{index.es-CF5dm42F.js → index.es-DZ6UeYE-.js} +2 -2
  38. package/dist/assets/vendor-charts-B7ViBL9w.js +71 -0
  39. package/dist/assets/vendor-icons-BvCtGbt1.js +8221 -0
  40. package/dist/assets/vendor-konva-CzxOmTv9.js +49 -0
  41. package/dist/assets/vendor-motion-Dz5URUo4.js +9 -0
  42. package/dist/assets/vendor-pdf-CVyNPGVr.js +191 -0
  43. package/dist/assets/{vendor-pptx-CJ3I-KT0.js → vendor-pptx-B0hlo0eh.js} +1 -1
  44. package/dist/assets/vendor-react-0Lg0vA-4.js +49 -0
  45. package/dist/assets/vendor-utils-4FcTwKPj.js +1 -0
  46. package/dist/index.html +2 -3
  47. package/dist/server.cjs +185 -73
  48. package/package.json +1 -1
  49. package/dist/assets/courseware-Cc-Yy0Ha.js +0 -1
  50. package/dist/assets/index-CsN5CIqI.css +0 -1
  51. package/dist/assets/index-D_zAVH7u.js +0 -682
  52. package/dist/assets/vendor-html2canvas-B0tyYwQk.js +0 -22
  53. package/dist/assets/vendor-konva-GivUq6dt.js +0 -89
  54. package/dist/assets/whiteboard-jgQrAUm7.js +0 -8343
  55. /package/dist/assets/{purify.es-V6uLfjnH.js → vendor-content-V6uLfjnH.js} +0 -0
package/dist/server.cjs CHANGED
@@ -973,8 +973,8 @@ function wrapCommandBus(commandBus, tracker, pluginId, manifestId) {
973
973
  throw e;
974
974
  }
975
975
  }),
976
- setInterceptor: createSafeFunction((interceptor) => {
977
- return commandBus.setInterceptor(interceptor);
976
+ setInterceptor: createSafeFunction((_interceptor) => {
977
+ throw new Error("[Security] setInterceptor cannot be configured from PluginContext");
978
978
  }),
979
979
  unregisterHandler: createSafeFunction((commandType) => {
980
980
  return commandBus.unregisterHandler(resolveType(commandType));
@@ -2506,8 +2506,8 @@ parentPort.on('message', async function(msg) {
2506
2506
  createCommand: function(type, payload, actorId, metadata) {
2507
2507
  return rawCommandBus.createCommand(type, payload, actorId, metadata);
2508
2508
  },
2509
- setInterceptor: function(interceptor) {
2510
- return rawCommandBus.setInterceptor(interceptor);
2509
+ setInterceptor: function(_interceptor) {
2510
+ throw new Error('[Security] setInterceptor cannot be configured from Worker PluginContext');
2511
2511
  }
2512
2512
  } : undefined;
2513
2513
 
@@ -2659,6 +2659,21 @@ parentPort.on('message', async function(msg) {
2659
2659
  },
2660
2660
  db: dbApi,
2661
2661
  require: function(moduleName) {
2662
+ var BLOCKED_NATIVE_MODULES = [
2663
+ 'child_process', 'node:child_process',
2664
+ 'fs', 'node:fs', 'fs/promises', 'node:fs/promises',
2665
+ 'net', 'node:net',
2666
+ 'http', 'node:http', 'https', 'node:https', 'http2', 'node:http2',
2667
+ 'dgram', 'node:dgram', 'dns', 'node:dns',
2668
+ 'cluster', 'node:cluster',
2669
+ 'worker_threads', 'node:worker_threads',
2670
+ 'vm', 'node:vm',
2671
+ 'v8', 'node:v8',
2672
+ 'wasi', 'node:wasi'
2673
+ ];
2674
+ if (BLOCKED_NATIVE_MODULES.indexOf(moduleName) !== -1) {
2675
+ throw new Error('[SecurityError] Direct access to Node.js native module "' + moduleName + '" is forbidden in plugin worker sandbox.');
2676
+ }
2662
2677
  if (PLUGIN_SHARED_MODULES.indexOf(moduleName) !== -1) {
2663
2678
  try {
2664
2679
  return requireFn(moduleName);
@@ -3374,7 +3389,16 @@ var CapabilityGuard = class {
3374
3389
  constructor() {
3375
3390
  this.actorCapabilities = /* @__PURE__ */ new Map();
3376
3391
  this.actorCapabilities.set("user-demo", ["*:*:*"]);
3377
- this.actorCapabilities.set("user-frontend", ["*:*:*"]);
3392
+ this.actorCapabilities.set("user-frontend", [
3393
+ "lesson:*",
3394
+ "whiteboard:*",
3395
+ "management:*",
3396
+ "quiz:*",
3397
+ "vfs:*",
3398
+ "process:*",
3399
+ "plugin:*"
3400
+ ]);
3401
+ this.actorCapabilities.set("anonymous", []);
3378
3402
  this.actorCapabilities.set("agent-system-0", [
3379
3403
  "lesson:write",
3380
3404
  "lesson:delete",
@@ -3388,8 +3412,8 @@ var CapabilityGuard = class {
3388
3412
  "process:write",
3389
3413
  "process:read"
3390
3414
  ]);
3391
- this.actorCapabilities.set("teacher-demo", ["lesson:write", "lesson:read"]);
3392
- this.actorCapabilities.set("student-demo", ["student:write"]);
3415
+ this.actorCapabilities.set("teacher-demo", ["lesson:*", "whiteboard:*", "management:*", "quiz:*", "vfs:*"]);
3416
+ this.actorCapabilities.set("student-demo", ["student:write", "lesson:read", "whiteboard:read"]);
3393
3417
  }
3394
3418
  grant(actorId, cap) {
3395
3419
  const caps = this.actorCapabilities.get(actorId) || [];
@@ -3402,8 +3426,28 @@ var CapabilityGuard = class {
3402
3426
  this.actorCapabilities.delete(actorId);
3403
3427
  }
3404
3428
  check(actorId, requiredCap) {
3405
- const isAdmin = actorId === "role:administrator" || actorId?.endsWith(":administrator") || actorId === "admin-demo";
3429
+ const isAdmin = actorId === "role:administrator" || actorId?.endsWith(":administrator") || actorId === "admin" || actorId === "usr_admin" || actorId === "admin-demo";
3406
3430
  if (isAdmin) return true;
3431
+ if (actorId?.endsWith(":teacher")) {
3432
+ const teacherCaps = ["lesson:*", "whiteboard:*", "management:*", "quiz:*", "vfs:*", "process:*", "plugin:*"];
3433
+ const [reqRes2, reqAct2] = requiredCap.split(":");
3434
+ if (teacherCaps.some((c) => {
3435
+ const [res, act] = c.split(":");
3436
+ return (res === reqRes2 || res === "*") && (act === reqAct2 || act === "*");
3437
+ })) {
3438
+ return true;
3439
+ }
3440
+ }
3441
+ if (actorId?.endsWith(":student")) {
3442
+ const studentCaps = ["student:write", "lesson:read", "whiteboard:read"];
3443
+ const [reqRes2, reqAct2] = requiredCap.split(":");
3444
+ if (studentCaps.some((c) => {
3445
+ const [res, act] = c.split(":");
3446
+ return (res === reqRes2 || res === "*") && (act === reqAct2 || act === "*");
3447
+ })) {
3448
+ return true;
3449
+ }
3450
+ }
3407
3451
  const caps = this.actorCapabilities.get(actorId) || [];
3408
3452
  if (caps.includes("*:*:*") || caps.includes("*")) return true;
3409
3453
  if (caps.includes(requiredCap)) return true;
@@ -3638,7 +3682,7 @@ var classroomToolSchema = import_zod.z.object({
3638
3682
  icon: import_zod.z.string().optional(),
3639
3683
  description: import_zod.z.string().optional(),
3640
3684
  commandType: import_zod.z.string().min(1),
3641
- payload: import_zod.z.record(import_zod.z.unknown()).optional()
3685
+ payload: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
3642
3686
  });
3643
3687
  var contributesSchema = import_zod.z.object({
3644
3688
  "classroom.tool": import_zod.z.array(classroomToolSchema).optional(),
@@ -3665,7 +3709,10 @@ var contributesSchema = import_zod.z.object({
3665
3709
  label: import_zod.z.string().min(1),
3666
3710
  icon: import_zod.z.string().optional()
3667
3711
  })).optional()
3668
- }).optional();
3712
+ // v0.2.6: 锚点槽位(anchor:*)为开放命名空间,由宿主公布锚点 id。
3713
+ // .passthrough() 保留任意 anchor:* 键(运行时透传),避免被 zod 默认 strip。
3714
+ // 锚点条目的运行时校验由前端注册时(ExtensionPointConfig)完成。
3715
+ }).passthrough().optional();
3669
3716
  var deploySchema = import_zod.z.object({
3670
3717
  script: import_zod.z.string().min(1, { error: "deploy.script \u4E0D\u80FD\u4E3A\u7A7A" }).optional(),
3671
3718
  staticRoute: import_zod.z.string().optional(),
@@ -3689,7 +3736,7 @@ var manifestSchema = import_zod.z.object({
3689
3736
  pluginDependencies: import_zod.z.array(import_zod.z.string().min(1)).optional(),
3690
3737
  provides: import_zod.z.array(import_zod.z.string().min(1)).optional(),
3691
3738
  configuration: import_zod.z.object({
3692
- properties: import_zod.z.record(import_zod.z.object({
3739
+ properties: import_zod.z.record(import_zod.z.string(), import_zod.z.object({
3693
3740
  type: import_zod.z.enum(["string", "number", "boolean", "integer"]),
3694
3741
  default: import_zod.z.unknown().optional(),
3695
3742
  description: import_zod.z.string().optional(),
@@ -4116,6 +4163,17 @@ db.exec(`
4116
4163
  status TEXT NOT NULL DEFAULT 'draft',
4117
4164
  graded_at INTEGER
4118
4165
  );
4166
+
4167
+ -- Performance Indexes
4168
+ CREATE INDEX IF NOT EXISTS idx_whiteboard_lesson ON whiteboard_elements(lesson_id);
4169
+ CREATE INDEX IF NOT EXISTS idx_class_students_class ON class_students(class_id);
4170
+ CREATE INDEX IF NOT EXISTS idx_class_students_student ON class_students(student_id);
4171
+ CREATE INDEX IF NOT EXISTS idx_schedules_class_date ON schedules(class_id, scheduled_date);
4172
+ CREATE INDEX IF NOT EXISTS idx_courseware_attempt_cw_st ON courseware_attempt(courseware_id, student_id);
4173
+ CREATE INDEX IF NOT EXISTS idx_submission_result_attempt ON submission_result(attempt_id);
4174
+ CREATE INDEX IF NOT EXISTS idx_events_type_time ON events(type, timestamp);
4175
+ CREATE INDEX IF NOT EXISTS idx_assignments_class ON assignments(class_id);
4176
+ CREATE INDEX IF NOT EXISTS idx_attendance_schedule ON attendance(schedule_id);
4119
4177
  `);
4120
4178
  try {
4121
4179
  db.exec(`ALTER TABLE plugins ADD COLUMN execution_mode TEXT DEFAULT 'inline'`);
@@ -4250,7 +4308,7 @@ var VfsPlugin = {
4250
4308
  "@openlearn/core:IDatabase@^1.0.0"
4251
4309
  ],
4252
4310
  capabilitiesProposed: ["vfs:read", "vfs:write"],
4253
- engines: { openlearn: "^2.5.0" }
4311
+ engines: { openlearn: "^0.2.5" }
4254
4312
  },
4255
4313
  activate: async (ctx) => {
4256
4314
  const commandBus = ctx.services.commandBus;
@@ -4416,7 +4474,7 @@ var ProcessPlugin = {
4416
4474
  "@openlearn/core:IDatabase@^1.0.0"
4417
4475
  ],
4418
4476
  capabilitiesProposed: ["process:read", "process:write"],
4419
- engines: { openlearn: "^2.5.0" }
4477
+ engines: { openlearn: "^0.2.5" }
4420
4478
  },
4421
4479
  activate: async (ctx) => {
4422
4480
  const commandBus = ctx.services.commandBus;
@@ -4547,7 +4605,7 @@ var ManagementPlugin = {
4547
4605
  "@openlearn/core:IDatabase@^1.0.0"
4548
4606
  ],
4549
4607
  capabilitiesProposed: ["class:read", "class:write", "student:read", "student:write"],
4550
- engines: { openlearn: "^2.5.0" }
4608
+ engines: { openlearn: "^0.2.5" }
4551
4609
  },
4552
4610
  activate: async (ctx) => {
4553
4611
  const commandBus = ctx.services.commandBus;
@@ -5446,7 +5504,7 @@ var AiSubmitInjectorPlugin = {
5446
5504
  "@openlearn/core:IAIService@^1.0.0"
5447
5505
  ],
5448
5506
  capabilitiesProposed: [],
5449
- engines: { openlearn: "^2.5.0" }
5507
+ engines: { openlearn: "^0.2.5" }
5450
5508
  },
5451
5509
  activate: async (ctx) => {
5452
5510
  const eventBus = ctx.services.eventBus;
@@ -5538,7 +5596,7 @@ var BuiltinPlugin = {
5538
5596
  "@openlearn/core:IPluginHost@^1.0.0"
5539
5597
  ],
5540
5598
  capabilitiesProposed: ["lesson:read", "lesson:write", "whiteboard:read", "whiteboard:write"],
5541
- engines: { openlearn: "^2.5.0" }
5599
+ engines: { openlearn: "^0.2.5" }
5542
5600
  },
5543
5601
  activate: async (ctx) => {
5544
5602
  const commandBus = ctx.services.commandBus;
@@ -6923,7 +6981,7 @@ var AiPlannerPlugin = {
6923
6981
  "@openlearn/core:IEventBusService@^1.0.0"
6924
6982
  ],
6925
6983
  capabilitiesProposed: ["process:write", "lesson:write", "assignment:write"],
6926
- engines: { openlearn: "^2.5.0" }
6984
+ engines: { openlearn: "^0.2.5" }
6927
6985
  },
6928
6986
  activate: async (ctx) => {
6929
6987
  const commandBus = ctx.services.commandBus;
@@ -7109,7 +7167,7 @@ var AssignmentEvalPlugin = {
7109
7167
  "@openlearn/core:ISemesterGradeService@^1.0.0"
7110
7168
  ],
7111
7169
  capabilitiesProposed: ["lesson:read", "lesson:write"],
7112
- engines: { openlearn: "^2.5.0" }
7170
+ engines: { openlearn: "^0.2.5" }
7113
7171
  },
7114
7172
  activate: async (ctx) => {
7115
7173
  const commandBus = ctx.services.commandBus;
@@ -7695,7 +7753,7 @@ var ContributionRegistry = class {
7695
7753
  register(pluginId, contributes) {
7696
7754
  this.unregister(pluginId);
7697
7755
  for (const [slot, configs] of Object.entries(contributes)) {
7698
- if (!configs || configs.length === 0) continue;
7756
+ if (!Array.isArray(configs) || configs.length === 0) continue;
7699
7757
  if (!this.contributions.has(slot)) {
7700
7758
  this.contributions.set(slot, /* @__PURE__ */ new Map());
7701
7759
  }
@@ -8057,7 +8115,7 @@ var PluginRuntimeComposition = class {
8057
8115
  this.workerManager = workerManager;
8058
8116
  this.id = "srv_plugin_runtime_composition";
8059
8117
  this.name = "PluginRuntimeComposition";
8060
- this.version = "2.5.0";
8118
+ this.version = "0.2.5";
8061
8119
  this._isStarted = false;
8062
8120
  }
8063
8121
  get isStarted() {
@@ -8111,7 +8169,7 @@ var PluginLifecycleManager = class {
8111
8169
  this.pluginHost = pluginHost;
8112
8170
  this.id = "srv_plugin_lifecycle_manager";
8113
8171
  this.name = "PluginLifecycleManager";
8114
- this.version = "2.5.0";
8172
+ this.version = "0.2.5";
8115
8173
  }
8116
8174
  getPluginState(pluginId) {
8117
8175
  return this.pluginHost.getPluginState(pluginId);
@@ -8158,7 +8216,7 @@ var PluginCapabilityGateway = class {
8158
8216
  this.capabilityRegistry = capabilityRegistry;
8159
8217
  this.id = "srv_plugin_capability_gateway";
8160
8218
  this.name = "PluginCapabilityGateway";
8161
- this.version = "2.5.0";
8219
+ this.version = "0.2.5";
8162
8220
  }
8163
8221
  listCapabilities() {
8164
8222
  const rawCaps = this.capabilityRegistry.listCapabilities();
@@ -8212,7 +8270,7 @@ var UnifiedExtensionRegistry = class {
8212
8270
  constructor() {
8213
8271
  this.id = "srv_unified_extension_registry";
8214
8272
  this.name = "UnifiedExtensionRegistry";
8215
- this.version = "2.5.0";
8273
+ this.version = "0.2.5";
8216
8274
  this._extensions = /* @__PURE__ */ new Map();
8217
8275
  }
8218
8276
  registerExtension(category, id, impl, meta) {
@@ -8317,7 +8375,7 @@ var PluginDistributionManager = class {
8317
8375
  this.pluginHost = pluginHost;
8318
8376
  this.id = "srv_plugin_distribution_manager";
8319
8377
  this.name = "PluginDistributionManager";
8320
- this.version = "2.5.0";
8378
+ this.version = "0.2.5";
8321
8379
  this._repositories = /* @__PURE__ */ new Map();
8322
8380
  }
8323
8381
  registerRepository(repo) {
@@ -8406,7 +8464,7 @@ function validatePluginStateTransition(currentState, nextState, pluginId) {
8406
8464
  }
8407
8465
  var ACTIVATION_TIMEOUT_MS = 5e3;
8408
8466
  var DEACTIVATION_TIMEOUT_MS = 5e3;
8409
- var OPENLEARN_VERSION = "2.5.0";
8467
+ var OPENLEARN_VERSION = "0.2.5";
8410
8468
  var PluginHost = class {
8411
8469
  constructor(serviceRegistry, esmLoader, db2, pluginsDir) {
8412
8470
  this.serviceRegistry = serviceRegistry;
@@ -10431,7 +10489,7 @@ var HotReloadController = class {
10431
10489
  }
10432
10490
  if (this.enabled) return;
10433
10491
  this.enabled = true;
10434
- await this.fileWatcher.startWatch(this.watchDir, (event) => {
10492
+ await this.fileWatcher.startWatch(this.watchDir, async (event) => {
10435
10493
  this.handleFileChange(event.pluginId, event.filePath);
10436
10494
  });
10437
10495
  console.log("[HotReload] Hot reload enabled \u2014 watching for plugin changes");
@@ -16020,7 +16078,7 @@ var StartupTimeoutError = class extends PlatformBootstrapError {
16020
16078
  this.name = "StartupTimeoutError";
16021
16079
  }
16022
16080
  };
16023
- var PLATFORM_VERSION = "2.5.0";
16081
+ var PLATFORM_VERSION = "0.2.5";
16024
16082
  var BOOTSTRAP_STAGE_NAMES = Object.freeze([
16025
16083
  "Created" /* Created */,
16026
16084
  "Configuring" /* Configuring */,
@@ -16722,10 +16780,10 @@ var PluginCompositionModule = class {
16722
16780
  const realPluginHost = options?.infrastructureRefs?.get("pluginHost") ?? { name: "PluginHostService", isReady: true, pluginsCount: 0 };
16723
16781
  const realContributionRegistry = options?.infrastructureRefs?.get("contributionRegistry") ?? { name: "ContributionRegistry", slotsCount: 0 };
16724
16782
  const realRuntimeComposition = options?.infrastructureRefs?.get("runtimeComposition") ?? { name: "PluginRuntimeComposition", isStarted: true };
16725
- const realLifecycleManager = options?.infrastructureRefs?.get("lifecycleManager") ?? { name: "PluginLifecycleManager", version: "2.5.0" };
16726
- const realCapabilityGateway = options?.infrastructureRefs?.get("capabilityGateway") ?? { name: "PluginCapabilityGateway", version: "2.5.0" };
16727
- const realExtensionRegistry = options?.infrastructureRefs?.get("extensionRegistry") ?? { name: "UnifiedExtensionRegistry", version: "2.5.0" };
16728
- const realDistributionManager = options?.infrastructureRefs?.get("distributionManager") ?? { name: "PluginDistributionManager", version: "2.5.0" };
16783
+ const realLifecycleManager = options?.infrastructureRefs?.get("lifecycleManager") ?? { name: "PluginLifecycleManager", version: "0.2.5" };
16784
+ const realCapabilityGateway = options?.infrastructureRefs?.get("capabilityGateway") ?? { name: "PluginCapabilityGateway", version: "0.2.5" };
16785
+ const realExtensionRegistry = options?.infrastructureRefs?.get("extensionRegistry") ?? { name: "UnifiedExtensionRegistry", version: "0.2.5" };
16786
+ const realDistributionManager = options?.infrastructureRefs?.get("distributionManager") ?? { name: "PluginDistributionManager", version: "0.2.5" };
16729
16787
  registerOrReplace({
16730
16788
  id: "srv_plugin_host",
16731
16789
  lifetime: "Singleton",
@@ -16893,7 +16951,7 @@ var Kernel = class {
16893
16951
  throw new Error(`[PayloadValidationError] Invalid command payload for ${command.type}: ${errors.join("; ")}`);
16894
16952
  }
16895
16953
  }
16896
- const isAdmin = command.actorId === "role:administrator" || command.actorId === "admin" || command.actorId === "usr_admin" || command.actorId === "admin-demo" || command.actorId?.endsWith(":administrator") || command.actorId?.endsWith(":admin") || command.actorId?.includes(":administrator") || command.actorId?.includes(":admin");
16954
+ const isAdmin = command.actorId === "role:administrator" || command.actorId === "admin" || command.actorId === "usr_admin" || command.actorId === "admin-demo" || command.actorId?.endsWith(":administrator") || command.actorId?.endsWith(":admin");
16897
16955
  if (action.capabilityRequired && !isAdmin) {
16898
16956
  const allowed = this.capabilityGuard.check(command.actorId, action.capabilityRequired);
16899
16957
  if (!allowed) {
@@ -18367,10 +18425,10 @@ function getCookieToken(req) {
18367
18425
  }
18368
18426
  function getActorId(req) {
18369
18427
  const token = getCookieToken(req);
18370
- if (!token) return "user-frontend";
18428
+ if (!token) return "anonymous";
18371
18429
  try {
18372
18430
  const session = getValidSession(token);
18373
- if (!session) return "user-frontend";
18431
+ if (!session) return "anonymous";
18374
18432
  let role = session.subRole || session.role;
18375
18433
  if (session.username === "admin" || session.userId === "usr_admin" || role === "admin" || role === "administrator") {
18376
18434
  role = "administrator";
@@ -18378,11 +18436,31 @@ function getActorId(req) {
18378
18436
  if (role) {
18379
18437
  return `user:${session.userId || "demo"}:${role}`;
18380
18438
  }
18381
- return "user-frontend";
18439
+ return "anonymous";
18382
18440
  } catch {
18383
- return "user-frontend";
18441
+ return "anonymous";
18384
18442
  }
18385
18443
  }
18444
+ function requireAuth(...roles) {
18445
+ return (req, res, next) => {
18446
+ const token = getCookieToken(req);
18447
+ if (!token) return res.status(401).json({ success: false, error: "Authentication required" });
18448
+ const session = getValidSession(token);
18449
+ if (!session) return res.status(401).json({ success: false, error: "Session expired or invalid" });
18450
+ if (roles.length > 0) {
18451
+ let userRole = session.role;
18452
+ if (session.username === "admin" || session.userId === "usr_admin" || userRole === "admin") {
18453
+ userRole = "administrator";
18454
+ }
18455
+ const effectiveRoles = roles.map((r) => r === "admin" ? "administrator" : r);
18456
+ if (!effectiveRoles.includes(userRole)) {
18457
+ return res.status(403).json({ success: false, error: `Role ${session.role} not allowed. Required: ${roles.join(", ")}` });
18458
+ }
18459
+ }
18460
+ req.session = session;
18461
+ next();
18462
+ };
18463
+ }
18386
18464
  function checkIsTeacherOrAdmin(req) {
18387
18465
  const token = getCookieToken(req);
18388
18466
  if (!token) return false;
@@ -19143,7 +19221,7 @@ function registerOsRoutes(ctx) {
19143
19221
  res.status(500).json({ error: e.message });
19144
19222
  }
19145
19223
  });
19146
- app.post("/api/commands", async (req, res) => {
19224
+ app.post("/api/commands", requireAuth(), async (req, res) => {
19147
19225
  try {
19148
19226
  const { commandType, payload } = req.body;
19149
19227
  const cmd = kernelContainer.commandBus.createCommand(
@@ -20860,7 +20938,7 @@ function registerAdminRoutes(ctx) {
20860
20938
  runGeminiAgentChat: runGeminiAgentChat2,
20861
20939
  runOpenAIAgentChat: runOpenAIAgentChat2
20862
20940
  } = ctx;
20863
- app.post("/api/admin/seed-demo", (req, res) => {
20941
+ app.post("/api/admin/seed-demo", requireAuth("administrator"), (req, res) => {
20864
20942
  try {
20865
20943
  const db2 = kernelContainer.db;
20866
20944
  const DEMO_CLASS_ID = "demo-class";
@@ -20876,7 +20954,7 @@ function registerAdminRoutes(ctx) {
20876
20954
  db2.prepare("INSERT INTO classes (id, name, description, created_at) VALUES (?, ?, ?, ?)").run(
20877
20955
  DEMO_CLASS_ID,
20878
20956
  "\u4EBA\u5DE5\u667A\u80FD\u4E0E\u521B\u610F\u7F16\u7A0B\u793A\u8303\u73ED",
20879
- "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C\uFFFD?",
20957
+ "\u8FD9\u662F\u7CFB\u7EDF\u521D\u59CB\u5316\u7684\u793A\u4F8B\u8BFE\u7A0B\u73ED\u7EA7\uFF0C\u7528\u4E8E\u6559\u5B66\u4F53\u9A8C?",
20880
20958
  Date.now()
20881
20959
  );
20882
20960
  }
@@ -20904,7 +20982,7 @@ function registerAdminRoutes(ctx) {
20904
20982
  lessonId = "demo-lesson";
20905
20983
  db2.prepare("INSERT INTO lessons (id, title, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(
20906
20984
  lessonId,
20907
- "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16\uFFFD?",
20985
+ "\u521D\u8BC6 Python\uFF1A\u667A\u80FD\u767D\u677F\u521B\u610F\u7F16?",
20908
20986
  JSON.stringify({ elements: [] }),
20909
20987
  Date.now(),
20910
20988
  Date.now()
@@ -20926,7 +21004,7 @@ function registerAdminRoutes(ctx) {
20926
21004
  res.status(500).json({ error: e.message });
20927
21005
  }
20928
21006
  });
20929
- app.post("/api/classes/import", (req, res) => {
21007
+ app.post("/api/classes/import", requireAuth("teacher", "administrator"), (req, res) => {
20930
21008
  try {
20931
21009
  const { classes } = req.body;
20932
21010
  if (!classes || !Array.isArray(classes)) {
@@ -20976,7 +21054,7 @@ function registerAdminRoutes(ctx) {
20976
21054
  res.status(500).json({ error: e.message });
20977
21055
  }
20978
21056
  });
20979
- app.post("/api/students/import", (req, res) => {
21057
+ app.post("/api/students/import", requireAuth("teacher", "administrator"), (req, res) => {
20980
21058
  try {
20981
21059
  const { students } = req.body;
20982
21060
  if (!students || !Array.isArray(students)) {
@@ -21575,16 +21653,16 @@ function registerRosterRoutes(ctx) {
21575
21653
  res.status(550).json({ error: e.message });
21576
21654
  }
21577
21655
  });
21578
- app.get("/api/users", async (req, res) => {
21656
+ app.get("/api/users", requireAuth("administrator"), async (req, res) => {
21579
21657
  try {
21580
- const cmd = kernelContainer.commandBus.createCommand("user.list", {}, "user-demo");
21658
+ const cmd = kernelContainer.commandBus.createCommand("user.list", {}, getActorId(req));
21581
21659
  const users = await kernelContainer.commandBus.execute(cmd);
21582
21660
  res.json(users);
21583
21661
  } catch (e) {
21584
21662
  res.status(550).json({ error: e.message });
21585
21663
  }
21586
21664
  });
21587
- app.post("/api/users", async (req, res) => {
21665
+ app.post("/api/users", requireAuth("administrator"), async (req, res) => {
21588
21666
  try {
21589
21667
  const { username, password, role, name, status = "active" } = req.body;
21590
21668
  const cmd = kernelContainer.commandBus.createCommand("user.create", {
@@ -21593,14 +21671,14 @@ function registerRosterRoutes(ctx) {
21593
21671
  role,
21594
21672
  name,
21595
21673
  status
21596
- }, "user-demo");
21674
+ }, getActorId(req));
21597
21675
  const result = await kernelContainer.commandBus.execute(cmd);
21598
21676
  res.json(result);
21599
21677
  } catch (e) {
21600
21678
  res.status(550).json({ error: e.message });
21601
21679
  }
21602
21680
  });
21603
- app.put("/api/users/:id", async (req, res) => {
21681
+ app.put("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21604
21682
  try {
21605
21683
  const { username, role, name, password, status } = req.body;
21606
21684
  const cmd = kernelContainer.commandBus.createCommand("user.update", {
@@ -21610,18 +21688,18 @@ function registerRosterRoutes(ctx) {
21610
21688
  name,
21611
21689
  password,
21612
21690
  status
21613
- }, "user-demo");
21691
+ }, getActorId(req));
21614
21692
  const result = await kernelContainer.commandBus.execute(cmd);
21615
21693
  res.json(result);
21616
21694
  } catch (e) {
21617
21695
  res.status(550).json({ error: e.message });
21618
21696
  }
21619
21697
  });
21620
- app.delete("/api/users/:id", async (req, res) => {
21698
+ app.delete("/api/users/:id", requireAuth("administrator"), async (req, res) => {
21621
21699
  try {
21622
21700
  const cmd = kernelContainer.commandBus.createCommand("user.delete", {
21623
21701
  userId: req.params.id
21624
- }, "user-demo");
21702
+ }, getActorId(req));
21625
21703
  const result = await kernelContainer.commandBus.execute(cmd);
21626
21704
  res.json(result);
21627
21705
  } catch (e) {
@@ -21636,7 +21714,7 @@ function registerRosterRoutes(ctx) {
21636
21714
  res.status(500).json({ error: e.message });
21637
21715
  }
21638
21716
  });
21639
- app.post("/api/labs", (req, res) => {
21717
+ app.post("/api/labs", requireAuth("teacher", "administrator"), (req, res) => {
21640
21718
  try {
21641
21719
  const { room_number, rows, cols } = req.body;
21642
21720
  const id = "lab_" + Math.random().toString(36).slice(2, 10);
@@ -21648,7 +21726,7 @@ function registerRosterRoutes(ctx) {
21648
21726
  res.status(500).json({ error: e.message });
21649
21727
  }
21650
21728
  });
21651
- app.put("/api/labs/:id", (req, res) => {
21729
+ app.put("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21652
21730
  try {
21653
21731
  const { room_number, rows, cols } = req.body;
21654
21732
  kernelContainer.db.prepare(
@@ -21659,7 +21737,7 @@ function registerRosterRoutes(ctx) {
21659
21737
  res.status(500).json({ error: e.message });
21660
21738
  }
21661
21739
  });
21662
- app.delete("/api/labs/:id", (req, res) => {
21740
+ app.delete("/api/labs/:id", requireAuth("teacher", "administrator"), (req, res) => {
21663
21741
  try {
21664
21742
  kernelContainer.db.prepare("DELETE FROM computer_labs WHERE id = ?").run(req.params.id);
21665
21743
  kernelContainer.db.prepare("DELETE FROM student_seats WHERE lab_id = ?").run(req.params.id);
@@ -21678,7 +21756,7 @@ function registerRosterRoutes(ctx) {
21678
21756
  res.status(500).json({ error: e.message });
21679
21757
  }
21680
21758
  });
21681
- app.post("/api/classes/:classId/seats", (req, res) => {
21759
+ app.post("/api/classes/:classId/seats", requireAuth("teacher", "administrator"), (req, res) => {
21682
21760
  try {
21683
21761
  const { lab_id, seats } = req.body;
21684
21762
  kernelContainer.db.prepare("UPDATE classes SET lab_id = ? WHERE id = ?").run(lab_id || null, req.params.classId);
@@ -21876,7 +21954,7 @@ function registerRosterRoutes(ctx) {
21876
21954
  res.status(500).json({ error: e.message });
21877
21955
  }
21878
21956
  });
21879
- app.post("/api/classes/:id/students/bulk-enroll", (req, res) => {
21957
+ app.post("/api/classes/:id/students/bulk-enroll", requireAuth("teacher", "administrator"), (req, res) => {
21880
21958
  try {
21881
21959
  const { students } = req.body;
21882
21960
  const classId = req.params.id;
@@ -23058,7 +23136,7 @@ function registerGradingRoutes(ctx) {
23058
23136
  if (!lessonId || !studentId || grade === void 0) {
23059
23137
  return res.status(400).json({ success: false, error: "lessonId, studentId, and grade are required" });
23060
23138
  }
23061
- const gradeService = await kernelContainer.registry.resolve(ISemesterGradeServiceToken);
23139
+ const gradeService = await kernelContainer.serviceRegistry.resolve(ISemesterGradeServiceToken);
23062
23140
  await gradeService.saveSemesterGrade(lessonId, studentId, Math.round(Number(grade)));
23063
23141
  res.json({ success: true });
23064
23142
  } catch (e) {
@@ -23067,7 +23145,7 @@ function registerGradingRoutes(ctx) {
23067
23145
  });
23068
23146
  app.get("/api/classes/:classId/points-dimensions", async (req, res) => {
23069
23147
  try {
23070
- const dimensionRegistry = await kernelContainer.registry.resolve(IPointsDimensionRegistryToken);
23148
+ const dimensionRegistry = await kernelContainer.serviceRegistry.resolve(IPointsDimensionRegistryToken);
23071
23149
  const dimensions = dimensionRegistry.listDimensions();
23072
23150
  res.json({ success: true, dimensions });
23073
23151
  } catch (e) {
@@ -23084,7 +23162,7 @@ function registerGradingRoutes(ctx) {
23084
23162
  if (!classId || !dimensionId || deltaPoints === void 0 || !reason) {
23085
23163
  return res.status(400).json({ success: false, error: "classId, dimensionId, deltaPoints, and reason are required" });
23086
23164
  }
23087
- const ledgerService = await kernelContainer.registry.resolve(IPointsLedgerServiceToken);
23165
+ const ledgerService = await kernelContainer.serviceRegistry.resolve(IPointsLedgerServiceToken);
23088
23166
  const logItem = await ledgerService.addPoints(studentId, classId, dimensionId, Number(deltaPoints), reason, pluginId);
23089
23167
  kernelContainer.eventBus.publish({
23090
23168
  id: logItem.id,
@@ -23102,7 +23180,7 @@ function registerGradingRoutes(ctx) {
23102
23180
  try {
23103
23181
  const { studentId } = req.params;
23104
23182
  const { classId } = req.query;
23105
- const ledgerService = await kernelContainer.registry.resolve(IPointsLedgerServiceToken);
23183
+ const ledgerService = await kernelContainer.serviceRegistry.resolve(IPointsLedgerServiceToken);
23106
23184
  const logs = await ledgerService.getLogs(studentId, classId);
23107
23185
  const summary = await ledgerService.getStudentDimensionSummary(studentId, classId || "");
23108
23186
  res.json({ success: true, logs, summary });
@@ -23421,6 +23499,28 @@ async function checkVersion(source, installedVersion) {
23421
23499
  }
23422
23500
 
23423
23501
  // server/routes/plugins.ts
23502
+ function isSafeExternalUrl(urlStr) {
23503
+ try {
23504
+ const parsed = new URL(urlStr);
23505
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
23506
+ return { safe: false, reason: "Only HTTP and HTTPS protocols are allowed" };
23507
+ }
23508
+ const hostname = parsed.hostname.toLowerCase();
23509
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname === "0.0.0.0" || hostname === "::1" || hostname === "[::1]") {
23510
+ return { safe: false, reason: "Access to loopback/local addresses is forbidden" };
23511
+ }
23512
+ const ipv4Match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
23513
+ if (ipv4Match) {
23514
+ const octets = ipv4Match.slice(1).map(Number);
23515
+ if (octets[0] === 127 || octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168 || octets[0] === 169 && octets[1] === 254 || octets[0] === 0 || octets[0] >= 224) {
23516
+ return { safe: false, reason: "Access to private or link-local IP addresses is forbidden" };
23517
+ }
23518
+ }
23519
+ return { safe: true };
23520
+ } catch (e) {
23521
+ return { safe: false, reason: `Invalid URL format: ${e.message}` };
23522
+ }
23523
+ }
23424
23524
  function registerPluginsRoutes(ctx) {
23425
23525
  const {
23426
23526
  app,
@@ -23568,12 +23668,19 @@ function registerPluginsRoutes(ctx) {
23568
23668
  res.status(500).json({ success: false, error: e.message });
23569
23669
  }
23570
23670
  });
23571
- app.post("/api/plugins/:id(*)/one-click-update", async (req, res) => {
23671
+ app.post("/api/plugins/:id(*)/one-click-update", requireAuth("administrator"), async (req, res) => {
23572
23672
  try {
23573
23673
  const targetPluginId = decodeURIComponent(req.params.id);
23574
23674
  const { downloadUrl } = req.body || {};
23575
23675
  let zipBuffer;
23576
23676
  if (downloadUrl) {
23677
+ const urlCheck = isSafeExternalUrl(downloadUrl);
23678
+ if (!urlCheck.safe) {
23679
+ return res.status(400).json({
23680
+ success: false,
23681
+ error: `\u5B89\u5168\u62E6\u622A: \u975E\u6CD5\u4E0B\u8F7D\u5730\u5740 (${urlCheck.reason})`
23682
+ });
23683
+ }
23577
23684
  try {
23578
23685
  const resp = await fetch(downloadUrl, {
23579
23686
  headers: { "User-Agent": "OpenLearnV2-PluginUpdater/1.0" },
@@ -23651,7 +23758,7 @@ function registerPluginsRoutes(ctx) {
23651
23758
  res.status(500).json({ success: false, error: e.message });
23652
23759
  }
23653
23760
  });
23654
- app.post("/api/plugins/:id(*)/config", (req, res) => {
23761
+ app.post("/api/plugins/:id(*)/config", requireAuth("administrator"), (req, res) => {
23655
23762
  try {
23656
23763
  const rawId = decodeURIComponent(req.params.id);
23657
23764
  const pluginId = kernelContainer.pluginHost.resolvePluginUuid(rawId);
@@ -23670,7 +23777,7 @@ function registerPluginsRoutes(ctx) {
23670
23777
  res.status(500).json({ success: false, error: e.message });
23671
23778
  }
23672
23779
  });
23673
- app.post("/api/plugins/:id(*)/toggle", async (req, res) => {
23780
+ app.post("/api/plugins/:id(*)/toggle", requireAuth("administrator"), async (req, res) => {
23674
23781
  try {
23675
23782
  const rawId = decodeURIComponent(req.params.id);
23676
23783
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23684,7 +23791,7 @@ function registerPluginsRoutes(ctx) {
23684
23791
  res.status(500).json({ success: false, error: err.message });
23685
23792
  }
23686
23793
  });
23687
- app.delete("/api/plugins/:id(*)", async (req, res) => {
23794
+ app.delete("/api/plugins/:id(*)", requireAuth("administrator"), async (req, res) => {
23688
23795
  try {
23689
23796
  const rawId = decodeURIComponent(req.params.id);
23690
23797
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23712,7 +23819,7 @@ function registerPluginsRoutes(ctx) {
23712
23819
  res.status(404).json({ success: false, error: err.message });
23713
23820
  }
23714
23821
  });
23715
- app.post("/api/plugins", async (req, res) => {
23822
+ app.post("/api/plugins", requireAuth("administrator"), async (req, res) => {
23716
23823
  try {
23717
23824
  const { sourceCode } = req.body;
23718
23825
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23727,7 +23834,7 @@ function registerPluginsRoutes(ctx) {
23727
23834
  res.status(500).json({ success: false, error: err.message });
23728
23835
  }
23729
23836
  });
23730
- app.post("/api/plugins/upload-zip", async (req, res) => {
23837
+ app.post("/api/plugins/upload-zip", requireAuth("administrator"), async (req, res) => {
23731
23838
  try {
23732
23839
  const { base64Data, filename, executionMode } = req.body;
23733
23840
  const cmd = kernelContainer.commandBus.createCommand(
@@ -23742,7 +23849,7 @@ function registerPluginsRoutes(ctx) {
23742
23849
  res.status(500).json({ success: false, error: err.message });
23743
23850
  }
23744
23851
  });
23745
- app.post("/api/plugins/upload-zip-raw", import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23852
+ app.post("/api/plugins/upload-zip-raw", requireAuth("administrator"), import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }), async (req, res) => {
23746
23853
  try {
23747
23854
  const zipBuffer = req.body;
23748
23855
  const filename = req.headers["x-filename"] ? decodeURIComponent(req.headers["x-filename"]) : "plugin.zip";
@@ -23786,6 +23893,7 @@ function registerPluginsRoutes(ctx) {
23786
23893
  });
23787
23894
  app.post(
23788
23895
  "/api/plugins/:id(*)/update-zip-raw",
23896
+ requireAuth("administrator"),
23789
23897
  import_express2.default.raw({ type: "application/octet-stream", limit: "400mb" }),
23790
23898
  async (req, res) => {
23791
23899
  try {
@@ -23872,7 +23980,7 @@ function registerPluginsRoutes(ctx) {
23872
23980
  res.status(500).json({ error: e.message });
23873
23981
  }
23874
23982
  });
23875
- app.post("/api/ai-providers", (req, res) => {
23983
+ app.post("/api/ai-providers", requireAuth("administrator"), (req, res) => {
23876
23984
  try {
23877
23985
  const { name, api_url, api_key, model_name } = req.body;
23878
23986
  if (!name || !api_url || !model_name) {
@@ -23887,7 +23995,7 @@ function registerPluginsRoutes(ctx) {
23887
23995
  res.status(500).json({ error: e.message });
23888
23996
  }
23889
23997
  });
23890
- app.put("/api/ai-providers/:id", (req, res) => {
23998
+ app.put("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23891
23999
  try {
23892
24000
  const { name, api_url, api_key, model_name } = req.body;
23893
24001
  if (!name || !api_url || !model_name) {
@@ -23907,7 +24015,7 @@ function registerPluginsRoutes(ctx) {
23907
24015
  res.status(500).json({ error: e.message });
23908
24016
  }
23909
24017
  });
23910
- app.delete("/api/ai-providers/:id", (req, res) => {
24018
+ app.delete("/api/ai-providers/:id", requireAuth("administrator"), (req, res) => {
23911
24019
  try {
23912
24020
  kernelContainer.db.prepare("DELETE FROM ai_providers WHERE id = ?").run(req.params.id);
23913
24021
  res.json({ success: true });
@@ -23927,7 +24035,7 @@ function registerPluginsRoutes(ctx) {
23927
24035
  res.status(500).json({ error: e.message });
23928
24036
  }
23929
24037
  });
23930
- app.put("/api/site-settings", (req, res) => {
24038
+ app.put("/api/site-settings", requireAuth("administrator"), (req, res) => {
23931
24039
  try {
23932
24040
  const { siteName, slogan, logoUrl } = req.body || {};
23933
24041
  kernelContainer.db.prepare(
@@ -23942,7 +24050,7 @@ function registerPluginsRoutes(ctx) {
23942
24050
  res.status(500).json({ error: e.message });
23943
24051
  }
23944
24052
  });
23945
- app.post("/api/ai-providers/test", async (req, res) => {
24053
+ app.post("/api/ai-providers/test", requireAuth("administrator"), async (req, res) => {
23946
24054
  try {
23947
24055
  const { api_url, api_key: providedKey, model_name } = req.body;
23948
24056
  if (!api_url || !model_name) {
@@ -23963,6 +24071,10 @@ function registerPluginsRoutes(ctx) {
23963
24071
  if (!cleanUrl.endsWith("/chat/completions")) {
23964
24072
  cleanUrl = cleanUrl.endsWith("/") ? cleanUrl + "chat/completions" : cleanUrl + "/chat/completions";
23965
24073
  }
24074
+ const urlSafety = isSafeExternalUrl(cleanUrl);
24075
+ if (!urlSafety.safe) {
24076
+ return res.status(400).json({ error: `Blocked unsafe AI provider URL: ${urlSafety.reason}` });
24077
+ }
23966
24078
  const response = await fetch(cleanUrl, {
23967
24079
  method: "POST",
23968
24080
  headers: {
@@ -24043,8 +24155,8 @@ async function startServer() {
24043
24155
  standardHeaders: true,
24044
24156
  legacyHeaders: false
24045
24157
  });
24046
- app.use(import_express3.default.json({ limit: "400mb" }));
24047
- app.use(import_express3.default.urlencoded({ limit: "400mb", extended: true }));
24158
+ app.use(import_express3.default.json({ limit: "10mb" }));
24159
+ app.use(import_express3.default.urlencoded({ limit: "10mb", extended: true }));
24048
24160
  app.use("/uploads", import_express3.default.static(import_path14.default.join(process.cwd(), "uploads")));
24049
24161
  app.use("/plugins", import_express3.default.static(import_path14.default.join(process.cwd(), "plugins")));
24050
24162
  app.use((req, res, next) => {