TUITION STUDIO V12 · LOGIC AUDIT

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.

Tổng checks73
PASS6
FAIL + REGRESSION51
Release blockers23

Blocker phải sửa trước khi gọi V12 ổn định

Identity & Access · Student email enrollment gate

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.
Identity & Access · Shared demo store is scoped by organization/group/user

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.
Identity & Access · Student sees only assignments for enrolled groups

Student paintAssignments renders every assignment in the global store; no membership/group filter.

FIX: Filter by active group membership and assignment target.
Assignment & Test · Target group/student model in demo

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.
Assignment & Test · Test answer-key security

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.
Assignment & Test · Teacher can grade short-answer test

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.
Assignment & Test · Student sees returned score/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.
Speaking & Files · Close modal stops microphone

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.
Speaking & Files · Teacher can play submitted speaking audio

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.
Class interaction · Feed group isolation

All posts/comments share global keys; no groupId.

FIX: Add group_id and authorize membership.
Class interaction · Chat conversation isolation

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.
Class interaction · User-generated content escaped

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.
Scheduling · Teacher create group/invite student

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.
Scheduling · Manager validates availability/absence/skill

UI claims these checks, but runConflictCheck only checks schedule/group/resource overlap.

FIX: Check teacher availability, approved absences, skill requirements and role before OK.
Scheduling · Changing form after check invalidates approval

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.
Scheduling · Save rechecks conflict

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.
Scheduling · Substitute assignment affects shared schedule

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 · Actual Teacher/Student actions use Sync Engine

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.
Edition & Package · Edition ZIP contains full core files

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.
Edition & Package · All internal ZIP links resolve

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.
Edition & Package · Edition UI follows selected language

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.
Database · RLS/data isolation policy

Prior notes recommend RLS, but no V12 RLS policies are included.

FIX: Implement organization/group/student/teacher RLS before production.
Regression · Teacher group/invite/student lifecycle preserved

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

tuition-studio-en-edition-v12.zip5broken links
tuition-studio-enterprise-edition-v12.zip13broken links
tuition-studio-ja-edition-v12.zip5broken links
tuition-studio-ko-edition-v12.zip5broken links
tuition-studio-zh-edition-v12.zip5broken links

Đ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.

#AreaCheckStatusSeverityFindingRequired action
1Identity & AccessStudent email enrollment gateFAILBLOCKERV12 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.
2Identity & AccessRole isolationPARTIALHIGHAdmin/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.
3Identity & AccessShared demo store is scoped by organization/group/userFAILBLOCKERAssignments, 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.
4Identity & AccessTeacher can act only on assigned groupsFAILHIGHTeacher Assignment creator offers IELTS/N4/HSK/TOPIK without checking teacher-group membership.Populate course/group picker only from active group_teacher_memberships.
5Identity & AccessStudent sees only assignments for enrolled groupsFAILBLOCKERStudent paintAssignments renders every assignment in the global store; no membership/group filter.Filter by active group membership and assignment target.
6Course lifecycleProgress ring and datesPASSLOWCurrent course progress/date UI is present.Keep, but calculate from server data instead of hard-coded values.
7Course lifecycleOld course archive/resource historyREGRESSIONHIGHV10 had an explicit old-course archive card; V12 Student removed it.Restore archive/history with immutable old enrollment resources, grades and submissions.
8Course lifecycleEnd → read-only → 90-day renewal → archive enforcementFAILHIGHLifecycle 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.
9Course lifecycleRenewal creates new enrollmentPARTIALMEDIUMDatabase 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.
10Course lifecycleCourse progress reacts to lesson/test completionFAILHIGHAssignment grading does not update lesson completion, skill mastery or course progress.Define completion events and recompute progress from curriculum requirements.
11Curriculum4-language curriculum modelPASSLOWCurriculum Studio supports English/CEFR, Japanese/JLPT, Chinese/HSK, Korean/TOPIK.Keep a single curriculum engine.
12CurriculumResource upload attached to lessonPARTIALMEDIUMUI attaches file metadata to a selected lesson, but upload is only browser demo/toast.Production Storage + asset rows + checksum/virus scan + permission validation.
13CurriculumPinned curriculum versionsPARTIALMEDIUMVersioning 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.
14CurriculumAssignment linked to curriculum lessonFAILHIGHV12 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.
15CurriculumStale version labelsFAILLOWCurriculum 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.
16Assignment & TestTeacher creates Test/Speaking/File/WritingPASSLOWInteractive creator exists for four assignment types.Keep.
17Assignment & TestTarget group/student model in demoFAILBLOCKERAssignment 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.
18Assignment & TestOpen/start/close/deadline lifecycleFAILHIGHOnly 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.
19Assignment & TestCalendar event created when assignment publishedFAILHIGHCreator 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.
20Assignment & TestTest question validationPARTIALHIGHQuestion 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.
21Assignment & TestPaste import countFAILLOWToast reports total input lines, even malformed rows that were not imported.Count only successfully parsed rows and show rejected lines.
22Assignment & TestTest answer-key securityFAILBLOCKERCorrect 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.
23Assignment & TestAutosave test draftPASSLOWAnswers are saved/restored from localStorage for the prototype.Production use attempt_id + server/local autosave with versioning.
24Assignment & TestAttempt/resubmission lifecycleFAILHIGHSubmissions 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.
25Assignment & TestTeacher can grade short-answer testFAILBLOCKERTeacher 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.
26Assignment & TestStudent sees returned score/feedbackFAILBLOCKERStudent 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.
27Assignment & TestGrade validationFAILHIGHScore 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.
28Assignment & TestWriting + attachment as one submissionFAILMEDIUM“Đí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.
29Assignment & TestDraft buttons really persistFAILMEDIUMSeveral “Lưu nháp” buttons only show a toast and do not persist the draft.Persist draft entity with updated_at and restore it.
30Speaking & FilesBrowser microphone recorderPARTIALHIGHMediaRecorder works when permission/HTTPS allow it.Keep fallback upload; add capability messaging.
31Speaking & FilesRecorder max durationFAILHIGHAssignment seconds value is not enforced; recording can exceed maximum.Auto-stop at max seconds and show remaining time.
32Speaking & FilesRecorder retryFAILMEDIUMAfter stop, Start remains disabled; assignment retries setting is not enforced/tracked.Re-enable retry until attempts limit; track attempts.
33Speaking & FilesClose modal stops microphoneFAILBLOCKERcloseModal 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.
34Speaking & FilesTeacher can play submitted speaking audioFAILBLOCKERStudent 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.
35Speaking & FilesFile type/size validationPARTIALHIGHFile 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.
36Speaking & FilesFile upload completion truthfulnessPARTIALMEDIUMPrototype 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.
37Class interactionNotebook worksPARTIALMEDIUMVocabulary/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.
38Class interactionFeed group isolationFAILBLOCKERAll posts/comments share global keys; no groupId.Add group_id and authorize membership.
39Class interactionChat conversation isolationFAILBLOCKERMessages only use from=teacher/student and one global thread; no sender/recipient/conversation IDs.Use conversation_id + sender_user_id + recipient/group scope.
40Class interactionCross-tab live refreshFAILHIGHTeacher/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.
41Class interactionUser-generated content escapedFAILBLOCKERNotebook, posts, comments, chat, writing and assignment text are interpolated into innerHTML without escaping.Render via textContent or HTML-escape/sanitize to prevent stored XSS.
42Class interactionLike/reaction persistenceFAILLOWLike button only toasts and does not store reaction state.Persist reaction or remove misleading button from prototype.
43Class interactionNotificationsFAILMEDIUM“Đă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.
44SchedulingTeacher multi-group overviewPASSLOWStatic multi-group schedule is shown.Keep, but source it from shared sessions.
45SchedulingTeacher create group/invite studentREGRESSIONBLOCKERV10 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.
46SchedulingTeacher schedule conflict checkREGRESSIONHIGHV10 Teacher had a check-slot modal; V12 only shows a static schedule list.Restore teacher self-check for own groups/substitute sessions.
47SchedulingTeacher absence/substitute requestREGRESSIONHIGHV10 Teacher had “Báo nghỉ / yêu cầu dạy thay”; V12 Teacher removed it.Restore request flow; Manager confirms substitute.
48SchedulingManager hard overlap checkPARTIALHIGHTeacher/group/resource overlap check works in JS for seed data.Move to shared store/server and add availability/absence/effective substitute checks.
49SchedulingManager validates availability/absence/skillFAILBLOCKERUI claims these checks, but runConflictCheck only checks schedule/group/resource overlap.Check teacher availability, approved absences, skill requirements and role before OK.
50SchedulingOnsite buffer policy cannot be bypassedFAILHIGHManager 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.
51SchedulingChanging form after check invalidates approvalFAILBLOCKERSave 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.
52SchedulingSave rechecks conflictFAILBLOCKERsaveSchedule pushes data without re-running validation; contradicts “server re-check” rule.Server/database re-check in transaction; demo save must invoke validator again.
53SchedulingSubstitute assignment affects shared scheduleFAILBLOCKERassignSub only shows toast; it does not update schedule/effective teacher or Student/Teacher pages.Persist session_teacher_assignment and broadcast update to all portals.
54SchedulingSchedule persists/reloadsFAILHIGHManager scheduleSeed is in-memory JS; saved sessions disappear on reload and are invisible to other pages.Use shared demo store; production class_sessions + reservations.
55AdminEmail invite validationPARTIALMEDIUMAdmin 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.
56AdminAudit actions are actually loggedFAILHIGHAudit is shown as a system feature, but prototype actions do not append audit records.All permission/schedule/substitute/archive actions create immutable audit entries.
57SyncCloud source-of-truth designPASSLOWSync Center documents correct source-of-truth/outbox principles.Keep.
58SyncActual Teacher/Student actions use Sync EngineFAILBLOCKERSync 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.
59SyncOffline submission state distinctionPARTIALHIGHSync 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.
60SyncResumable upload connected to actual files/audioFAILHIGHResumable upload exists only in design/DB simulation, not the Student submission flow.Connect Storage multipart/resumable sessions to submission_files/speaking_attempts.
61SyncLogout/cache isolationDESIGNHIGHRule exists in Sync Center but current static pages have no login/logout cache purge.On logout revoke token and purge/encrypt user-scoped cache.
62Edition & PackageEdition ZIP contains full core filesPARTIALBLOCKERCore 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.
63Edition & PackageAll internal ZIP links resolveFAILBLOCKERAutomated 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.
64Edition & PackageEdition UI follows selected languageFAILBLOCKERstart.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.
65Edition & PackageEnterprise language selectorPARTIALMEDIUMManifest lists all locales, but Enterprise portal itself has no active UI language selector/runtime.Add locale selector persisted per user/device.
66Edition & PackageFresh backend schema included/definedFAILHIGHV12 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.
67DatabaseV12 notebook/feed/chat foreign keysFAILHIGHV12 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.
68DatabaseRLS/data isolation policyDESIGNBLOCKERPrior notes recommend RLS, but no V12 RLS policies are included.Implement organization/group/student/teacher RLS before production.
69DatabaseMigration order is unambiguousFAILHIGHV7.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.
70DatabaseAssignment table links to class/group with FKFAILHIGHV6 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.
71RegressionStudent calendar/classes/substitute detail preservedREGRESSIONHIGHV10 had classes, monthly calendar and primary-vs-substitute detail; V12 removed them.Merge V12 engines into V10 Student shell rather than replacing it.
72RegressionTeacher group/invite/student lifecycle preservedREGRESSIONBLOCKERV10 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.
73RegressionFeature checklist reflects actual implementationFAILHIGHChecklist 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.