Không chỉ syntax — kiểm tra luồng dữ liệu và quyền từ đầu đến cuối
Kết luận audit: NOT RELEASE READY. V12 là prototype tốt để hợp nhất engine, nhưng còn blocker về data scope, assignment grading, speaking, scheduler, sync và Multi‑Edition package.
Blocker phải sửa trước khi gọi V12 ổn định
V12 Student page opens directly; the V10 verified-email/enrollment gate was removed.
FIX: Restore Auth/enrollment gate; server must verify email and active group membership before rendering course data.Assignments, posts, comments, notebook and messages use global localStorage keys. A second user/class in the same origin would see the same data.
FIX: Namespace/demo entities by organization_id, group_id, user_id/conversation_id; production RLS must enforce the same scopes.Student paintAssignments renders every assignment in the global store; no membership/group filter.
FIX: Filter by active group membership and assignment target.Assignment stores course text but no groupId/target list; any Student V12 page sees it.
FIX: Store group_id and assignment_targets; validate teacher permission at publish.Correct answers are stored client-side in the assignment object/static JS and student auto-grades in-browser.
FIX: Production answer keys must stay server-side; browser receives only public question payload.Teacher grade modal does not render test questions/answers, so manual short-answer grading is impossible.
FIX: Render each question, student answer, objective result and manual points/feedback.Student card only changes to “Đã chấm”; it does not display score, feedback, graded time or detailed result.
FIX: Add result drawer/card and returned/resubmit states.closeModal does not stop an active recorder/media tracks, so microphone may continue recording after UI closes.
FIX: Central cleanup on close/navigation/unload; stop recorder, tracks, timers and revoke object URLs.Student stores only audio metadata in localStorage; Teacher sees name/size, not playable bytes/object URL.
FIX: Production Storage URL; demo can use IndexedDB/object blob reference. Teacher grading needs audio player.All posts/comments share global keys; no groupId.
FIX: Add group_id and authorize membership.Messages only use from=teacher/student and one global thread; no sender/recipient/conversation IDs.
FIX: Use conversation_id + sender_user_id + recipient/group scope.Notebook, posts, comments, chat, writing and assignment text are interpolated into innerHTML without escaping.
FIX: Render via textContent or HTML-escape/sanitize to prevent stored XSS.V10 had create-group and email-invite flows; V12 Teacher removed them.
FIX: Restore group creation/invite/student roster from V10 and connect to shared group/membership data.UI claims these checks, but runConflictCheck only checks schedule/group/resource overlap.
FIX: Check teacher availability, approved absences, skill requirements and role before OK.Save button remains enabled after an OK check even if teacher/time/resource inputs are changed.
FIX: Any input change resets checked state; save must call conflict check again atomically.saveSchedule pushes data without re-running validation; contradicts “server re-check” rule.
FIX: Server/database re-check in transaction; demo save must invoke validator again.assignSub only shows toast; it does not update schedule/effective teacher or Student/Teacher pages.
FIX: Persist session_teacher_assignment and broadcast update to all portals.Sync Center is an isolated simulation. Student/Teacher writes go straight to localStorage and ignore offline/outbox/conflict states.
FIX: Create one shared data service abstraction; UI mutations always go through it.Core files are present, but internal start.html links point to root while files live under core/.
FIX: Fix start links to core/... or place launch files at root; automated zip link test must be a release gate.Automated audit found 5 broken links in each language ZIP and 13 in Enterprise ZIP.
FIX: Run package link resolver in CI and block build on any missing target.start.html is localized, but V12 Student/Teacher ignore ?edition=xx and remain Vietnamese.
FIX: Load locale pack into the actual app UI/dynamic strings or build localized app shell from one source.Prior notes recommend RLS, but no V12 RLS policies are included.
FIX: Implement organization/group/student/teacher RLS before production.V10 had group creation, email invites, roster, lifecycle and calendar; V12 removed those interactive flows.
FIX: Merge V12 assignment/feed/chat into the richer V10 Teacher shell.Kiểm tra Edition ZIP
Điểm phát hiện: các language ZIP có file Core nhưng start.html trỏ sai thư mục; đồng thời query ?edition=ja/zh/ko chưa được Student/Teacher xử lý, nên app Core vẫn tiếng Việt.
| # | Area | Check | Status | Severity | Finding | Required action |
|---|---|---|---|---|---|---|
| 1 | Identity & Access | Student email enrollment gate | FAIL | BLOCKER | V12 Student page opens directly; the V10 verified-email/enrollment gate was removed. | Restore Auth/enrollment gate; server must verify email and active group membership before rendering course data. |
| 2 | Identity & Access | Role isolation | PARTIAL | HIGH | Admin/Manager/Teacher/Student have separate pages, but static prototype has no authenticated server-side role enforcement. | Enforce RBAC/RLS server-side; UI routing is not authorization. |
| 3 | Identity & Access | Shared demo store is scoped by organization/group/user | FAIL | BLOCKER | Assignments, posts, comments, notebook and messages use global localStorage keys. A second user/class in the same origin would see the same data. | Namespace/demo entities by organization_id, group_id, user_id/conversation_id; production RLS must enforce the same scopes. |
| 4 | Identity & Access | Teacher can act only on assigned groups | FAIL | HIGH | Teacher Assignment creator offers IELTS/N4/HSK/TOPIK without checking teacher-group membership. | Populate course/group picker only from active group_teacher_memberships. |
| 5 | Identity & Access | Student sees only assignments for enrolled groups | FAIL | BLOCKER | Student paintAssignments renders every assignment in the global store; no membership/group filter. | Filter by active group membership and assignment target. |
| 6 | Course lifecycle | Progress ring and dates | PASS | LOW | Current course progress/date UI is present. | Keep, but calculate from server data instead of hard-coded values. |
| 7 | Course lifecycle | Old course archive/resource history | REGRESSION | HIGH | V10 had an explicit old-course archive card; V12 Student removed it. | Restore archive/history with immutable old enrollment resources, grades and submissions. |
| 8 | Course lifecycle | End → read-only → 90-day renewal → archive enforcement | FAIL | HIGH | Lifecycle is displayed as tags only; no V12 Student/Teacher logic changes access based on dates/status. | Backend lifecycle service/cron must change enrollment status and authorize read/write accordingly. |
| 9 | Course lifecycle | Renewal creates new enrollment | PARTIAL | MEDIUM | Database design from V7.2 specifies this, but V12 UI no longer exposes the renewal action. | Restore Teacher/Manager renewal flow; never extend old enrollment in-place. |
| 10 | Course lifecycle | Course progress reacts to lesson/test completion | FAIL | HIGH | Assignment grading does not update lesson completion, skill mastery or course progress. | Define completion events and recompute progress from curriculum requirements. |
| 11 | Curriculum | 4-language curriculum model | PASS | LOW | Curriculum Studio supports English/CEFR, Japanese/JLPT, Chinese/HSK, Korean/TOPIK. | Keep a single curriculum engine. |
| 12 | Curriculum | Resource upload attached to lesson | PARTIAL | MEDIUM | UI attaches file metadata to a selected lesson, but upload is only browser demo/toast. | Production Storage + asset rows + checksum/virus scan + permission validation. |
| 13 | Curriculum | Pinned curriculum versions | PARTIAL | MEDIUM | Versioning rule is documented/UI, but create/publish/migrate buttons do not persist real version transitions. | Implement draft→review→published→retired and explicit group migration transactions. |
| 14 | Curriculum | Assignment linked to curriculum lesson | FAIL | HIGH | V12 assignment objects have course name only; no lesson/curriculum_node ID. | Require optional/required lesson_id and learning outcome links so calendar/progress stay coherent. |
| 15 | Curriculum | Stale version labels | FAIL | LOW | Curriculum V12 still visibly says “Curriculum Studio V10 / Quy tắc V10”; manager/admin CSS markers also retain old V8/V9/V10 names. | Rename visible version labels and internal markers to V12/V12.1 to avoid diagnostics confusion. |
| 16 | Assignment & Test | Teacher creates Test/Speaking/File/Writing | PASS | LOW | Interactive creator exists for four assignment types. | Keep. |
| 17 | Assignment & Test | Target group/student model in demo | FAIL | BLOCKER | Assignment stores course text but no groupId/target list; any Student V12 page sees it. | Store group_id and assignment_targets; validate teacher permission at publish. |
| 18 | Assignment & Test | Open/start/close/deadline lifecycle | FAIL | HIGH | Only due string + status=open exist; student can submit regardless of open/closed/expired. | Use open_at/due_at/close_at, timezone-aware timestamps and late policy. |
| 19 | Assignment & Test | Calendar event created when assignment published | FAIL | HIGH | Creator text claims publish creates a calendar item, but no V12 calendar store/event is written and Student V12 has no calendar section. | Create calendar event referencing assignment_id; restore student/teacher calendars. |
| 20 | Assignment & Test | Test question validation | PARTIAL | HIGH | Question text is validated; blank MCQ options, invalid totals and point mismatch can still be published. | Validate all options, correct answer, points >0 and sum(question points)=assignment max or auto-derive max. |
| 21 | Assignment & Test | Paste import count | FAIL | LOW | Toast reports total input lines, even malformed rows that were not imported. | Count only successfully parsed rows and show rejected lines. |
| 22 | Assignment & Test | Test answer-key security | FAIL | BLOCKER | Correct answers are stored client-side in the assignment object/static JS and student auto-grades in-browser. | Production answer keys must stay server-side; browser receives only public question payload. |
| 23 | Assignment & Test | Autosave test draft | PASS | LOW | Answers are saved/restored from localStorage for the prototype. | Production use attempt_id + server/local autosave with versioning. |
| 24 | Assignment & Test | Attempt/resubmission lifecycle | FAIL | HIGH | Submissions are appended, but Student uses the first matching submission; attempts/retries/resubmit_requested are not enforced. | Use attempt_no and latest submission; enforce attempts_allowed and resubmit state. |
| 25 | Assignment & Test | Teacher can grade short-answer test | FAIL | BLOCKER | Teacher grade modal does not render test questions/answers, so manual short-answer grading is impossible. | Render each question, student answer, objective result and manual points/feedback. |
| 26 | Assignment & Test | Student sees returned score/feedback | FAIL | BLOCKER | Student card only changes to “Đã chấm”; it does not display score, feedback, graded time or detailed result. | Add result drawer/card and returned/resubmit states. |
| 27 | Assignment & Test | Grade validation | FAIL | HIGH | Score input relies on HTML min/max; saveGrade accepts NaN/out-of-range via JS and overwrites state. | Validate numeric score server-side and in JS; preserve auto/manual/final score components. |
| 28 | Assignment & Test | Writing + attachment as one submission | FAIL | MEDIUM | “Đính kèm Word/PDF” opens generic file submission, creating a separate submission instead of attaching to the writing attempt. | Use one draft/submission ID with text_answer + submission_files. |
| 29 | Assignment & Test | Draft buttons really persist | FAIL | MEDIUM | Several “Lưu nháp” buttons only show a toast and do not persist the draft. | Persist draft entity with updated_at and restore it. |
| 30 | Speaking & Files | Browser microphone recorder | PARTIAL | HIGH | MediaRecorder works when permission/HTTPS allow it. | Keep fallback upload; add capability messaging. |
| 31 | Speaking & Files | Recorder max duration | FAIL | HIGH | Assignment seconds value is not enforced; recording can exceed maximum. | Auto-stop at max seconds and show remaining time. |
| 32 | Speaking & Files | Recorder retry | FAIL | MEDIUM | After stop, Start remains disabled; assignment retries setting is not enforced/tracked. | Re-enable retry until attempts limit; track attempts. |
| 33 | Speaking & Files | Close modal stops microphone | FAIL | BLOCKER | closeModal does not stop an active recorder/media tracks, so microphone may continue recording after UI closes. | Central cleanup on close/navigation/unload; stop recorder, tracks, timers and revoke object URLs. |
| 34 | Speaking & Files | Teacher can play submitted speaking audio | FAIL | BLOCKER | Student stores only audio metadata in localStorage; Teacher sees name/size, not playable bytes/object URL. | Production Storage URL; demo can use IndexedDB/object blob reference. Teacher grading needs audio player. |
| 35 | Speaking & Files | File type/size validation | PARTIAL | HIGH | File input accept attribute exists, but drag/drop accepts anything and no max size checks run. | Validate MIME + extension + size before queueing; server repeats validation/virus scan. |
| 36 | Speaking & Files | File upload completion truthfulness | PARTIAL | MEDIUM | Prototype explicitly stores metadata only; it does not falsely claim Storage ACK, but final upload lifecycle is not connected. | Use queued/uploading/uploaded/server_ack states and resumable upload. |
| 37 | Class interaction | Notebook works | PARTIAL | MEDIUM | Vocabulary/Grammar/Notes add/delete/filter works, but store is not scoped by user/course and has no sync metadata. | Add user_id/course_id/device version; escape content and sync delta. |
| 38 | Class interaction | Feed group isolation | FAIL | BLOCKER | All posts/comments share global keys; no groupId. | Add group_id and authorize membership. |
| 39 | Class interaction | Chat conversation isolation | FAIL | BLOCKER | Messages only use from=teacher/student and one global thread; no sender/recipient/conversation IDs. | Use conversation_id + sender_user_id + recipient/group scope. |
| 40 | Class interaction | Cross-tab live refresh | FAIL | HIGH | Teacher/Student write the same localStorage keys but neither listens for storage events, so the other open tab does not repaint until reload/local action. | Listen for storage events/BroadcastChannel in demo; production Realtime event → delta pull. |
| 41 | Class interaction | User-generated content escaped | FAIL | BLOCKER | Notebook, posts, comments, chat, writing and assignment text are interpolated into innerHTML without escaping. | Render via textContent or HTML-escape/sanitize to prevent stored XSS. |
| 42 | Class interaction | Like/reaction persistence | FAIL | LOW | Like button only toasts and does not store reaction state. | Persist reaction or remove misleading button from prototype. |
| 43 | Class interaction | Notifications | FAIL | MEDIUM | “Đăng & thông báo”, assignment publish, grading and chat do not create a notification entity. | Create notification/outbox events with read state and preference rules. |
| 44 | Scheduling | Teacher multi-group overview | PASS | LOW | Static multi-group schedule is shown. | Keep, but source it from shared sessions. |
| 45 | Scheduling | Teacher create group/invite student | REGRESSION | BLOCKER | V10 had create-group and email-invite flows; V12 Teacher removed them. | Restore group creation/invite/student roster from V10 and connect to shared group/membership data. |
| 46 | Scheduling | Teacher schedule conflict check | REGRESSION | HIGH | V10 Teacher had a check-slot modal; V12 only shows a static schedule list. | Restore teacher self-check for own groups/substitute sessions. |
| 47 | Scheduling | Teacher absence/substitute request | REGRESSION | HIGH | V10 Teacher had “Báo nghỉ / yêu cầu dạy thay”; V12 Teacher removed it. | Restore request flow; Manager confirms substitute. |
| 48 | Scheduling | Manager hard overlap check | PARTIAL | HIGH | Teacher/group/resource overlap check works in JS for seed data. | Move to shared store/server and add availability/absence/effective substitute checks. |
| 49 | Scheduling | Manager validates availability/absence/skill | FAIL | BLOCKER | UI claims these checks, but runConflictCheck only checks schedule/group/resource overlap. | Check teacher availability, approved absences, skill requirements and role before OK. |
| 50 | Scheduling | Onsite buffer policy cannot be bypassed | FAIL | HIGH | Manager may select 0-minute buffer even for onsite although Admin policy says 15 minutes. | Derive minimum buffer from organization policy/mode; manager can only increase it. |
| 51 | Scheduling | Changing form after check invalidates approval | FAIL | BLOCKER | Save button remains enabled after an OK check even if teacher/time/resource inputs are changed. | Any input change resets checked state; save must call conflict check again atomically. |
| 52 | Scheduling | Save rechecks conflict | FAIL | BLOCKER | saveSchedule pushes data without re-running validation; contradicts “server re-check” rule. | Server/database re-check in transaction; demo save must invoke validator again. |
| 53 | Scheduling | Substitute assignment affects shared schedule | FAIL | BLOCKER | assignSub only shows toast; it does not update schedule/effective teacher or Student/Teacher pages. | Persist session_teacher_assignment and broadcast update to all portals. |
| 54 | Scheduling | Schedule persists/reloads | FAIL | HIGH | Manager scheduleSeed is in-memory JS; saved sessions disappear on reload and are invisible to other pages. | Use shared demo store; production class_sessions + reservations. |
| 55 | Admin | Email invite validation | PARTIAL | MEDIUM | Admin invite adds a row, but only checks non-empty email; duplicates/format/org role state are not validated. | Validate normalized email, duplicate pending invite, authorization and expiry. |
| 56 | Admin | Audit actions are actually logged | FAIL | HIGH | Audit is shown as a system feature, but prototype actions do not append audit records. | All permission/schedule/substitute/archive actions create immutable audit entries. |
| 57 | Sync | Cloud source-of-truth design | PASS | LOW | Sync Center documents correct source-of-truth/outbox principles. | Keep. |
| 58 | Sync | Actual Teacher/Student actions use Sync Engine | FAIL | BLOCKER | Sync Center is an isolated simulation. Student/Teacher writes go straight to localStorage and ignore offline/outbox/conflict states. | Create one shared data service abstraction; UI mutations always go through it. |
| 59 | Sync | Offline submission state distinction | PARTIAL | HIGH | Sync Center explains “saved locally vs submitted”, but Student assignment UI does not use those states. | Expose local_saved/queued/uploading/server_ack on actual submission cards. |
| 60 | Sync | Resumable upload connected to actual files/audio | FAIL | HIGH | Resumable upload exists only in design/DB simulation, not the Student submission flow. | Connect Storage multipart/resumable sessions to submission_files/speaking_attempts. |
| 61 | Sync | Logout/cache isolation | DESIGN | HIGH | Rule exists in Sync Center but current static pages have no login/logout cache purge. | On logout revoke token and purge/encrypt user-scoped cache. |
| 62 | Edition & Package | Edition ZIP contains full core files | PARTIAL | BLOCKER | Core files are present, but internal start.html links point to root while files live under core/. | Fix start links to core/... or place launch files at root; automated zip link test must be a release gate. |
| 63 | Edition & Package | All internal ZIP links resolve | FAIL | BLOCKER | Automated audit found 5 broken links in each language ZIP and 13 in Enterprise ZIP. | Run package link resolver in CI and block build on any missing target. |
| 64 | Edition & Package | Edition UI follows selected language | FAIL | BLOCKER | start.html is localized, but V12 Student/Teacher ignore ?edition=xx and remain Vietnamese. | Load locale pack into the actual app UI/dynamic strings or build localized app shell from one source. |
| 65 | Edition & Package | Enterprise language selector | PARTIAL | MEDIUM | Manifest lists all locales, but Enterprise portal itself has no active UI language selector/runtime. | Add locale selector persisted per user/device. |
| 66 | Edition & Package | Fresh backend schema included/defined | FAIL | HIGH | V12 package includes only database-unified-core-v12.sql, which explicitly depends on prior schemas; fresh setup cannot reconstruct the full backend from V12 alone. | Ship ordered migrations/schema manifest or one clean baseline schema plus migrations. |
| 67 | Database | V12 notebook/feed/chat foreign keys | FAIL | HIGH | V12 additions use uuid user_id/group_id fields without FKs to users/class_groups/organizations; direct_messages also lacks FK constraints. | Add FKs, indexes, uniqueness/idempotency and deletion policy. |
| 68 | Database | RLS/data isolation policy | DESIGN | BLOCKER | Prior notes recommend RLS, but no V12 RLS policies are included. | Implement organization/group/student/teacher RLS before production. |
| 69 | Database | Migration order is unambiguous | FAIL | HIGH | V7.2 duplicates V7 enum/table definitions while V12 says run after prior schemas; running both can fail on enum creation. | Publish one canonical migration chain; do not run full-copy schemas twice. |
| 70 | Database | Assignment table links to class/group with FK | FAIL | HIGH | V6 learning_assignments.class_id/teacher_id are untyped UUIDs without FK constraints to V7 users/class_groups. | Align names and add FKs to class_groups/users; include organization scope. |
| 71 | Regression | Student calendar/classes/substitute detail preserved | REGRESSION | HIGH | V10 had classes, monthly calendar and primary-vs-substitute detail; V12 removed them. | Merge V12 engines into V10 Student shell rather than replacing it. |
| 72 | Regression | Teacher group/invite/student lifecycle preserved | REGRESSION | BLOCKER | V10 had group creation, email invites, roster, lifecycle and calendar; V12 removed those interactive flows. | Merge V12 assignment/feed/chat into the richer V10 Teacher shell. |
| 73 | Regression | Feature checklist reflects actual implementation | FAIL | HIGH | Checklist labels Teacher multi-group, schedule conflict and absence/substitute as interactive even though V12 Teacher page is static/missing them. | Checklist must be generated from audited tests/status and cannot self-certify. |
Automated evidence
JavaScript syntax: index-online-v12.html: PASS; trang-hoc-vien-online-v12.html: PASS; trang-giao-vien-online-v12.html: PASS; trang-quan-ly-giao-vien-v12.html: PASS; trang-admin-doanh-nghiep-v12.html: PASS; curriculum-studio-v12.html: PASS; sync-center-v12.html: PASS; download-center-v12.html: PASS; feature-master-checklist-v12.html: PASS
Full unified ZIP ở root có link hợp lệ, nhưng từng Edition ZIP không qua link-resolution test.