openlearn-next 0.4.2 → 0.7.3

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 (149) hide show
  1. package/README.md +26 -21
  2. package/cli-data.mjs +535 -40
  3. package/cli-doctor.mjs +456 -17
  4. package/cli.mjs +214 -12
  5. package/dist/assets/AcademicYearFilter-DUUGpDKt.js +1 -0
  6. package/dist/assets/ActivityWorkspaceWidget-5PzyxF6a.js +1 -0
  7. package/dist/assets/AdminDirectoryView-BCtmQTEK.js +5 -0
  8. package/dist/assets/AssessmentCenter-B43ojHG-.js +1 -0
  9. package/dist/assets/BatchPickerModal-CbmjInp7.js +1 -0
  10. package/dist/assets/ClassesView-DEnMaDOt.js +32 -0
  11. package/dist/assets/ClassroomCountdownWidget-CHq4983w.js +2 -0
  12. package/dist/assets/CloudDriveModal-D2t3Uyzr.js +1 -0
  13. package/dist/assets/ComputerLabView-YtnoT5Rb.js +1 -0
  14. package/dist/assets/CourseManagement-DOXyJ_j-.js +1 -0
  15. package/dist/assets/CourseWizardModal-Dbi6Caw2.js +3 -0
  16. package/dist/assets/CoursewareHubPanel-CyxDIJAF.js +1 -0
  17. package/dist/assets/Dashboard-2rLu_ZBy.js +8 -0
  18. package/dist/assets/ExportWeightModal-BrmAh6VX.js +1 -0
  19. package/dist/assets/GLTFLoader-CZJbo_y1.js +1 -0
  20. package/dist/assets/HelpTour-D_q1z_MI.js +1 -0
  21. package/dist/assets/HelpView-CVBrKDrd.js +204 -0
  22. package/dist/assets/ImportLessonsModal-PhHtX31R.js +1 -0
  23. package/dist/assets/ImportModal-DqjqNeH4.js +2 -0
  24. package/dist/assets/InteractiveCoursewareViewer-Vi6lLz7a.js +1 -0
  25. package/dist/assets/InteractiveWhiteboard-lTzeayX5.js +65 -0
  26. package/dist/assets/LazyCourseware-KIt0rGtW.js +2 -0
  27. package/dist/assets/LazyWhiteboard-CCN3pYcW.js +2 -0
  28. package/dist/assets/LessonEditorView-D_GVhHuM.js +1 -0
  29. package/dist/assets/LiveClassroomView-BRsZ6QEq.js +61 -0
  30. package/dist/assets/NotificationDetailModal-tY5rxYCN.js +1 -0
  31. package/dist/assets/OrbitControls-CQjN_uwS.js +1 -0
  32. package/dist/assets/PluginView-CedpAW6d.js +77 -0
  33. package/dist/assets/ProcessLogsModal-Cfr-T9Gd.js +1 -0
  34. package/dist/assets/QuizGeneratorModal-bUA002kP.js +1 -0
  35. package/dist/assets/StudentAssignmentView-BhAz6Hfk.js +1 -0
  36. package/dist/assets/StudentLessonView-DC1yX4kG.js +1 -0
  37. package/dist/assets/StudentView-PHKxIV9T.js +2 -0
  38. package/dist/assets/SystemResourceLibraryModal-DgXYe6_x.js +1 -0
  39. package/dist/assets/TeacherView-DscJtOJ9.js +2 -0
  40. package/dist/assets/TimetableView-D2ozoj_D.js +6 -0
  41. package/dist/assets/UTIF-FfCsrHhe.js +1 -0
  42. package/dist/assets/__vite-optional-peer-dep_ai_ooxml-ui-BIHI7g3E.js +1 -0
  43. package/dist/assets/browser-DEI0QxZC.js +1 -0
  44. package/dist/assets/html2canvas-pro.esm-Bo50djkB.js +12 -0
  45. package/dist/assets/index-2676X8YB.js +131 -0
  46. package/dist/assets/index-C6hlh8pw.css +1 -0
  47. package/dist/assets/{index.es-C5eWEO4o.js → index.es-DyEF0CZ9.js} +1 -1
  48. package/dist/assets/pluginParsers-e4PSm2Iy.js +1 -0
  49. package/dist/assets/react_pptx-react-viewer-BIHI7g3E.js +1 -0
  50. package/dist/assets/teaching-modes-client-BeVaDdJ-.js +1 -0
  51. package/dist/assets/three.module-iOYB3rD4.js +4228 -0
  52. package/dist/assets/timeline-duration-BgdJCSrW.js +1 -0
  53. package/dist/assets/{vendor-charts-qLbgF1eL.js → vendor-charts-SrpBsvM3.js} +2 -2
  54. package/dist/assets/{vendor-icons-BRmhY6fg.js → vendor-icons-CXrZ3R2V.js} +2 -2
  55. package/dist/assets/{vendor-konva-CEOq4dcl.js → vendor-konva-Dne0Z-WC.js} +1 -1
  56. package/dist/assets/{vendor-pdf-D7rGevI1.js → vendor-pdf-C1Vh2Aqq.js} +56 -56
  57. package/dist/assets/vendor-pptx-Bzn6whfK.js +11311 -0
  58. package/dist/assets/vendor-pptx-DIWdXF1L.css +1 -0
  59. package/dist/assets/{vendor-react-B0t7H3hh.js → vendor-react-Kv_JATwr.js} +1 -1
  60. package/dist/assets/vendor-utils-aM7aYvPP.js +1 -0
  61. package/dist/cli-migrator.cjs +310 -0
  62. package/dist/env-validation.cjs +351 -0
  63. package/dist/index.html +13 -10
  64. package/dist/plugin-net-preload.cjs +263 -0
  65. package/dist/server.cjs +51140 -27229
  66. package/migrations/000_initial_schema.sql +410 -0
  67. package/migrations/001_add_execution_mode.sql +6 -0
  68. package/migrations/002_add_client_session_expiry.sql +6 -0
  69. package/migrations/003_classroom_runtime.sql +33 -0
  70. package/migrations/004_courseware_score_config.sql +26 -0
  71. package/migrations/005_assignment_hub.sql +155 -0
  72. package/migrations/006_classroom_event_bus.sql +28 -0
  73. package/migrations/007_interactive_classroom.sql +119 -0
  74. package/migrations/008_teaching_modes.sql +36 -0
  75. package/migrations/009_classroom_peer_review.sql +159 -0
  76. package/migrations/010_class_groups.sql +33 -0
  77. package/migrations/011_classroom_feed.sql +34 -0
  78. package/migrations/012_auto_record_score.sql +48 -0
  79. package/migrations/013_score_source_strategy.sql +81 -0
  80. package/migrations/014_performance_indexes.sql +21 -0
  81. package/migrations/015_demo_data_registry.sql +26 -0
  82. package/migrations/016_preset_polls_and_passcode_expiry.sql +33 -0
  83. package/migrations/017_pacing_signals_segment.sql +6 -0
  84. package/migrations/018_processes_plugin_owner.sql +26 -0
  85. package/migrations/019_plugins_version.sql +61 -0
  86. package/migrations/020_upload_max_file_mb.sql +14 -0
  87. package/migrations/021_class_owner_and_password_gate.sql +11 -0
  88. package/migrations/022_plugin_public_routes.sql +14 -0
  89. package/migrations/023_encrypt_class_passcodes.sql +18 -0
  90. package/migrations/024_segment_gates.sql +37 -0
  91. package/migrations/025_assignment_lookup_indexes.sql +11 -0
  92. package/migrations/026_plugin_grants.sql +21 -0
  93. package/migrations/027_academic_year.sql +26 -0
  94. package/migrations/028_classroom_indexes.sql +14 -0
  95. package/migrations/029_clean_lesson_think_artifacts.sql +13 -0
  96. package/migrations/030_backfill_academic_year.sql +30 -0
  97. package/migrations/031_assessment_core.sql +158 -0
  98. package/migrations/032_progress_verification.sql +17 -0
  99. package/migrations/033_student_lock_mode.sql +9 -0
  100. package/migrations/034_plugin_orphan_data.sql +27 -0
  101. package/migrations/035_icebreaker_checkins.sql +26 -0
  102. package/migrations/036_student_read_notifications_created_at.sql +19 -0
  103. package/migrations/037_plugin_config_scopes.sql +40 -0
  104. package/migrations/038_assessment_ai_grading_suggestion.sql +10 -0
  105. package/migrations/039_question_bank_sharing_and_papers.sql +14 -0
  106. package/migrations/040_assignment_grade_history.sql +37 -0
  107. package/migrations/041_course_package_idempotency.sql +33 -0
  108. package/migrations/042_assignment_grade_resubmit_audit.sql +12 -0
  109. package/migrations/043_mark_sha256_passwords.sql +31 -0
  110. package/migrations/README.md +61 -0
  111. package/migrations/schema-golden.json +640 -0
  112. package/package.json +54 -28
  113. package/dist/assets/AdminDirectoryView-DY--WM5Z.js +0 -1
  114. package/dist/assets/BatchPickerModal-BpWu0Lil.js +0 -1
  115. package/dist/assets/ClassesView-KbHEqJto.js +0 -22
  116. package/dist/assets/ClassroomCountdownWidget-96WFRO9A.js +0 -2
  117. package/dist/assets/CloudDriveModal-DEQ1nkNk.js +0 -1
  118. package/dist/assets/ComputerLabView-1qWDNRQ2.js +0 -1
  119. package/dist/assets/CourseManagement-D3ZpxY0l.js +0 -1
  120. package/dist/assets/CourseWizardModal-Ck_-M8pk.js +0 -3
  121. package/dist/assets/CoursewareHubPanel-CaEizhxl.js +0 -1
  122. package/dist/assets/Dashboard-CYbpbofV.js +0 -8
  123. package/dist/assets/ExportWeightModal-DW2bu9Zz.js +0 -1
  124. package/dist/assets/HelpTour-CMJbbGne.js +0 -1
  125. package/dist/assets/HelpView-CtzdqhBq.js +0 -204
  126. package/dist/assets/ImportLessonsModal-jBuIK453.js +0 -1
  127. package/dist/assets/ImportModal-D7L-KNhZ.js +0 -1
  128. package/dist/assets/InteractiveCoursewareViewer-Bj7ahXMs.js +0 -1
  129. package/dist/assets/InteractiveWhiteboard-B7JcJvDu.js +0 -77
  130. package/dist/assets/LazyCourseware-CuiPxhDg.js +0 -2
  131. package/dist/assets/LazyWhiteboard-BJwCEZAU.js +0 -2
  132. package/dist/assets/LessonEditorView-DFrOp2qp.js +0 -1
  133. package/dist/assets/LiveClassroomView-BZ5nGee3.js +0 -59
  134. package/dist/assets/NotificationDetailModal-Baqnc5pU.js +0 -1
  135. package/dist/assets/PluginView-CCbIuZ24.js +0 -66
  136. package/dist/assets/ProcessLogsModal-DmFXg9mG.js +0 -1
  137. package/dist/assets/QuizGeneratorModal-BBEDssp7.js +0 -1
  138. package/dist/assets/StudentAssignmentView-DgIjUsXz.js +0 -1
  139. package/dist/assets/StudentLessonView-CBJbI5x6.js +0 -1
  140. package/dist/assets/StudentPreviewModal-Bh8OZs0t.js +0 -1
  141. package/dist/assets/StudentView--uGxc5TJ.js +0 -2
  142. package/dist/assets/SystemResourceLibraryModal-BVCclcqA.js +0 -1
  143. package/dist/assets/TeacherView-D4Zsc0eZ.js +0 -2
  144. package/dist/assets/TimetableView-BQG-rEb5.js +0 -6
  145. package/dist/assets/index-BKBCBKvy.js +0 -217
  146. package/dist/assets/index-CvGu7LSj.css +0 -1
  147. package/dist/assets/purify.es-CYR4BTuT.js +0 -3
  148. package/dist/assets/vendor-pptx-C5-U7ieS.js +0 -39
  149. package/dist/assets/vendor-utils-m0Urvtws.js +0 -1
@@ -0,0 +1,410 @@
1
+ -- UP
2
+ -- OpenLearn Core Initial Schema
3
+
4
+ CREATE TABLE IF NOT EXISTS events (
5
+ id TEXT PRIMARY KEY,
6
+ type TEXT NOT NULL,
7
+ source TEXT NOT NULL,
8
+ payload TEXT NOT NULL,
9
+ timestamp INTEGER NOT NULL,
10
+ correlationId TEXT
11
+ );
12
+
13
+ CREATE TABLE IF NOT EXISTS lessons (
14
+ id TEXT PRIMARY KEY,
15
+ title TEXT NOT NULL,
16
+ content TEXT,
17
+ timeline TEXT,
18
+ progress_mode TEXT DEFAULT 'manual',
19
+ progress_conditions TEXT,
20
+ creator_id TEXT,
21
+ created_at INTEGER NOT NULL,
22
+ updated_at INTEGER NOT NULL
23
+ );
24
+
25
+ CREATE TABLE IF NOT EXISTS whiteboard_elements (
26
+ id TEXT PRIMARY KEY,
27
+ lesson_id TEXT NOT NULL,
28
+ type TEXT NOT NULL,
29
+ data TEXT NOT NULL,
30
+ created_at INTEGER NOT NULL
31
+ );
32
+
33
+ CREATE TABLE IF NOT EXISTS plugins (
34
+ id TEXT PRIMARY KEY,
35
+ name TEXT NOT NULL,
36
+ manifest TEXT NOT NULL,
37
+ source_code TEXT NOT NULL,
38
+ status TEXT NOT NULL,
39
+ created_at INTEGER NOT NULL,
40
+ loader_version TEXT DEFAULT 'vm',
41
+ zip_package BLOB,
42
+ file_path TEXT DEFAULT NULL,
43
+ updated_at INTEGER DEFAULT NULL
44
+ );
45
+
46
+ CREATE TABLE IF NOT EXISTS plugin_storage (
47
+ plugin_id TEXT NOT NULL,
48
+ key TEXT NOT NULL,
49
+ value TEXT NOT NULL,
50
+ updated_at INTEGER NOT NULL,
51
+ PRIMARY KEY (plugin_id, key)
52
+ );
53
+
54
+ CREATE TABLE IF NOT EXISTS pending_commands (
55
+ id TEXT PRIMARY KEY,
56
+ command_type TEXT NOT NULL,
57
+ payload TEXT NOT NULL,
58
+ actor_id TEXT NOT NULL,
59
+ created_at INTEGER NOT NULL
60
+ );
61
+
62
+ CREATE TABLE IF NOT EXISTS processes (
63
+ id TEXT PRIMARY KEY,
64
+ name TEXT NOT NULL,
65
+ status TEXT NOT NULL,
66
+ task_type TEXT,
67
+ payload TEXT,
68
+ state TEXT,
69
+ logs TEXT,
70
+ created_at INTEGER NOT NULL,
71
+ updated_at INTEGER NOT NULL
72
+ );
73
+
74
+ CREATE TABLE IF NOT EXISTS vfs_nodes (
75
+ id TEXT PRIMARY KEY,
76
+ parent_id TEXT,
77
+ type TEXT NOT NULL,
78
+ name TEXT NOT NULL,
79
+ content TEXT,
80
+ created_at INTEGER NOT NULL,
81
+ updated_at INTEGER NOT NULL
82
+ );
83
+
84
+ CREATE TABLE IF NOT EXISTS classes (
85
+ id TEXT PRIMARY KEY,
86
+ name TEXT NOT NULL,
87
+ description TEXT,
88
+ lab_id TEXT,
89
+ class_passcode TEXT,
90
+ created_at INTEGER NOT NULL
91
+ );
92
+
93
+ CREATE TABLE IF NOT EXISTS students (
94
+ id TEXT PRIMARY KEY,
95
+ student_number TEXT UNIQUE,
96
+ name TEXT NOT NULL,
97
+ email TEXT,
98
+ password TEXT,
99
+ locked_lesson_id TEXT,
100
+ private_notes TEXT,
101
+ avatar TEXT,
102
+ created_at INTEGER NOT NULL
103
+ );
104
+
105
+ CREATE TABLE IF NOT EXISTS class_students (
106
+ class_id TEXT NOT NULL,
107
+ student_id TEXT NOT NULL,
108
+ joined_at INTEGER NOT NULL,
109
+ PRIMARY KEY (class_id, student_id)
110
+ );
111
+
112
+ CREATE TABLE IF NOT EXISTS student_lesson_progress (
113
+ student_id TEXT NOT NULL,
114
+ lesson_id TEXT NOT NULL,
115
+ completed INTEGER NOT NULL DEFAULT 0,
116
+ progress_percent INTEGER NOT NULL DEFAULT 0,
117
+ completed_segments TEXT,
118
+ assigned_at INTEGER NOT NULL,
119
+ PRIMARY KEY (student_id, lesson_id)
120
+ );
121
+
122
+ CREATE TABLE IF NOT EXISTS assignments (
123
+ id TEXT PRIMARY KEY,
124
+ class_id TEXT NOT NULL,
125
+ lesson_id TEXT,
126
+ title TEXT NOT NULL,
127
+ description TEXT,
128
+ content TEXT,
129
+ created_at INTEGER NOT NULL
130
+ );
131
+
132
+ CREATE TABLE IF NOT EXISTS assignment_submissions (
133
+ assignment_id TEXT NOT NULL,
134
+ student_id TEXT NOT NULL,
135
+ content TEXT,
136
+ score INTEGER,
137
+ feedback TEXT,
138
+ submitted_at INTEGER NOT NULL,
139
+ graded_at INTEGER,
140
+ status TEXT NOT NULL DEFAULT 'submitted',
141
+ PRIMARY KEY (assignment_id, student_id)
142
+ );
143
+
144
+ CREATE TABLE IF NOT EXISTS schedules (
145
+ id TEXT PRIMARY KEY,
146
+ class_id TEXT NOT NULL,
147
+ lesson_id TEXT NOT NULL,
148
+ scheduled_date TEXT NOT NULL,
149
+ time_slot TEXT,
150
+ status TEXT DEFAULT 'scheduled',
151
+ notes TEXT,
152
+ created_at INTEGER NOT NULL
153
+ );
154
+
155
+ CREATE TABLE IF NOT EXISTS attendance (
156
+ schedule_id TEXT NOT NULL,
157
+ student_id TEXT NOT NULL,
158
+ status TEXT NOT NULL,
159
+ recorded_at INTEGER NOT NULL,
160
+ PRIMARY KEY (schedule_id, student_id)
161
+ );
162
+
163
+ CREATE TABLE IF NOT EXISTS system_resources (
164
+ id TEXT PRIMARY KEY,
165
+ name TEXT NOT NULL,
166
+ type TEXT NOT NULL,
167
+ content TEXT,
168
+ created_at INTEGER NOT NULL
169
+ );
170
+
171
+ CREATE TABLE IF NOT EXISTS computer_labs (
172
+ id TEXT PRIMARY KEY,
173
+ room_number TEXT NOT NULL,
174
+ rows INTEGER NOT NULL,
175
+ cols INTEGER NOT NULL,
176
+ created_at INTEGER NOT NULL
177
+ );
178
+
179
+ CREATE TABLE IF NOT EXISTS student_seats (
180
+ class_id TEXT NOT NULL,
181
+ student_id TEXT NOT NULL,
182
+ lab_id TEXT NOT NULL,
183
+ row_idx INTEGER NOT NULL,
184
+ col_idx INTEGER NOT NULL,
185
+ PRIMARY KEY (class_id, student_id)
186
+ );
187
+
188
+ CREATE TABLE IF NOT EXISTS users (
189
+ id TEXT PRIMARY KEY,
190
+ username TEXT UNIQUE NOT NULL,
191
+ password_hash TEXT NOT NULL,
192
+ role TEXT NOT NULL,
193
+ name TEXT NOT NULL,
194
+ status TEXT DEFAULT 'active',
195
+ avatar TEXT,
196
+ created_at INTEGER NOT NULL
197
+ );
198
+
199
+ CREATE TABLE IF NOT EXISTS client_sessions (
200
+ id TEXT PRIMARY KEY,
201
+ session_data TEXT NOT NULL,
202
+ updated_at INTEGER NOT NULL
203
+ );
204
+
205
+ CREATE TABLE IF NOT EXISTS student_read_notifications (
206
+ student_id TEXT NOT NULL,
207
+ notification_id TEXT NOT NULL,
208
+ PRIMARY KEY (student_id, notification_id)
209
+ );
210
+
211
+ CREATE TABLE IF NOT EXISTS ai_providers (
212
+ id TEXT PRIMARY KEY,
213
+ name TEXT NOT NULL,
214
+ api_url TEXT NOT NULL,
215
+ api_key TEXT,
216
+ model_name TEXT NOT NULL,
217
+ created_at INTEGER NOT NULL,
218
+ updated_at INTEGER NOT NULL
219
+ );
220
+
221
+ CREATE TABLE IF NOT EXISTS exams (
222
+ id TEXT PRIMARY KEY,
223
+ class_id TEXT NOT NULL,
224
+ title TEXT NOT NULL,
225
+ description TEXT,
226
+ max_score INTEGER NOT NULL DEFAULT 100,
227
+ created_at INTEGER NOT NULL
228
+ );
229
+
230
+ CREATE TABLE IF NOT EXISTS exam_scores (
231
+ exam_id TEXT NOT NULL,
232
+ student_id TEXT NOT NULL,
233
+ score REAL,
234
+ notes TEXT,
235
+ recorded_at INTEGER NOT NULL,
236
+ PRIMARY KEY (exam_id, student_id)
237
+ );
238
+
239
+ CREATE TABLE IF NOT EXISTS class_grade_weights (
240
+ class_id TEXT PRIMARY KEY,
241
+ attendance_weight REAL NOT NULL DEFAULT 0.15,
242
+ progress_weight REAL NOT NULL DEFAULT 0.25,
243
+ assignment_weight REAL NOT NULL DEFAULT 0.35,
244
+ exam_weight REAL NOT NULL DEFAULT 0.25,
245
+ updated_at INTEGER NOT NULL
246
+ );
247
+
248
+ CREATE TABLE IF NOT EXISTS student_semester_reports (
249
+ id TEXT PRIMARY KEY,
250
+ student_id TEXT NOT NULL,
251
+ class_id TEXT NOT NULL,
252
+ semester_name TEXT NOT NULL,
253
+ attendance_score REAL NOT NULL,
254
+ progress_score REAL NOT NULL,
255
+ assignment_score REAL NOT NULL,
256
+ exam_score REAL NOT NULL,
257
+ total_score REAL NOT NULL,
258
+ grade_level TEXT NOT NULL,
259
+ teacher_evaluation TEXT,
260
+ ai_evaluation TEXT,
261
+ dimension_scores TEXT,
262
+ created_at INTEGER NOT NULL,
263
+ updated_at INTEGER NOT NULL,
264
+ UNIQUE(student_id, class_id, semester_name)
265
+ );
266
+
267
+ CREATE TABLE IF NOT EXISTS student_point_logs (
268
+ id TEXT PRIMARY KEY,
269
+ student_id TEXT NOT NULL,
270
+ class_id TEXT NOT NULL,
271
+ dimension_id TEXT NOT NULL,
272
+ plugin_id TEXT,
273
+ delta_points REAL NOT NULL,
274
+ reason TEXT NOT NULL,
275
+ created_at INTEGER NOT NULL
276
+ );
277
+
278
+ CREATE TABLE IF NOT EXISTS courseware (
279
+ id TEXT PRIMARY KEY,
280
+ uuid TEXT UNIQUE NOT NULL,
281
+ name TEXT NOT NULL,
282
+ type TEXT,
283
+ entry TEXT NOT NULL,
284
+ created_at INTEGER NOT NULL
285
+ );
286
+
287
+ CREATE TABLE IF NOT EXISTS courseware_attempt (
288
+ id TEXT PRIMARY KEY,
289
+ courseware_id TEXT NOT NULL,
290
+ student_id TEXT NOT NULL,
291
+ started_at INTEGER NOT NULL,
292
+ finished_at INTEGER,
293
+ status TEXT NOT NULL
294
+ );
295
+
296
+ CREATE TABLE IF NOT EXISTS submission_raw (
297
+ id TEXT PRIMARY KEY,
298
+ attempt_id TEXT NOT NULL,
299
+ event_type TEXT NOT NULL,
300
+ payload_json TEXT NOT NULL,
301
+ created_at INTEGER NOT NULL
302
+ );
303
+
304
+ CREATE TABLE IF NOT EXISTS submission_result (
305
+ id TEXT PRIMARY KEY,
306
+ attempt_id TEXT NOT NULL,
307
+ score REAL,
308
+ comment TEXT,
309
+ completion REAL,
310
+ extra_json TEXT
311
+ );
312
+
313
+ CREATE TABLE IF NOT EXISTS mfe_remotes (
314
+ name TEXT PRIMARY KEY,
315
+ entry TEXT NOT NULL,
316
+ meta TEXT DEFAULT '{}',
317
+ created_at TEXT DEFAULT (datetime('now')),
318
+ updated_at TEXT DEFAULT (datetime('now'))
319
+ );
320
+
321
+ CREATE TABLE IF NOT EXISTS plugin_submissions (
322
+ id TEXT PRIMARY KEY,
323
+ lesson_id TEXT NOT NULL,
324
+ student_id TEXT NOT NULL,
325
+ file_path TEXT NOT NULL,
326
+ version INTEGER NOT NULL DEFAULT 1,
327
+ created_at INTEGER NOT NULL,
328
+ updated_at INTEGER NOT NULL,
329
+ UNIQUE(lesson_id, student_id)
330
+ );
331
+
332
+ CREATE TABLE IF NOT EXISTS plugin_peer_reviews (
333
+ id TEXT PRIMARY KEY,
334
+ submission_id TEXT NOT NULL,
335
+ reviewer_id TEXT NOT NULL,
336
+ score INTEGER NOT NULL,
337
+ comment TEXT,
338
+ created_at INTEGER NOT NULL,
339
+ UNIQUE(submission_id, reviewer_id)
340
+ );
341
+
342
+ CREATE TABLE IF NOT EXISTS plugin_grades (
343
+ id TEXT PRIMARY KEY,
344
+ submission_id TEXT NOT NULL UNIQUE,
345
+ teacher_score INTEGER,
346
+ teacher_comment TEXT,
347
+ teacher_weight REAL NOT NULL DEFAULT 0.6,
348
+ peer_weight REAL NOT NULL DEFAULT 0.4,
349
+ calculated_final_score INTEGER,
350
+ status TEXT NOT NULL DEFAULT 'draft',
351
+ graded_at INTEGER
352
+ );
353
+
354
+ -- Performance Indexes
355
+ CREATE INDEX IF NOT EXISTS idx_whiteboard_lesson ON whiteboard_elements(lesson_id);
356
+ CREATE INDEX IF NOT EXISTS idx_class_students_class ON class_students(class_id);
357
+ CREATE INDEX IF NOT EXISTS idx_class_students_student ON class_students(student_id);
358
+ CREATE INDEX IF NOT EXISTS idx_schedules_class_date ON schedules(class_id, scheduled_date);
359
+ CREATE INDEX IF NOT EXISTS idx_courseware_attempt_cw_st ON courseware_attempt(courseware_id, student_id);
360
+ CREATE INDEX IF NOT EXISTS idx_submission_result_attempt ON submission_result(attempt_id);
361
+ CREATE INDEX IF NOT EXISTS idx_events_type_time ON events(type, timestamp);
362
+ CREATE INDEX IF NOT EXISTS idx_assignments_class ON assignments(class_id);
363
+ CREATE INDEX IF NOT EXISTS idx_attendance_schedule ON attendance(schedule_id);
364
+
365
+ -- DOWN
366
+ DROP INDEX IF EXISTS idx_attendance_schedule;
367
+ DROP INDEX IF EXISTS idx_assignments_class;
368
+ DROP INDEX IF EXISTS idx_events_type_time;
369
+ DROP INDEX IF EXISTS idx_submission_result_attempt;
370
+ DROP INDEX IF EXISTS idx_courseware_attempt_cw_st;
371
+ DROP INDEX IF EXISTS idx_schedules_class_date;
372
+ DROP INDEX IF EXISTS idx_class_students_student;
373
+ DROP INDEX IF EXISTS idx_class_students_class;
374
+ DROP INDEX IF EXISTS idx_whiteboard_lesson;
375
+ DROP TABLE IF EXISTS plugin_grades;
376
+ DROP TABLE IF EXISTS plugin_peer_reviews;
377
+ DROP TABLE IF EXISTS plugin_submissions;
378
+ DROP TABLE IF EXISTS mfe_remotes;
379
+ DROP TABLE IF EXISTS submission_result;
380
+ DROP TABLE IF EXISTS submission_raw;
381
+ DROP TABLE IF EXISTS courseware_attempt;
382
+ DROP TABLE IF EXISTS courseware;
383
+ DROP TABLE IF EXISTS student_point_logs;
384
+ DROP TABLE IF EXISTS student_semester_reports;
385
+ DROP TABLE IF EXISTS class_grade_weights;
386
+ DROP TABLE IF EXISTS exam_scores;
387
+ DROP TABLE IF EXISTS exams;
388
+ DROP TABLE IF EXISTS ai_providers;
389
+ DROP TABLE IF EXISTS student_read_notifications;
390
+ DROP TABLE IF EXISTS client_sessions;
391
+ DROP TABLE IF EXISTS users;
392
+ DROP TABLE IF EXISTS student_seats;
393
+ DROP TABLE IF EXISTS computer_labs;
394
+ DROP TABLE IF EXISTS system_resources;
395
+ DROP TABLE IF EXISTS attendance;
396
+ DROP TABLE IF EXISTS schedules;
397
+ DROP TABLE IF EXISTS assignment_submissions;
398
+ DROP TABLE IF EXISTS assignments;
399
+ DROP TABLE IF EXISTS student_lesson_progress;
400
+ DROP TABLE IF EXISTS class_students;
401
+ DROP TABLE IF EXISTS students;
402
+ DROP TABLE IF EXISTS classes;
403
+ DROP TABLE IF EXISTS vfs_nodes;
404
+ DROP TABLE IF EXISTS processes;
405
+ DROP TABLE IF EXISTS pending_commands;
406
+ DROP TABLE IF EXISTS plugin_storage;
407
+ DROP TABLE IF EXISTS plugins;
408
+ DROP TABLE IF EXISTS whiteboard_elements;
409
+ DROP TABLE IF EXISTS lessons;
410
+ DROP TABLE IF EXISTS events;
@@ -0,0 +1,6 @@
1
+ -- UP
2
+ -- Phase 5: Worker isolation mode support — execution_mode column for plugins table
3
+ ALTER TABLE plugins ADD COLUMN execution_mode TEXT DEFAULT 'inline';
4
+
5
+ -- DOWN
6
+ -- Note: SQLite does not support DROP COLUMN in earlier versions without table recreation.
@@ -0,0 +1,6 @@
1
+ -- UP
2
+ -- SEC-AUTH-03: client_sessions 添加 expires_at 列
3
+ ALTER TABLE client_sessions ADD COLUMN expires_at INTEGER;
4
+
5
+ -- DOWN
6
+ -- Note: SQLite does not support DROP COLUMN in earlier versions without table recreation.
@@ -0,0 +1,33 @@
1
+ -- UP
2
+ -- Classroom and AI Assistant Runtime Tables
3
+
4
+ CREATE TABLE IF NOT EXISTS student_rollcalls (
5
+ id TEXT PRIMARY KEY,
6
+ student_id TEXT NOT NULL,
7
+ class_id TEXT,
8
+ lesson_id TEXT,
9
+ picked_time INTEGER NOT NULL
10
+ );
11
+
12
+ CREATE TABLE IF NOT EXISTS site_settings (
13
+ id TEXT PRIMARY KEY,
14
+ site_name TEXT,
15
+ slogan TEXT,
16
+ logo_url TEXT
17
+ );
18
+
19
+ CREATE TABLE IF NOT EXISTS agent_conversations (
20
+ id TEXT PRIMARY KEY,
21
+ conv_key TEXT NOT NULL,
22
+ role TEXT NOT NULL,
23
+ content TEXT NOT NULL,
24
+ created_at INTEGER NOT NULL
25
+ );
26
+
27
+ CREATE INDEX IF NOT EXISTS idx_agent_conv_key ON agent_conversations(conv_key, created_at);
28
+
29
+ -- DOWN
30
+ DROP INDEX IF EXISTS idx_agent_conv_key;
31
+ DROP TABLE IF EXISTS agent_conversations;
32
+ DROP TABLE IF EXISTS site_settings;
33
+ DROP TABLE IF EXISTS student_rollcalls;
@@ -0,0 +1,26 @@
1
+ -- UP
2
+ -- Courseware Score Aggregation Policy (native / platform side)
3
+ --
4
+ -- 记录每个互动课件的「成绩归集策略」:同一个 attempt 往往会产生多次分数样本
5
+ -- (学生反复提交、或平台分数变量监视器持续采样),宿主按此策略决定最终成绩,
6
+ -- 使记录层(submission_raw -> submission_result)自身闭环,不再依赖某个插件。
7
+ --
8
+ -- courseware_id = '*' 表示全局默认策略(课件没有单独配置时使用)。
9
+
10
+ CREATE TABLE IF NOT EXISTS courseware_score_config (
11
+ courseware_id TEXT PRIMARY KEY,
12
+ courseware_name TEXT,
13
+ score_policy TEXT NOT NULL DEFAULT 'LATEST',
14
+ score_fields TEXT NOT NULL DEFAULT '',
15
+ raw_full_score REAL NOT NULL DEFAULT 100,
16
+ target_full_score REAL NOT NULL DEFAULT 100,
17
+ weight_percentage REAL NOT NULL DEFAULT 100,
18
+ lesson_id TEXT,
19
+ updated_at INTEGER NOT NULL DEFAULT 0
20
+ );
21
+
22
+ CREATE INDEX IF NOT EXISTS idx_courseware_score_config_lesson ON courseware_score_config(lesson_id);
23
+
24
+ -- DOWN
25
+ DROP INDEX IF EXISTS idx_courseware_score_config_lesson;
26
+ DROP TABLE IF EXISTS courseware_score_config;
@@ -0,0 +1,155 @@
1
+ -- UP
2
+ -- 作业中心(Assignment Hub)
3
+ --
4
+ -- 背景:白板上的「课堂作业任务」教学对象此前只有一个模拟上传按钮,而平台真正的
5
+ -- 提交/互评/评分链路(plugin_submissions / plugin_peer_reviews / plugin_grades)
6
+ -- 只按 lesson_id 记录、且重交会覆盖历史。本次把作业提升为一等实体:
7
+ -- plugin_assignments 作业实体(可同时挂 lesson_id + class_id + 白板元素 id)
8
+ -- plugin_submission_versions 每次提交留档(重交不丢历史)
9
+ -- plugin_assignment_files 上传文件元数据(实体文件落盘,下载端点据此鉴权)
10
+ -- plugin_peer_review_tasks 互评任务分配(谁评谁 / 匿名 / 截止)
11
+ -- 并给 plugin_submissions 增加 assignment_id、plugin_grades / plugin_peer_reviews
12
+ -- 补充作业维度与发布字段。
13
+
14
+ CREATE TABLE IF NOT EXISTS plugin_assignments (
15
+ id TEXT PRIMARY KEY,
16
+ class_id TEXT,
17
+ lesson_id TEXT,
18
+ element_id TEXT,
19
+ title TEXT NOT NULL,
20
+ description TEXT,
21
+ instructions TEXT,
22
+ due_at INTEGER,
23
+ allow_late INTEGER NOT NULL DEFAULT 1,
24
+ allow_text INTEGER NOT NULL DEFAULT 1,
25
+ allow_link INTEGER NOT NULL DEFAULT 0,
26
+ max_files INTEGER NOT NULL DEFAULT 10,
27
+ max_file_size INTEGER NOT NULL DEFAULT 20971520,
28
+ allowed_ext TEXT NOT NULL DEFAULT '',
29
+ peer_review_mode TEXT NOT NULL DEFAULT 'assigned',
30
+ peer_review_count INTEGER NOT NULL DEFAULT 2,
31
+ peer_review_due_at INTEGER,
32
+ teacher_weight REAL NOT NULL DEFAULT 0.6,
33
+ peer_weight REAL NOT NULL DEFAULT 0.4,
34
+ status TEXT NOT NULL DEFAULT 'published',
35
+ created_by TEXT,
36
+ created_at INTEGER NOT NULL,
37
+ updated_at INTEGER NOT NULL
38
+ );
39
+
40
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_plugin_assignments_element ON plugin_assignments(element_id);
41
+ CREATE INDEX IF NOT EXISTS idx_plugin_assignments_lesson ON plugin_assignments(lesson_id);
42
+ CREATE INDEX IF NOT EXISTS idx_plugin_assignments_class ON plugin_assignments(class_id);
43
+
44
+ -- plugin_submissions 需要从「按 lesson 唯一」改为「按 assignment 唯一」,
45
+ -- SQLite 无法删除表级 UNIQUE 约束,因此重建表并保留旧数据(旧数据 assignment_id 为 NULL)。
46
+ CREATE TABLE IF NOT EXISTS plugin_submissions_new (
47
+ id TEXT PRIMARY KEY,
48
+ assignment_id TEXT,
49
+ lesson_id TEXT,
50
+ student_id TEXT NOT NULL,
51
+ file_path TEXT,
52
+ version INTEGER NOT NULL DEFAULT 1,
53
+ created_at INTEGER NOT NULL,
54
+ updated_at INTEGER NOT NULL
55
+ );
56
+
57
+ INSERT OR IGNORE INTO plugin_submissions_new
58
+ (id, assignment_id, lesson_id, student_id, file_path, version, created_at, updated_at)
59
+ SELECT id, NULL, lesson_id, student_id, file_path, version, created_at, updated_at FROM plugin_submissions;
60
+
61
+ DROP TABLE IF EXISTS plugin_submissions;
62
+ ALTER TABLE plugin_submissions_new RENAME TO plugin_submissions;
63
+
64
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_plugin_submissions_assignment_student ON plugin_submissions(assignment_id, student_id);
65
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_plugin_submissions_legacy ON plugin_submissions(lesson_id, student_id) WHERE assignment_id IS NULL;
66
+
67
+ CREATE TABLE IF NOT EXISTS plugin_submission_versions (
68
+ id TEXT PRIMARY KEY,
69
+ submission_id TEXT NOT NULL,
70
+ assignment_id TEXT,
71
+ student_id TEXT NOT NULL,
72
+ version INTEGER NOT NULL,
73
+ files_json TEXT NOT NULL DEFAULT '[]',
74
+ text_content TEXT,
75
+ link_url TEXT,
76
+ is_late INTEGER NOT NULL DEFAULT 0,
77
+ submitted_at INTEGER NOT NULL,
78
+ UNIQUE(submission_id, version)
79
+ );
80
+
81
+ CREATE INDEX IF NOT EXISTS idx_plugin_submission_versions_submission ON plugin_submission_versions(submission_id);
82
+
83
+ CREATE TABLE IF NOT EXISTS plugin_assignment_files (
84
+ id TEXT PRIMARY KEY,
85
+ assignment_id TEXT NOT NULL,
86
+ submission_id TEXT,
87
+ version_id TEXT,
88
+ student_id TEXT NOT NULL,
89
+ original_name TEXT NOT NULL,
90
+ stored_path TEXT NOT NULL,
91
+ size INTEGER NOT NULL DEFAULT 0,
92
+ mime TEXT,
93
+ sha256 TEXT,
94
+ uploaded_at INTEGER NOT NULL,
95
+ deleted_at INTEGER
96
+ );
97
+
98
+ CREATE INDEX IF NOT EXISTS idx_plugin_assignment_files_owner ON plugin_assignment_files(assignment_id, student_id);
99
+
100
+ CREATE TABLE IF NOT EXISTS plugin_peer_review_tasks (
101
+ id TEXT PRIMARY KEY,
102
+ assignment_id TEXT NOT NULL,
103
+ submission_id TEXT NOT NULL,
104
+ reviewer_id TEXT NOT NULL,
105
+ anonymous INTEGER NOT NULL DEFAULT 1,
106
+ status TEXT NOT NULL DEFAULT 'pending',
107
+ due_at INTEGER,
108
+ created_at INTEGER NOT NULL,
109
+ UNIQUE(submission_id, reviewer_id)
110
+ );
111
+
112
+ CREATE INDEX IF NOT EXISTS idx_plugin_peer_review_tasks_reviewer ON plugin_peer_review_tasks(reviewer_id, status);
113
+
114
+ ALTER TABLE plugin_peer_reviews ADD COLUMN assignment_id TEXT;
115
+ ALTER TABLE plugin_peer_reviews ADD COLUMN task_id TEXT;
116
+ ALTER TABLE plugin_peer_reviews ADD COLUMN anonymous INTEGER NOT NULL DEFAULT 1;
117
+ ALTER TABLE plugin_peer_reviews ADD COLUMN status TEXT NOT NULL DEFAULT 'submitted';
118
+ ALTER TABLE plugin_peer_reviews ADD COLUMN updated_at INTEGER;
119
+
120
+ ALTER TABLE plugin_grades ADD COLUMN assignment_id TEXT;
121
+ ALTER TABLE plugin_grades ADD COLUMN peer_average_score REAL;
122
+ ALTER TABLE plugin_grades ADD COLUMN source TEXT NOT NULL DEFAULT 'teacher';
123
+ ALTER TABLE plugin_grades ADD COLUMN published_at INTEGER;
124
+ ALTER TABLE plugin_grades ADD COLUMN graded_by TEXT;
125
+
126
+ -- DOWN
127
+ DROP INDEX IF EXISTS idx_plugin_peer_review_tasks_reviewer;
128
+ DROP TABLE IF EXISTS plugin_peer_review_tasks;
129
+ DROP INDEX IF EXISTS idx_plugin_assignment_files_owner;
130
+ DROP TABLE IF EXISTS plugin_assignment_files;
131
+ DROP INDEX IF EXISTS idx_plugin_submission_versions_submission;
132
+ DROP TABLE IF EXISTS plugin_submission_versions;
133
+
134
+ DROP INDEX IF EXISTS idx_plugin_submissions_legacy;
135
+ DROP INDEX IF EXISTS idx_plugin_submissions_assignment_student;
136
+ CREATE TABLE IF NOT EXISTS plugin_submissions_legacy (
137
+ id TEXT PRIMARY KEY,
138
+ lesson_id TEXT NOT NULL,
139
+ student_id TEXT NOT NULL,
140
+ file_path TEXT NOT NULL,
141
+ version INTEGER NOT NULL DEFAULT 1,
142
+ created_at INTEGER NOT NULL,
143
+ updated_at INTEGER NOT NULL,
144
+ UNIQUE(lesson_id, student_id)
145
+ );
146
+ INSERT OR IGNORE INTO plugin_submissions_legacy (id, lesson_id, student_id, file_path, version, created_at, updated_at)
147
+ SELECT id, COALESCE(lesson_id, assignment_id), student_id, COALESCE(file_path, ''), version, created_at, updated_at
148
+ FROM plugin_submissions;
149
+ DROP TABLE IF EXISTS plugin_submissions;
150
+ ALTER TABLE plugin_submissions_legacy RENAME TO plugin_submissions;
151
+
152
+ DROP INDEX IF EXISTS idx_plugin_assignments_class;
153
+ DROP INDEX IF EXISTS idx_plugin_assignments_lesson;
154
+ DROP INDEX IF EXISTS idx_plugin_assignments_element;
155
+ DROP TABLE IF EXISTS plugin_assignments;
@@ -0,0 +1,28 @@
1
+ -- UP
2
+ -- 课堂事件统一:events 审计表补索引与课堂维度
3
+ --
4
+ -- 背景:课堂里的状态变更(锁屏、进度、随堂作答、课件 attempt、进度模式)此前
5
+ -- 都是 REST 路由里直接 `io.emit`,绕过内核总线,因此不进 `events` 表。统一走
6
+ -- 总线后,`events` 成为课堂的事实日志,读取形态也变了:
7
+ -- - 按时间窗口查询(课堂报告、排障回溯)
8
+ -- - 按 correlationId 串联同一条业务流(一次课件作答的 log → adopt → submit)
9
+ -- - 按课节重放整堂课
10
+ -- 现有索引只有 (type, timestamp),上述三种查询都走不到索引。本次补齐:
11
+ -- idx_events_timestamp 纯时间窗口查询
12
+ -- idx_events_correlation 按 correlationId 串联
13
+ -- events.lesson_id 课堂维度列 + (lesson_id, timestamp) 复合索引
14
+ --
15
+ -- 关于顺序:不额外引入 seq 列。SQLite 每张普通表都有单调递增的内建 rowid,
16
+ -- 按 `ORDER BY rowid` 即可得到稳定的事件顺序,无需维护内存计数器,
17
+ -- 也避免了进程重启后序号回退的问题。
18
+
19
+ CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
20
+ CREATE INDEX IF NOT EXISTS idx_events_correlation ON events(correlationId);
21
+ ALTER TABLE events ADD COLUMN lesson_id TEXT;
22
+ CREATE INDEX IF NOT EXISTS idx_events_lesson_time ON events(lesson_id, timestamp);
23
+
24
+ -- DOWN
25
+ -- 只回滚索引:DROP COLUMN 需要 SQLite 3.35+,且留下一个未被写入的 NULL 列是无害的。
26
+ DROP INDEX IF EXISTS idx_events_timestamp;
27
+ DROP INDEX IF EXISTS idx_events_correlation;
28
+ DROP INDEX IF EXISTS idx_events_lesson_time;