# PRD — UtiVerse Homeroom Workspace

**Status:** Draft — siap diimplementasikan bertahap  
**Versi:** 0.1  
**Tanggal:** 29 Juli 2026  
**Produk:** UtiVerse — Wali Kelas  
**Nama fitur:** Homeroom Workspace / Ruang Kerja Wali Kelas

---

## 0. Cara menggunakan PRD ini

Dokumen ini adalah kontrak pengembangan fitur wali kelas. IDE/agent yang mengerjakannya wajib:

1. Memeriksa ulang route, controller, model, migration, dan komponen aktual karena repo dapat berkembang setelah tanggal PRD ini.
2. Mengerjakan fase secara berurutan dan menyelesaikan safety net sebelum mengubah skema atau perilaku existing.
3. Tidak mengedit migration lama yang sudah pernah dijalankan; selalu membuat migration baru.
4. Mempertahankan alur absensi mapel, absensi harian wali kelas, rekap XLSX, dan Voting Kelas yang sudah berjalan.
5. Memisahkan visibilitas menu frontend dari otorisasi backend; seluruh endpoint wajib memeriksa hak aksesnya sendiri.
6. Memakai `StudentEnrollment` dan konteks periode untuk data historis, bukan hanya `synced_students.class_id` terkini.
7. Menjalankan verification commands dan memenuhi Definition of Done pada fase aktif.
8. Menyebutkan pada handoff: fase yang selesai, test yang dijalankan, test yang belum dijalankan, dan risiko tersisa.

### Status implementasi

- [x] Fondasi existing — menu wali kelas dan penentuan wali dari `synced_classes.homeroom_teacher_id`.
- [x] Absensi harian wali kelas H/S/I/A beserta catatan.
- [x] Fallback data absensi mapel ke tampilan absensi wali kelas.
- [x] Rekap kehadiran bulanan dan ekspor XLSX.
- [x] Catatan pelanggaran dasar: tambah, daftar bulanan, ringkasan, dan hapus.
- [x] Voting Kelas.
- [x] Phase 0 — Safety net dan perbaikan integritas data.
- [x] Phase 1 — Arsip periode dan histori penugasan wali kelas.
- [x] Phase 2 — Biodata siswa dan orang tua/wali.
- [x] Phase 3 — Lifecycle pelanggaran dan tindak lanjut.
- [x] Phase 4 — Laporan dan export.
- [x] Phase 5 — Dashboard wali kelas dan profil siswa.
- [x] Phase 6 — Catatan wali kelas menyeluruh dan eskalasi.
- [ ] Phase 7 — Hardening, analytics, dan rollout.

**Checkpoint terakhir:** Phase 7 mencapai checkpoint hardening otomatis pada 29 Juli 2026. Analytics agregat dan panduan penggunaan sudah tersedia; seluruh regression suite hijau. Rollout belum ditandai selesai sampai analytics terbaru diuji ulang pada browser 360 px/desktop dan sampel DOCX dibuka/dirender stabil di Word serta LibreOffice.

---

## 1. Ringkasan keputusan

Homeroom Workspace adalah pusat kerja wali kelas untuk:

- memantau kehadiran harian dan keterlambatan;
- melihat biodata serta kontak siswa dan orang tua/wali;
- mencatat serta menindaklanjuti pelanggaran;
- melihat profil dan timeline siswa;
- mencatat pembinaan maupun pencapaian positif;
- menghasilkan laporan resmi;
- menemukan siswa yang membutuhkan perhatian tanpa membuka data kelas lain.

Fitur ini tidak mengganti absensi mapel. Absensi mapel tetap mencatat kehadiran per sesi pelajaran dengan status H/S/I/A/T, sedangkan absensi wali kelas tetap menjadi status harian H/S/I/A.

| Sumber data | Makna | Status | Peran di Homeroom Workspace |
|---|---|---|---|
| Absensi mapel | Kehadiran pada sesi pelajaran | H/S/I/A/T | Sinyal pendukung dan sumber keterlambatan |
| Absensi wali kelas | Status kehadiran harian | H/S/I/A | Status harian yang dapat dikoreksi wali kelas |
| Biodata siswa | Kontak, alamat, dan orang tua/wali | Draft/diajukan/diverifikasi/revisi | Data komunikasi yang diisi siswa dan diperiksa wali |
| Catatan pelanggaran | Insiden kedisiplinan | Ringan/sedang/berat | Kasus yang harus dapat ditindaklanjuti |
| Catatan wali kelas | Observasi pembinaan atau pencapaian | Positif/pembinaan/umum | Timeline siswa non-pelanggaran |

### Compatibility contract — tidak boleh dilanggar

1. Status `T` pada absensi mapel tidak boleh dihapus atau diubah menjadi `A`.
2. Absensi harian wali kelas tetap memakai H/S/I/A pada versi pertama.
3. Keterlambatan mapel ditampilkan sebagai jumlah/sinyal terpisah; tidak otomatis mengubah status harian menjadi alpa.
4. Route dan perilaku absensi mapel existing harus tetap berfungsi.
5. Rekap dan ekspor XLSX wali kelas existing tidak boleh dihapus.
6. Voting Kelas tetap menjadi modul paralel dan tidak digabungkan ke lifecycle pelanggaran.
7. Data siswa terkini tetap bersumber dari sinkronisasi sekolah.
8. Data historis wajib memakai enrollment dan periode agar tidak berubah saat siswa naik atau pindah kelas.
9. Jangan menganggap menu yang tersembunyi sebagai proteksi; controller/policy tetap wajib menolak akses tidak sah.
10. Tidak boleh ada pengurangan XP, hukuman otomatis, atau publikasi peringkat pelanggaran siswa.
11. Data identitas dari sinkronisasi tetap read-only bagi siswa; biodata lokal hanya melengkapi data yang belum tersedia.
12. Biodata dan nomor kontak hanya boleh dibuka oleh siswa pemilik data, wali kelas aktif yang sah, dan admin.
13. Wali kelas periode lama tidak otomatis boleh melihat nomor telepon atau alamat terkini setelah penugasannya berakhir.

---

## 2. Latar belakang masalah

Wali kelas membutuhkan gambaran siswa secara utuh, tetapi data saat ini masih tersebar:

- status hadir berasal dari absensi harian dan absensi mapel;
- keterlambatan tersedia pada absensi mapel, tetapi belum menjadi sinyal khusus bagi wali kelas;
- catatan pelanggaran hanya berupa daftar bulanan;
- tindakan yang diambil masih berupa satu kolom teks;
- belum ada status kasus, riwayat tindak lanjut, atau penanda selesai;
- belum ada laporan DOCX untuk arsip, orang tua, atau koordinasi internal;
- belum ada profil individual yang menggabungkan kehadiran, keterlambatan, dan catatan;
- belum ada tempat bagi siswa untuk mengisi nomor HP, alamat, serta kontak orang tua/wali;
- menu Profil siswa saat ini masih mengarah ke pengaturan akun dan belum menjadi biodata;
- wali kelas dan admin belum mempunyai rekap kelengkapan atau export data kontak;
- relasi siswa serta wali kelas terkini dapat berubah ketika sinkronisasi atau pergantian periode;
- backend belum memastikan `student_id` benar-benar anggota `class_id` pada penyimpanan pelanggaran;
- belum ada automated test khusus untuk boundary akses catatan pelanggaran.

Akibatnya wali kelas masih perlu menyusun laporan manual dan berisiko kehilangan konteks historis ketika siswa naik kelas.

---

## 3. Tujuan produk

### Tujuan utama

- Wali kelas dapat menyelesaikan pekerjaan harian dari satu dashboard.
- Riwayat siswa tetap benar setelah kenaikan atau perpindahan kelas.
- Pelanggaran mempunyai lifecycle yang jelas dari pencatatan sampai penyelesaian.
- Laporan resmi dapat dibuat tanpa menyalin data manual.
- Siswa dapat melengkapi biodata sendiri dan wali kelas dapat memverifikasinya.
- Wali kelas dapat menemukan kontak utama orang tua tanpa menyimpan ulang di luar sistem.
- Siswa yang membutuhkan perhatian terlihat lebih awal dari sinyal kehadiran dan pembinaan.
- Catatan positif mendapat tempat yang terpisah dari pelanggaran.
- Seluruh akses data dibatasi berdasarkan kelas dan periode yang sah.

### Indikator keberhasilan

- Wali kelas dapat mencatat insiden lengkap dalam maksimal 60 detik dari HP.
- Laporan DOCX individual atau rekap kelas dapat diunduh dalam maksimal 10 detik untuk satu kelas normal.
- Laporan individual memuat seluruh catatan sesuai filter dan tidak memuat siswa lain.
- Wali kelas lama masih dapat membuka arsip periode ketika memang ditugaskan pada periode tersebut.
- Siswa yang bukan anggota kelas/periode ditolak server walaupun request dimanipulasi.
- Dashboard dapat dibuka nyaman pada lebar 360 px tanpa scroll horizontal.
- Minimal 95% siswa pada kelas aktif mempunyai satu kontak orang tua/wali yang telah diverifikasi.
- Export biodata mempertahankan nomor telepon sebagai teks dan tidak menghilangkan angka nol awal.
- Tidak ada regresi pada absensi mapel, absensi harian wali kelas, rekap XLSX, atau Voting Kelas.

### Non-goals versi pertama

- Tidak membuat aplikasi native.
- Tidak mengirim WhatsApp, SMS, atau email otomatis kepada orang tua.
- Tidak membuat portal orang tua.
- Tidak mengumpulkan NIK, nomor KK, foto KK, atau dokumen kependudukan pada versi pertama.
- Tidak membuat AI menilai tingkat pelanggaran atau menentukan hukuman.
- Tidak mengurangi XP siswa berdasarkan pelanggaran.
- Tidak menampilkan leaderboard pelanggaran.
- Tidak mengganti sistem data induk sekolah.
- Tidak menambah role BK sebelum kebutuhan dan kebijakan aksesnya disepakati.

---

## 4. Terminologi

- **Wali kelas:** guru yang ditugaskan pada satu kelas dalam periode akademik tertentu.
- **Periode:** kombinasi tahun pelajaran dan semester.
- **Status harian:** H/S/I/A yang mewakili kondisi siswa pada satu hari.
- **Keterlambatan:** status `T` dari satu atau lebih sesi absensi mapel.
- **Biodata siswa:** data kontak dan alamat yang melengkapi identitas hasil sinkronisasi.
- **Kontak orang tua/wali:** satu atau lebih orang yang dapat dihubungi, dengan satu kontak utama.
- **Kelengkapan biodata:** status draft, submitted, verified, atau revision_requested.
- **Pelanggaran:** insiden kedisiplinan dengan tingkat ringan, sedang, atau berat.
- **Kasus terbuka:** pelanggaran yang masih membutuhkan tindak lanjut.
- **Tindak lanjut:** aksi setelah insiden, misalnya pembinaan, komunikasi orang tua, rujukan, atau penyelesaian.
- **Catatan wali kelas:** observasi non-pelanggaran berupa catatan umum, pembinaan, atau pencapaian positif.
- **Profil siswa:** tampilan individual yang merangkum identitas, kehadiran, keterlambatan, pelanggaran, dan catatan.
- **Siswa perlu perhatian:** siswa yang memenuhi sinyal deterministik yang dapat dijelaskan, bukan hasil penilaian AI.

---

## 5. Pengguna dan hak akses produk

### 5.1 Wali kelas

Wali kelas dapat:

- melihat kelas yang menjadi tanggung jawabnya pada periode terpilih;
- melihat biodata siswa aktif pada kelas yang sedang menjadi tanggung jawabnya;
- meminta perbaikan dan memverifikasi biodata;
- mengekspor biodata kelas untuk kebutuhan sekolah;
- mengisi dan mengoreksi absensi harian;
- melihat rekap kehadiran serta keterlambatan mapel;
- membuat, mengedit, menindaklanjuti, dan menyelesaikan pelanggaran;
- membuat catatan pembinaan, umum, dan positif;
- membuka profil siswa kelasnya;
- mengunduh DOCX individual dan rekap kelas;
- melihat arsip periode ketika pernah menjadi wali kelas pada periode tersebut.

### 5.2 Admin

Admin mempertahankan kemampuan melihat seluruh kelas. Mutasi data oleh admin wajib:

- melewati policy yang eksplisit;
- mencatat aktor dan waktu;
- tidak bergantung pada visibilitas menu;
- dapat dibedakan dari catatan yang dibuat wali kelas.

Admin juga dapat melihat kelengkapan biodata seluruh siswa, meminta revisi, memverifikasi, dan mengekspor data sesuai filter.

### 5.3 Guru mapel

Guru mapel tidak otomatis dapat membuka catatan wali kelas. Guru mapel hanya menjadi sumber:

- absensi per sesi;
- status keterlambatan;
- catatan kehadiran mapel yang memang sudah tersimpan.

Akses lintas peran ke kasus siswa ditunda sampai kebijakan BK/kurikulum disepakati.

### 5.4 Siswa

Siswa dapat:

- melihat identitas hasil sinkronisasi dalam mode read-only;
- mengisi dan memperbarui biodata miliknya sendiri;
- menyimpan draft sebelum semua data lengkap;
- mengajukan biodata untuk diverifikasi;
- melihat catatan revisi dari wali kelas/admin;
- melihat kapan datanya terakhir diperbarui dan diverifikasi.

Siswa tidak dapat melihat biodata siswa lain atau mengubah nama, NIS, NISN, kelas, jenis kelamin, serta tempat/tanggal lahir yang bersumber dari sinkronisasi.

### 5.5 Orang tua

Orang tua belum mempunyai akun pada versi pertama. Data orang tua/wali diisi oleh siswa dan diverifikasi manual oleh wali kelas/admin.

Siswa dan orang tua tidak dapat membuka catatan internal wali kelas. Laporan kepada orang tua diberikan melalui dokumen yang sengaja dibuat dan diperiksa wali kelas.

### 5.6 Akses setelah pergantian wali

- Wali kelas aktif dapat melihat data kontak terkini siswa aktif di kelasnya.
- Wali kelas lama dapat melihat laporan historis yang menjadi kewenangannya, tetapi tidak otomatis melihat nomor telepon/alamat terkini.
- Admin tetap dapat melihat data terkini sesuai kebutuhan administrasi.
- Setiap pembukaan detail dan export biodata dicatat pada audit log.

---

## 6. User stories

### Wali kelas

- Sebagai wali kelas, saya ingin mengetahui siswa yang biodatanya belum lengkap agar dapat mengingatkan mereka.
- Sebagai wali kelas, saya ingin melihat kontak utama orang tua dari profil siswa tanpa membuka spreadsheet terpisah.
- Sebagai wali kelas, saya ingin meminta revisi jika nomor atau alamat belum jelas.
- Sebagai wali kelas, saya ingin mengekspor biodata kelas ke XLSX saat diminta pihak sekolah.
- Sebagai wali kelas, saya ingin melihat ringkasan kelas hari ini agar tahu siapa yang belum mempunyai status harian.
- Sebagai wali kelas, saya ingin melihat berapa kali seorang siswa terlambat pada mapel agar dapat melakukan pembinaan.
- Sebagai wali kelas, saya ingin mencatat pelanggaran dari HP tanpa formulir yang panjang.
- Sebagai wali kelas, saya ingin menambahkan tindak lanjut berkali-kali tanpa menimpa catatan sebelumnya.
- Sebagai wali kelas, saya ingin menandai kasus selesai dan mengetahui siapa yang menyelesaikannya.
- Sebagai wali kelas, saya ingin mencetak laporan individual untuk pertemuan dengan orang tua.
- Sebagai wali kelas, saya ingin mencetak rekap bulanan untuk arsip sekolah.
- Sebagai wali kelas, saya ingin menulis pencapaian positif agar profil siswa tidak hanya berisi masalah.
- Sebagai wali kelas lama, saya ingin membuka arsip kelas yang pernah saya wali tanpa melihat kelas yang bukan tanggung jawab saya.

### Admin

- Sebagai admin, saya ingin melihat persentase kelengkapan biodata per kelas.
- Sebagai admin, saya ingin mengekspor biodata seluruh siswa berdasarkan kelas dan status.
- Sebagai admin, saya ingin memeriksa laporan semua kelas ketika diperlukan.
- Sebagai admin, saya ingin mengetahui siapa yang membuat atau mengubah catatan.
- Sebagai admin, saya ingin data lama tetap terhubung ke periode yang benar setelah sinkronisasi siswa.

### Siswa

- Sebagai siswa, saya ingin mengisi biodata dari HP tanpa mengubah identitas resmi sekolah.
- Sebagai siswa, saya ingin menyimpan draft jika belum mengetahui semua data orang tua.
- Sebagai siswa, saya ingin tahu bagian mana yang belum lengkap atau perlu diperbaiki.
- Sebagai siswa, saya ingin memperbarui nomor kontak ketika berganti nomor.

---

## 7. Ruang lingkup fitur

### 7.1 Biodata siswa dan orang tua/wali

#### Penempatan fitur

**Portal siswa**

- Route utama: `/student/profile`.
- Label: **Biodata Saya**.
- Akses dari kartu/banner kelengkapan pada Beranda siswa.
- Akses kedua dari menu avatar pengguna.
- `/settings` tetap digunakan untuk akun, password, dan preferensi; biodata tidak dicampur dengan pengaturan akun.
- Navigasi bawah HP tidak ditambah item permanen agar tidak terlalu padat.

**Wali kelas**

- Tab **Biodata** pada Profil Siswa.
- Halaman **Kelengkapan Biodata** pada Homeroom Workspace.
- Filter lengkap/belum lengkap/diajukan/perlu revisi/diverifikasi.
- Aksi lihat detail, minta revisi, verifikasi, export individual, dan export kelas.
- Tombol **WhatsApp** pada setiap kontak orang tua/wali yang mempunyai nomor valid.

**Admin**

- Kolom status biodata pada halaman Data Siswa.
- Filter kelas, periode, status siswa, dan status biodata.
- Detail biodata serta histori verifikasi.
- Export XLSX sesuai filter dan DOCX individual.

#### Data identitas read-only dari sinkronisasi

- nama lengkap;
- NIS dan NISN;
- kelas aktif;
- jenis kelamin;
- tempat dan tanggal lahir;
- status aktif.

Jika identitas tersebut salah, perbaikannya dilakukan pada sumber data sekolah lalu disinkronkan ulang, bukan diedit siswa di UtiVerse.

#### Data yang diisi siswa

Data siswa:

- nomor HP siswa opsional;
- nomor WhatsApp siswa opsional;
- email siswa opsional;
- alamat jalan/dusun;
- RT/RW;
- desa/kelurahan;
- kecamatan;
- kabupaten/kota;
- provinsi;
- kode pos opsional;
- tinggal bersama siapa;
- transportasi utama opsional.

Data orang tua/wali menggunakan daftar fleksibel, bukan kolom ayah dan ibu yang selalu wajib. Setiap kontak memuat:

- hubungan: ayah, ibu, wali, atau lainnya;
- nama lengkap;
- nomor telepon;
- nomor WhatsApp jika berbeda;
- pekerjaan opsional;
- alamat sama dengan siswa atau alamat terpisah;
- penanda kontak utama;
- penanda kontak darurat.

#### Tombol komunikasi WhatsApp

- Tombol tersedia pada kartu kontak orang tua/wali di Profil Siswa dan detail biodata wali kelas.
- Gunakan URL resmi `https://wa.me/{nomor}` dengan nomor Indonesia yang sudah dinormalisasi ke format `62...` tanpa tanda `+`, spasi, atau tanda baca.
- Pada HP, tautan diteruskan ke aplikasi WhatsApp jika tersedia.
- Pada laptop, tautan membuka WhatsApp Web atau aplikasi Desktop sesuai konfigurasi perangkat.
- Tautan dibuka pada tab/konteks baru dengan proteksi `noopener` dan `noreferrer`.
- Pesan awal boleh diisi otomatis dari template yang aman, tetapi pengguna tetap harus menekan tombol **Kirim** di WhatsApp.
- Aplikasi tidak menganggap chat berhasil terkirim dan tidak menyimpan status terkirim/terbaca.
- Isi pesan awal tidak boleh memuat detail pelanggaran, nilai, kondisi kesehatan, atau data sensitif secara otomatis.
- Template awal yang disarankan hanya berisi salam, identitas wali kelas, nama siswa, dan permintaan untuk berkomunikasi.
- Jika kontak mempunyai nomor telepon tetapi bukan WhatsApp, tampilkan aksi salin nomor/telepon tanpa tombol WhatsApp.
- Aksi membuka WhatsApp dapat diaudit menggunakan ID siswa/kontak dan waktu tanpa menyimpan nomor atau isi pesan pada audit description.

Aturan minimum untuk diajukan:

- alamat siswa terisi;
- minimal satu orang tua/wali;
- tepat satu kontak utama;
- kontak utama mempunyai nomor telepon atau WhatsApp.

#### Workflow kelengkapan

```text
draft -> submitted -> verified
                   -> revision_requested -> submitted
```

- Siswa dapat menyimpan draft kapan saja.
- Submit menjalankan validasi kelengkapan minimum.
- Wali kelas aktif atau admin dapat memverifikasi.
- Permintaan revisi wajib mempunyai alasan.
- Perubahan siswa setelah verified mengembalikan status ke submitted dan menyimpan jejak perubahan.
- Sistem menampilkan tanggal pembaruan dan verifikasi terakhir.
- Banner kelengkapan bersifat pengingat, bukan pemblokir akses belajar pada versi pertama.

#### Data minimization

- Jangan mengumpulkan NIK, nomor KK, foto KK, data bantuan sosial, atau dokumen kependudukan pada versi pertama.
- Jangan mewajibkan email jika komunikasi utama melalui telepon/WhatsApp.
- Nomor telepon disimpan dalam format ternormalisasi dan ditampilkan dalam format yang mudah dibaca.
- Kondisi keluarga tidak boleh dipaksa mengikuti struktur ayah+ibu; satu wali sah harus didukung.

### 7.2 Dashboard wali kelas

Dashboard menampilkan:

- kelas dan periode aktif;
- jumlah siswa aktif;
- jumlah dan persentase biodata lengkap/diverifikasi;
- daftar siswa yang biodatanya belum lengkap atau perlu revisi;
- status kehadiran hari ini;
- siswa yang belum mempunyai status harian;
- jumlah keterlambatan mapel hari ini dan bulan berjalan;
- kasus terbuka menurut tingkat;
- tindak lanjut yang jatuh tempo;
- daftar siswa perlu perhatian;
- shortcut absensi, catat pelanggaran, profil siswa, rekap, dan laporan.

Dashboard tidak menampilkan uraian sensitif pada kartu ringkas. Detail hanya muncul setelah pengguna membuka siswa/kasus yang berwenang.

### 7.3 Absensi harian dan keterlambatan

Absensi wali kelas mempertahankan H/S/I/A.

Aturan penggabungan:

1. Isian manual wali kelas menjadi status harian utama.
2. Jika belum ada isian manual, sistem dapat memakai fallback absensi mapel sesuai aturan existing.
3. Status `T` mapel dihitung sebagai hadir untuk status harian, tetapi dicatat sebagai keterlambatan terpisah.
4. Jumlah keterlambatan harus dapat dilihat per hari, bulan, semester, dan siswa.
5. Catatan mapel tidak boleh otomatis disalin menjadi catatan pelanggaran.
6. Wali kelas dapat membuat tindak lanjut dari sinyal keterlambatan melalui aksi eksplisit.

### 7.4 Lifecycle pelanggaran

Data minimum saat mencatat:

- kelas dan periode;
- siswa;
- tanggal kejadian;
- tingkat ringan/sedang/berat;
- uraian;
- tindakan awal opsional;
- pencatat.

Lifecycle:

```text
open -> in_progress -> resolved
```

Aturan:

- `open`: baru dicatat dan belum selesai.
- `in_progress`: sudah mempunyai tindak lanjut atau penanggung jawab.
- `resolved`: sudah mempunyai catatan penyelesaian dan waktu selesai.
- Kasus resolved dapat dibuka kembali dengan alasan yang tercatat.
- Edit tidak menghapus histori tindak lanjut.
- Penghapusan memakai soft delete dan hanya tersedia bagi pengguna berwenang.
- Tingkat berat tidak otomatis mengirim data keluar aplikasi.

### 7.5 Timeline tindak lanjut

Satu pelanggaran dapat mempunyai banyak tindak lanjut:

- pembinaan siswa;
- komunikasi orang tua;
- kesepakatan/pernyataan;
- rujukan internal;
- penyelesaian;
- pembukaan kembali.

Setiap entri menyimpan jenis, uraian, waktu kejadian, pencatat, dan waktu dibuat. Riwayat tidak boleh ditimpa ketika tindak lanjut baru ditambahkan.

### 7.6 Profil siswa wali kelas

Profil memuat:

- identitas dasar siswa;
- biodata kontak dan alamat;
- daftar orang tua/wali dengan kontak utama;
- status kelengkapan dan verifikasi biodata;
- kelas dan periode;
- ringkasan H/S/I/A;
- jumlah keterlambatan mapel;
- grafik atau tren bulanan sederhana;
- pelanggaran terbuka dan selesai;
- timeline tindak lanjut;
- catatan wali kelas;
- pencapaian positif;
- tombol laporan DOCX individual.

Profil menggunakan periode terpilih dan tidak mencampur data tahun pelajaran lain tanpa label yang jelas.

### 7.7 Catatan wali kelas non-pelanggaran

Jenis awal:

- `general`: observasi umum;
- `coaching`: pembinaan yang bukan kasus pelanggaran;
- `positive`: pencapaian atau perilaku positif.

Catatan non-pelanggaran:

- tidak mempunyai tingkat ringan/sedang/berat;
- tidak masuk hitungan kasus;
- dapat dipilih untuk disertakan atau tidak dalam laporan;
- tetap mempunyai periode, pencatat, waktu, dan audit.

### 7.8 Siswa perlu perhatian

Sinyal versi pertama bersifat deterministik dan dapat dijelaskan:

- persentase hadir di bawah ambang konfigurasi;
- alpa lebih dari ambang bulanan;
- keterlambatan mapel berulang;
- kasus sedang/berat yang masih terbuka;
- tindak lanjut yang melewati tenggat.

Setiap label wajib menjelaskan alasan, misalnya “3 kali terlambat bulan ini”. Tidak boleh ada skor rahasia atau label permanen terhadap siswa.

### 7.9 Laporan

Jenis laporan:

1. DOCX laporan individual siswa.
2. DOCX rekap catatan pelanggaran kelas.
3. DOCX lembar biodata individual.
4. XLSX biodata siswa dan kontak orang tua/wali per kelas.
5. XLSX rekap biodata seluruh siswa untuk admin.
6. XLSX rekap kehadiran existing.
7. Opsi PDF ditunda; DOCX menjadi prioritas dokumen individual yang perlu diedit dan ditandatangani.

---

## 8. Laporan dan export

### 8.1 Teknologi

- Gunakan `phpoffice/phpword`.
- Gunakan `TemplateProcessor` dengan template DOCX sekolah agar kop, logo, dan tanda tangan dapat diubah tanpa mengubah kode.
- Gunakan PhpSpreadsheet existing untuk export biodata XLSX.
- Template disimpan pada lokasi aplikasi yang tidak dapat diunduh langsung tanpa otorisasi.
- File sementara dibersihkan setelah response selesai.
- Nama file harus disanitasi.

### 8.2 Laporan individual siswa

Filter:

- periode;
- siswa;
- rentang tanggal;
- tingkat pelanggaran;
- status kasus;
- sertakan/tidak sertakan catatan non-pelanggaran.

Isi minimum:

- identitas sekolah;
- judul laporan;
- tahun pelajaran dan semester;
- nama, NIS/NISN, dan kelas siswa;
- nama wali kelas;
- ringkasan kehadiran dan keterlambatan;
- tabel pelanggaran kronologis;
- tingkat, uraian, tindakan awal, status, dan penyelesaian;
- ringkasan tindak lanjut;
- catatan penutup;
- tanggal pembuatan dokumen;
- tempat tanda tangan wali kelas, orang tua, dan pihak sekolah sesuai template.

### 8.3 Rekap kelas

Filter:

- kelas;
- periode;
- bulan atau rentang tanggal;
- tingkat;
- status kasus.

Isi minimum:

- identitas kelas dan wali kelas;
- total kasus menurut tingkat dan status;
- tabel siswa dan kejadian;
- jumlah kasus per siswa;
- daftar kasus terbuka;
- tempat pengesahan.

Jika data kosong, dokumen tetap valid dan menampilkan “Nihil catatan pelanggaran pada periode terpilih”.

### 8.4 Export biodata

**XLSX kelas**

- Dapat dibuat oleh wali kelas aktif untuk kelasnya.
- Satu baris mewakili satu siswa.
- Kontak orang tua/wali dapat dibuat sebagai kolom kontak utama dan kolom tambahan yang jelas.
- Nomor telepon wajib ditulis sebagai teks agar angka nol awal tidak hilang.
- Filter: kelas, status siswa, status biodata, dan periode aktif.
- Kolom sensitif yang tidak diperlukan tidak boleh ikut hanya karena tersedia di database.

**XLSX admin**

- Dapat mencakup satu kelas atau seluruh siswa sesuai filter.
- Export seluruh sekolah memerlukan aksi eksplisit dan dicatat pada audit log.
- Nama file menyertakan cakupan dan tanggal pembuatan.

**DOCX individual**

- Identitas read-only dari sinkronisasi.
- Kontak siswa.
- Alamat lengkap.
- Daftar orang tua/wali dan kontak utama.
- Status serta tanggal verifikasi.
- Kolom tanda tangan siswa, orang tua/wali, dan wali kelas jika dibutuhkan template.

Data export harus sesuai keadaan saat dibuat. Wali kelas lama tidak boleh mengekspor biodata kontak terkini setelah penugasannya berakhir.

### 8.5 Keamanan dokumen

- Endpoint export wajib menjalankan policy yang sama dengan halaman sumber.
- Filter `student_id`, `class_id`, dan periode tidak boleh dipercaya langsung.
- Dokumen tidak boleh memuat data kelas lain.
- Response memakai content type dan nama file yang benar.
- Data sensitif tidak dicatat ke log aplikasi.
- Pembuatan DOCX tidak boleh mengeksekusi macro atau template dari upload pengguna.
- Setiap export biodata mencatat aktor, filter/cakupan, waktu, dan jumlah siswa tanpa menulis nomor telepon ke audit description.

---

## 9. Arsitektur data

Migration lama tidak boleh diedit. Perubahan dibuat melalui migration baru.

### 9.1 `student_profiles`

Satu profil untuk satu `synced_student`.

| Kolom | Tipe | Catatan |
|---|---|---|
| `id` | bigint | Primary key |
| `student_id` | foreign unique | Relasi ke `synced_students` |
| `phone` | string nullable | Nomor siswa ternormalisasi |
| `whatsapp_phone` | string nullable | Jika berbeda dari telepon |
| `email` | string nullable | Tidak wajib |
| `address_line` | text nullable | Jalan/dusun/lingkungan |
| `rt` | string nullable | Simpan sebagai teks |
| `rw` | string nullable | Simpan sebagai teks |
| `village` | string nullable | Desa/kelurahan |
| `district` | string nullable | Kecamatan |
| `city` | string nullable | Kabupaten/kota |
| `province` | string nullable | Provinsi |
| `postal_code` | string nullable | Simpan sebagai teks |
| `living_with` | string nullable | Tinggal bersama |
| `transportation` | string nullable | Opsional |
| `status` | string/enum | draft/submitted/verified/revision_requested |
| `submitted_at` | datetime nullable | Waktu diajukan |
| `verified_at` | datetime nullable | Waktu diverifikasi |
| `verified_by` | foreign user nullable | Wali/admin |
| `revision_notes` | text nullable | Wajib saat meminta revisi |
| timestamps | timestamps | Waktu pembuatan/perubahan |

Identitas resmi tidak diduplikasi ke tabel ini; nama, NIS/NISN, kelas, gender, serta tempat/tanggal lahir tetap dibaca dari `synced_students`.

### 9.2 `student_guardians`

Satu siswa dapat mempunyai lebih dari satu orang tua/wali.

| Kolom | Tipe | Catatan |
|---|---|---|
| `id` | bigint | Primary key |
| `student_profile_id` | foreign | Cascade sesuai kebijakan |
| `relationship` | string/enum | father/mother/guardian/other |
| `full_name` | string | Wajib |
| `phone` | string nullable | Salah satu phone/WhatsApp wajib untuk kontak utama |
| `whatsapp_phone` | string nullable | Jika berbeda |
| `occupation` | string nullable | Opsional |
| `same_address` | boolean | Default true |
| `address` | text nullable | Wajib jika tidak sama |
| `is_primary_contact` | boolean | Tepat satu per profil submitted |
| `is_emergency_contact` | boolean | Minimal satu dianjurkan |
| timestamps | timestamps | Waktu pembuatan/perubahan |

Gunakan database constraint/index yang memungkinkan dan validasi transaksi agar hanya ada satu kontak utama.

### 9.3 Perluasan `student_violations`

Kolom yang direncanakan:

| Kolom | Tipe | Catatan |
|---|---|---|
| `academic_year_id` | foreign nullable saat backfill | Wajib untuk record baru |
| `semester_id` | foreign nullable saat backfill | Wajib untuk record baru |
| `status` | enum/string | `open`, `in_progress`, `resolved` |
| `follow_up_due_at` | datetime nullable | Tenggat tindak lanjut |
| `resolved_at` | datetime nullable | Waktu selesai |
| `resolved_by` | foreign nullable | User penyelesai |
| `resolution_notes` | text nullable | Kesimpulan kasus |
| `updated_by` | foreign nullable | Aktor perubahan terakhir |
| `deleted_at` | timestamp nullable | Soft delete |

Kolom existing `date`, `category`, `description`, `action_taken`, dan `recorded_by` tetap dipertahankan.

Data lama tidak boleh otomatis dianggap resolved hanya karena `action_taken` berisi teks.

### 9.4 `student_violation_follow_ups`

| Kolom | Tipe |
|---|---|
| `id` | bigint |
| `student_violation_id` | foreign |
| `type` | string/enum |
| `notes` | text |
| `occurred_at` | datetime |
| `recorded_by` | foreign user |
| `created_at`, `updated_at` | timestamps |

Jenis awal: `coaching`, `parent_contact`, `agreement`, `referral`, `resolution`, `reopen`.

### 9.5 `student_homeroom_notes`

| Kolom | Tipe |
|---|---|
| `id` | bigint |
| `class_id` | foreign |
| `student_id` | foreign |
| `academic_year_id` | foreign |
| `semester_id` | foreign |
| `type` | `general`, `coaching`, `positive` |
| `note_date` | date |
| `content` | text |
| `recorded_by` | foreign user |
| `updated_by` | foreign user nullable |
| `deleted_at` | timestamp nullable |
| timestamps | timestamps |

### 9.6 `homeroom_assignments`

Tabel ini diperlukan karena `synced_classes.homeroom_teacher_id` hanya menggambarkan penugasan terkini.

| Kolom | Tipe |
|---|---|
| `id` | bigint |
| `class_id` | foreign |
| `synced_teacher_id` | foreign |
| `academic_year_id` | foreign |
| `semester_id` | foreign nullable jika penugasan setahun |
| `assigned_at` | datetime nullable |
| `ended_at` | datetime nullable |
| timestamps | timestamps |

Constraint unik disesuaikan dengan aturan sekolah agar satu kelas tidak mempunyai dua wali aktif pada periode yang sama.

### 9.7 Lampiran

Lampiran bukti ditunda ke P2. Jika diterapkan, gunakan tabel polymorphic atau tabel khusus dengan:

- disk/path privat;
- nama asli;
- MIME;
- ukuran;
- uploader;
- checksum opsional;
- timestamps.

Download harus melalui controller terotorisasi, bukan URL publik.

---

## 10. Integritas data dan periode

### Validasi membership

Pada setiap create/update/export:

1. Pastikan pengguna berhak atas `class_id` dan periode.
2. Pastikan siswa terdaftar pada kelas tersebut melalui `StudentEnrollment` untuk tahun pelajaran terpilih.
3. Untuk data lama tanpa periode, lakukan backfill terkontrol dan tandai data yang ambigu.
4. Jangan hanya memakai rule `exists:synced_students,id`.

### Histori wali kelas

- Saat sinkronisasi atau pengaturan wali kelas berlangsung, simpan snapshot penugasan pada `homeroom_assignments`.
- Akses periode aktif dapat memakai relasi terkini.
- Akses arsip memakai `homeroom_assignments`.
- Admin dapat mengoreksi histori melalui alur khusus dengan audit.

### Backfill

- Tambah kolom nullable terlebih dahulu.
- Backfill berdasarkan periode aktif dan data kelas yang dapat dipastikan.
- Record ambigu tidak ditebak; sediakan laporan atau command untuk pemeriksaan admin.
- Setelah data valid, pertimbangkan constraint non-null untuk record baru.

### Integritas biodata

- Endpoint siswa selalu mengambil profil dari `request()->user()->synced_student_id`; jangan menerima `student_id` bebas untuk mutation self-service.
- Nomor Indonesia menerima input `08...`, `62...`, atau `+62...`, lalu dinormalisasi secara konsisten.
- Nomor telepon disimpan sebagai string, bukan integer.
- Submit dan verifikasi dilakukan dalam transaction bersama validasi kontak utama.
- Siswa nonaktif dapat melihat atau memperbarui data hanya sesuai kebijakan akun; wali kelas tidak otomatis melihatnya pada daftar aktif.
- Perubahan pada profil verified menghapus status verified sampai diverifikasi ulang.
- Nilai sebelum dan sesudah perubahan penting tersedia melalui audit/version history tanpa menaruh nomor lengkap di log umum.

---

## 11. Backend boundaries

### Class/service baru yang direncanakan

- `HomeroomAccessService`: menyelesaikan kelas/periode yang boleh diakses.
- `HomeroomDashboardService`: merakit ringkasan tanpa query N+1.
- `StudentAttentionService`: menghasilkan sinyal deterministik beserta alasan.
- `StudentProfileService`: kelengkapan, normalisasi kontak, submit, verifikasi, dan revisi.
- `StudentProfileExportService`: dataset XLSX/DOCX dengan pembatasan cakupan.
- `StudentViolationReportService`: membentuk dataset laporan.
- `HomeroomDocxService`: mengisi template dan mengirim file.
- Policy untuk violation, follow-up, note, profile, dan report.

Controller harus tipis dan tidak menduplikasi aturan akses antar halaman.

### Perubahan controller existing

- `StudentViolationController`: tambah show/edit/update, lifecycle, periode, dan validasi membership.
- `HomeroomAttendanceController`: tambah sinyal keterlambatan dan penggunaan roster historis.
- `StudentProfileController`: self-service biodata untuk siswa.
- `HomeroomStudentProfileController`: daftar/detail/verifikasi dalam kelas wali.
- `AdminStudentProfileController`: rekap, verifikasi, dan export admin.
- Jangan menaruh seluruh generator DOCX di controller.

### Audit

Audit minimum:

- submit, revisi, dan verifikasi biodata;
- perubahan kontak utama;
- pembukaan detail biodata oleh wali/admin jika audit read diaktifkan;
- export biodata kelas atau sekolah;
- membuat, mengubah, menghapus, membuka kembali, dan menyelesaikan pelanggaran;
- menambah tindak lanjut;
- membuat/mengubah/menghapus catatan wali kelas;
- ekspor laporan individual dan rekap;
- koreksi histori penugasan wali kelas oleh admin.

---

## 12. Route contract

Route existing dipertahankan:

```text
GET    /homeroom/attendance
POST   /homeroom/attendance
GET    /homeroom/attendance/recap
GET    /homeroom/attendance/recap/export
GET    /homeroom/violations
POST   /homeroom/violations
DELETE /homeroom/violations/{violation}
```

Route baru yang direncanakan:

```text
GET    /homeroom
GET    /homeroom/students/{student}
GET    /homeroom/student-profiles
GET    /homeroom/student-profiles/{student}
POST   /homeroom/student-profiles/{student}/verify
POST   /homeroom/student-profiles/{student}/request-revision
GET    /homeroom/student-profiles/export/xlsx
GET    /homeroom/student-profiles/{student}/export/docx

GET    /homeroom/violations/{violation}
PUT    /homeroom/violations/{violation}
POST   /homeroom/violations/{violation}/follow-ups
POST   /homeroom/violations/{violation}/resolve
POST   /homeroom/violations/{violation}/reopen

GET    /homeroom/notes
POST   /homeroom/notes
PUT    /homeroom/notes/{note}
DELETE /homeroom/notes/{note}
POST   /homeroom/communications

GET    /homeroom/reports/student/{student}/docx
GET    /homeroom/reports/violations/docx

GET    /student/profile
PUT    /student/profile
POST   /student/profile/submit

GET    /admin/student-profiles
GET    /admin/student-profiles/export/xlsx
GET    /admin/student-profiles/{student}
POST   /admin/student-profiles/{student}/verify
POST   /admin/student-profiles/{student}/request-revision
GET    /admin/student-profiles/{student}/export/docx
```

Mutation siswa tidak menerima student ID dari form; siswa hanya dapat mengubah profil berdasarkan akun login. Nama route mengikuti konvensi Laravel dan diverifikasi sebelum implementasi. Route-model binding tidak menggantikan policy.

---

## 13. Struktur frontend

Halaman yang direncanakan:

```text
resources/js/pages/Homeroom/
├── Dashboard.tsx
├── Attendance.tsx
├── Recap.tsx
├── StudentProfiles.tsx
├── Violations.tsx
├── ViolationDetail.tsx
├── StudentProfile.tsx
├── Notes.tsx
└── Reports.tsx

resources/js/pages/StudentPortal/
└── Profile.tsx

resources/js/pages/Admin/
└── StudentProfiles.tsx
```

Komponen reusable:

```text
resources/js/components/Homeroom/
├── AttendanceSummary.tsx
├── AttentionReasonBadge.tsx
├── BiodataCompletenessBadge.tsx
├── GuardianContactCard.tsx
├── StudentTimeline.tsx
├── ViolationStatusBadge.tsx
├── FollowUpForm.tsx
└── ReportFilter.tsx
```

### Mobile contract

- Viewport minimum: 360 px.
- Tidak ada horizontal scroll pada daftar siswa atau kartu dashboard.
- Aksi utama dapat disentuh dengan target minimal sekitar 40 px.
- Form panjang memakai section atau modal yang jelas.
- Detail sensitif tidak ditampilkan penuh pada kartu ringkas.
- Filter periode tetap mudah diakses.
- Form biodata dipecah menjadi Identitas, Kontak Siswa, Alamat, dan Orang Tua/Wali.
- Siswa dapat menyimpan draft tanpa kehilangan isian.
- Kesalahan validasi ditampilkan pada section dan field terkait.
- Tombol export tidak boleh memicu export dua kali saat ditekan berulang.

---

## 14. Kebutuhan non-fungsional

### Keamanan dan privasi

- Semua query dibatasi kelas dan periode sebelum mengambil detail.
- Siswa hanya dapat membaca dan mengubah biodata miliknya sendiri.
- Guru mapel dan wali kelas lama tidak dapat membuka kontak/alamat terkini.
- Mutation memakai Form Request dan policy.
- Data internal tidak tersedia untuk siswa.
- Nomor telepon ditampilkan penuh hanya pada halaman terotorisasi; daftar ringkas dapat memakai masking.
- Export biodata dianggap tindakan sensitif dan wajib diaudit.
- Lampiran berada di storage privat.
- Export tidak menerima path template dari request.
- Uraian pelanggaran tidak dimasukkan ke analytics publik.

### Performa

- Dashboard kelas normal tidak melakukan query per siswa.
- Rekap kelengkapan biodata dihitung secara agregat, bukan query per profil.
- Daftar/timeline panjang memakai pagination atau lazy loading.
- Export satu kelas normal selesai sinkron dalam target 10 detik.
- Jika dataset besar melampaui batas, pertimbangkan queued export pada fase lanjutan.

### Auditability

- `recorded_by`, `updated_by`, dan timestamps dipertahankan.
- Submit, verify, revision request, dan perubahan kontak utama dapat dilacak.
- Soft delete digunakan untuk data catatan.
- Tindak lanjut bersifat append-oriented.
- Perubahan status penting dapat dilacak.

### Accessibility

- Status tidak dibedakan hanya melalui warna.
- Tombol H/S/I/A/T mempunyai label aksesibel.
- Dialog dapat ditutup dan fokus kembali ke pemicu.
- Dokumen DOCX memakai judul dan tabel yang terbaca.

---

## 15. Tahap implementasi wajib

### Phase 0 — Safety net dan integritas

- [x] Tambahkan feature test akses wali kelas, admin, guru non-wali, dan siswa.
- [x] Tambahkan test manipulasi `student_id` dari kelas lain.
- [x] Perbaiki validasi membership pada `StudentViolationController`.
- [x] Tambahkan test create/list/delete pelanggaran existing.
- [x] Tambahkan regression test absensi wali kelas dan ekspor XLSX.
- [x] Catat kontrak penggabungan status `T` mapel menjadi hadir + sinyal terlambat.

**Status:** Selesai 29 Juli 2026. Validasi membership juga diterapkan pada penyimpanan absensi wali kelas. Verifikasi: safety suite 9 test/58 assertion, Core Flows + safety suite 13 test/69 assertion, dan seluruh suite 53 test/564 assertion hijau.

**Definition of Done:** celah membership tertutup, boundary akses teruji, dan fitur existing tetap hijau. ✅

### Phase 1 — Arsip periode

- [x] Buat migration perluasan periode pada pelanggaran.
- [x] Buat `homeroom_assignments`.
- [x] Integrasikan penyimpanan histori penugasan dengan sync/pengaturan wali.
- [x] Gunakan `PeriodContext` pada halaman wali kelas.
- [x] Gunakan `StudentEnrollment` untuk roster periode.
- [x] Buat backfill dan laporan data ambigu.

**Status:** Selesai 29 Juli 2026. Arsip bersifat hanya-baca, akses kelas diselesaikan terpusat melalui histori penugasan, dan roster memakai enrollment tahun ajaran sehingga tidak berubah setelah siswa naik kelas. Sinkronisasi kelas serta aktivasi semester menyimpan snapshot wali kelas. Catatan lama hanya di-backfill bila rentang tanggal semester memberi hasil pasti; sisanya dilaporkan lewat `php artisan homeroom:period-audit`.

**Verifikasi:** migration naik/turun/naik berhasil pada `utiverse_testing`; migration lokal `utiverse` berhasil dengan 1 snapshot penugasan dan 0 catatan pelanggaran ambigu; focused suite 15 test/93 assertion; seluruh suite 59 test/599 assertion; Pint, TypeScript, production build, dan `git diff --check` hijau.

**Definition of Done:** wali dapat membuka periode aktif dan arsip yang sah tanpa roster berubah setelah kenaikan kelas. ✅

### Phase 2 — Biodata siswa dan orang tua/wali

- [x] Buat migration/model `student_profiles` dan `student_guardians`.
- [x] Buat self-service `/student/profile` dengan identitas sync read-only.
- [x] Implementasikan save draft, submit, revision request, dan verify.
- [x] Terapkan normalisasi nomor Indonesia dan validasi satu kontak utama.
- [x] Tambahkan kartu/banner kelengkapan pada Beranda siswa dan akses dari menu avatar.
- [x] Tambahkan daftar kelengkapan serta detail biodata untuk wali kelas.
- [x] Tambahkan tombol WhatsApp pada kontak valid dengan template pesan awal yang aman.
- [x] Tambahkan rekap biodata pada Data Siswa untuk admin.
- [x] Tambahkan policy agar siswa hanya mengubah data sendiri dan wali hanya melihat kelas aktif.
- [x] Tambahkan audit perubahan penting dan verifikasi.
- [x] Pastikan form nyaman pada HP 360 px.

**Status:** Selesai 29 Juli 2026. Identitas sinkronisasi tetap read-only; biodata lokal mendukung draft, submitted, verified, dan revision_requested. Wali kelas hanya dapat membuka siswa aktif pada kelas perwalian aktif, sedangkan wali lama dan guru non-wali ditolak. Admin memperoleh status/filter pada Data Siswa. Export massal XLSX diselesaikan lebih awal dengan nomor sebagai teks; DOCX individual tetap berada pada Phase 4 setelah dependency PHPWord dipasang.

**Verifikasi:** migration testing naik/turun/naik berhasil; migration development berada pada batch 24; focused StudentProfile suite 11 test/95 assertion; focused Homeroom suite 19 test/143 assertion; seluruh suite 70 test/694 assertion; scoped Pint hijau; TypeScript, production build, route contract, dan `git diff --check` hijau.

**Definition of Done:** siswa dapat mengisi dan mengajukan biodata dari HP, wali/admin dapat meminta revisi atau memverifikasi, dan tidak ada akses lintas siswa/kelas.

### Phase 3 — Lifecycle pelanggaran

- [x] Tambahkan status open/in_progress/resolved.
- [x] Implementasikan edit dengan audit.
- [x] Buat timeline tindak lanjut.
- [x] Implementasikan resolve dan reopen.
- [x] Ganti hard delete menjadi soft delete.
- [x] Tambahkan filter siswa, tingkat, status, dan rentang tanggal.
- [x] Pastikan UI nyaman pada HP 360 px.

**Status:** Selesai 29 Juli 2026. Kasus baru berstatus open, tindak lanjut mengubahnya menjadi in_progress, dan resolve menyimpan catatan, aktor, waktu, serta entri timeline. Reopen membutuhkan alasan dan mengembalikan kasus ke in_progress tanpa menghapus histori. Edit mempertahankan timeline, penghapusan memakai soft delete, dan arsip periode tetap hanya-baca. Daftar menggunakan kartu responsif serta filter siswa, tingkat, status, bulan, dan rentang tanggal; detail kasus mempunyai modal edit/tindak lanjut/resolve/reopen.

**Verifikasi:** migration development berada pada batch 25; migration database testing naik/turun/naik berhasil setelah hardening indeks foreign key MySQL; focused StudentViolation suite 7 test/77 assertion; focused Homeroom suite 19 test/143 assertion; seluruh suite 77 test/771 assertion; TypeScript, production build, route contract, scoped Pint, dan `git diff --check` hijau.

**Definition of Done:** satu kasus dapat berjalan dari pencatatan sampai selesai tanpa kehilangan histori.

### Phase 4 — Laporan dan export

- [x] Pasang dan kunci versi `phpoffice/phpword`.
- [x] Sediakan template DOCX sekolah.
- [x] Implementasikan dataset/report service terpisah.
- [x] Buat laporan pelanggaran individual siswa.
- [x] Buat rekap pelanggaran kelas.
- [x] Buat DOCX biodata individual.
- [x] Buat XLSX biodata kelas untuk wali dan XLSX terfilter untuk admin.
- [x] Pastikan nomor telepon diekspor sebagai teks.
- [x] Tambahkan dokumen nihil.
- [x] Tambahkan audit export dan pembersihan file sementara.
- [x] Tambahkan feature test otorisasi, header download, filter, serta isolasi kelas.

**Status:** Selesai 29 Juli 2026. PHPWord 1.4 dipasang dengan template DOCX privat yang memakai identitas sekolah dari Settings dan fallback UtiVerse. Wali kelas dapat mengunduh laporan individual sesuai filter dan rekap kelas, termasuk periode arsip yang memang pernah menjadi tanggung jawabnya. Wali, admin, dan siswa dapat mengunduh lembar biodata individual sesuai policy; laporan nihil, nama file aman, audit tanpa nomor telepon, dan penghapusan file sementara ikut diterapkan. Dependency export juga dinaikkan ke PhpSpreadsheet 5.9.0 dan Guzzle 7.15.2 setelah audit keamanan.

**Verifikasi:** focused HomeroomReportExport suite 5 test/44 assertion; seluruh suite 82 test/815 assertion; TypeScript, production build, scoped Pint, route contract, Composer audit, `git fsck`, validasi ZIP template, dan `git diff --check` hijau. Tiga sampel DOCX dibuka melalui Microsoft Word, dirender menjadi PNG, dan diperiksa visual per halaman; spot-check LibreOffice tetap masuk matriks manual karena LibreOffice tidak tersedia pada mesin pengembangan.

**Definition of Done:** DOCX dapat dibuka di Microsoft Word/LibreOffice, XLSX mempertahankan nomor telepon, isi sesuai filter, dan data tidak bocor lintas kelas.

### Phase 5 — Dashboard dan profil siswa

- [x] Buat dashboard wali kelas.
- [x] Tambahkan ringkasan kelengkapan biodata dan daftar perlu revisi.
- [x] Tambahkan ringkasan absensi hari ini.
- [x] Tambahkan agregasi keterlambatan mapel.
- [x] Implementasikan sinyal siswa perlu perhatian dengan alasan.
- [x] Buat profil dan timeline individual.
- [x] Pastikan query tidak N+1.

**Status:** Selesai 29 Juli 2026. Dashboard wali kelas menjadi pintu masuk terpadu untuk ringkasan siswa, kelengkapan biodata, absensi H/S/I/A, keterlambatan T, kasus aktif, tindak lanjut lewat tenggat, serta daftar siswa perlu perhatian dengan alasan deterministik. Ambang awal dapat diatur melalui Settings, dengan default kehadiran di bawah 80%, minimal 3 alpa, dan minimal 3 kejadian terlambat. Profil siswa menggabungkan tren absensi, kontak aktif, tombol WhatsApp yang sudah tersedia pada biodata, pelanggaran, dan tindak lanjut; kontak terkini disembunyikan dari wali periode lama.

**Verifikasi:** focused HomeroomDashboard suite 5 test/79 assertion; seluruh suite 87 test/894 assertion; TypeScript, production build, scoped Pint, Composer audit, npm audit, dan `git diff --check` hijau. Pengujian browser terautentikasi pada viewport 392 px dan 1440 px memastikan dashboard serta profil siswa tidak memiliki horizontal overflow atau error console. Query dashboard tetap konstan pada roster 14 siswa dan berada di bawah batas 12 query.

**Definition of Done:** wali dapat menemukan siswa yang perlu perhatian dan membuka konteks lengkap dari satu alur.

### Phase 6 — Catatan menyeluruh dan eskalasi

- [x] Buat catatan general/coaching/positive.
- [x] Integrasikan catatan ke timeline siswa.
- [x] Tambahkan opsi catatan pada laporan.
- [x] Tambahkan pencatatan komunikasi orang tua.
- [x] Rancang capability/role BK sebelum membuka akses.
- [x] Attachment privat tetap ditunda karena kebutuhan, tipe, dan batas ukuran belum dikonfirmasi.

**Status:** Selesai 29 Juli 2026. Catatan umum, pembinaan non-pelanggaran, dan pencapaian positif mempunyai periode, pencatat, audit create/update/delete, soft delete, filter, pagination, dan mode arsip hanya-baca. Profil siswa menyatukan catatan tersebut dengan pelanggaran, tindak lanjut, dan log komunikasi orang tua yang append-only. Komunikasi menyimpan snapshot nama/hubungan kontak, saluran, waktu, ringkasan, hasil, dan pencatat tanpa mengirim pesan otomatis. Laporan individual menyediakan pilihan eksplisit untuk menyertakan catatan serta komunikasi; default tetap tidak menyertakannya. Akses BK tidak dibuka: endpoint tetap dibatasi wali kelas yang sah dan admin sampai capability khusus disepakati.

**Verifikasi:** focused HomeroomDashboard suite 7 test/125 assertion; focused HomeroomReportExport suite 6 test/55 assertion; seluruh suite 90 test/951 assertion; migration development batch 26; TypeScript, production build, Pint, route contract, dan QA browser 360/1440 px hijau. DOCX sintetis dapat dibaca `python-docx`, mempunyai 6 tabel, dan mempertahankan seluruh teks catatan/komunikasi. Render visual belum dapat dinyatakan lulus karena LibreOffice tidak tersedia dan ekspor Word lokal melewati batas waktu aman.

**Definition of Done:** profil siswa tidak hanya berisi pelanggaran dan akses kolaborasi tetap terkontrol.

### Phase 7 — Hardening dan rollout

- [x] Tambahkan analytics tren tanpa leaderboard siswa.
- [x] Uji periode lama, siswa pindah kelas, dan pergantian wali.
- [x] Uji file DOCX dengan karakter Indonesia dan data panjang secara struktural.
- [x] Uji export XLSX biodata dengan nomor berawalan nol.
- [x] Uji perubahan nomor, kontak utama, siswa nonaktif, dan pergantian wali.
- [ ] Uji ulang analytics terbaru pada browser mobile 360 px serta desktop.
- [x] Audit seluruh query dan endpoint export.
- [x] Siapkan panduan penggunaan wali kelas.
- [x] Jalankan regression suite seluruh aplikasi.

**Status:** Checkpoint hardening otomatis selesai 29 Juli 2026. Dashboard mempunyai tren kelas maksimal enam bulan yang hanya menampilkan agregat H/S/I/A/T, jumlah kasus, catatan positif, dan komunikasi—tanpa nama, ranking, atau skor siswa. Query analytics bersifat konstan terhadap jumlah siswa. Panduan operasional tersedia di `docs/PANDUAN-WALI-KELAS.md`. Gate rollout yang tersisa adalah QA browser ulang setelah penambahan analytics serta render visual DOCX lintas Word/LibreOffice.

**Verifikasi:** focused HomeroomDashboard suite 7 test/138 assertion; focused HomeroomReportExport suite 6 test/56 assertion; seluruh suite 90 test/965 assertion; TypeScript, production build, Pint, Composer/npm audit, route contract, migrate rollback/up testing, dan `git diff --check` hijau. Coverage existing juga memverifikasi histori siswa/wali, pembatasan kontak arsip, normalisasi nomor, kontak utama, siswa nonaktif, XLSX sebagai teks, serta export lintas kelas.

**Definition of Done:** acceptance criteria, security matrix, regression test, dan manual QA lulus.

---

## 16. Acceptance test minimum

### Authorization

- [x] Wali kelas A tidak dapat membuka siswa atau kasus kelas B.
- [x] Wali kelas lama tidak dapat melihat biodata kontak terkini setelah penugasannya berakhir.
- [x] Guru non-wali mendapat 403 pada endpoint Homeroom Workspace.
- [x] Siswa tidak dapat membuka endpoint catatan atau laporan.
- [x] Siswa A tidak dapat membaca atau mengubah biodata siswa B.
- [x] Admin dapat mengakses sesuai policy dan mutasinya tercatat.
- [x] ID siswa valid dari kelas lain tetap ditolak.
- [x] Export menjalankan policy yang sama dengan tampilan.

### Biodata

- [x] Identitas hasil sinkronisasi tampil read-only bagi siswa.
- [x] Draft dapat disimpan walaupun belum lengkap.
- [x] Submit ditolak jika alamat atau kontak utama belum memenuhi syarat.
- [x] Satu profil submitted hanya mempunyai satu kontak utama.
- [x] Struktur satu wali tanpa ayah/ibu tetap dapat diajukan.
- [x] Permintaan revisi membutuhkan alasan yang terlihat oleh siswa.
- [x] Perubahan profil verified mengembalikan status ke submitted.
- [x] Nomor `0812...`, `62812...`, dan `+62812...` dinormalisasi secara konsisten.
- [x] Tombol WhatsApp menghasilkan URL `wa.me` dengan nomor `62...` yang benar.
- [x] Tombol WhatsApp tidak tampil jika nomor kosong atau tidak valid.
- [x] Pesan awal tidak memuat pelanggaran, nilai, atau data sensitif secara otomatis.
- [x] Membuka WhatsApp tidak mengubah status apa pun menjadi “terkirim”.
- [x] Nomor telepon tidak diperlakukan sebagai angka.
- [x] Siswa nonaktif tidak muncul pada daftar aktif tanpa filter eksplisit.
- [x] Wali/admin dapat melihat waktu pembaruan dan verifikasi terakhir.

### Periode dan roster

- [x] Siswa naik kelas tidak hilang dari laporan periode lama.
- [x] Wali baru tidak otomatis menjadi pemilik data periode lama.
- [x] Wali lama dapat membuka kelas yang memang menjadi tanggung jawabnya pada periode lama.
- [x] Filter semester harus berada dalam tahun pelajaran yang dipilih.
- [ ] Data tanpa periode yang ambigu tidak dimasukkan diam-diam.

### Pelanggaran

- [x] Pelanggaran baru berstatus open.
- [x] Edit menyimpan aktor perubahan.
- [x] Banyak tindak lanjut tersimpan kronologis.
- [x] Resolve membutuhkan catatan penyelesaian.
- [x] Reopen membutuhkan alasan.
- [x] Soft deleted record tidak muncul pada daftar normal.

### Catatan wali kelas dan komunikasi

- [x] Catatan general/coaching/positive tidak masuk hitungan kasus pelanggaran.
- [x] Catatan menyimpan periode, pencatat, aktor pembaruan, audit, dan soft delete.
- [x] Wali kelas lain serta mode arsip tidak dapat mengubah catatan.
- [x] Guardian dari siswa lain ditolak pada log komunikasi.
- [x] Log komunikasi bersifat append-only dan tidak menandai pesan sebagai terkirim.
- [x] Timeline individual menggabungkan catatan dan komunikasi secara kronologis.
- [x] Catatan/komunikasi hanya masuk laporan individual jika dipilih eksplisit.

### Absensi

- [x] Status T mapel tetap tersimpan sebagai T.
- [x] Status T dihitung hadir pada status harian fallback.
- [x] Jumlah T tampil sebagai keterlambatan terpisah.
- [x] Isian manual wali kelas tetap diprioritaskan sesuai kontrak existing.
- [x] Ekspor XLSX existing tetap dapat diunduh.

### DOCX

- [x] Laporan individual hanya memuat siswa yang dipilih.
- [x] Rekap kelas menghormati periode dan filter.
- [x] Dokumen nihil dapat dibuka.
- [x] Nama Indonesia, simbol, dan teks multi-baris tidak rusak.
- [x] Nama file aman.
- [x] File sementara dibersihkan.
- [ ] Dokumen dapat dibuka di Microsoft Word dan LibreOffice.

### Export biodata

- [x] Wali hanya dapat mengekspor kelas aktif yang menjadi tanggung jawabnya.
- [x] Admin dapat mengekspor sesuai filter kelas/status.
- [x] Nomor berawalan nol tidak berubah di XLSX.
- [x] XLSX membedakan kontak siswa dan kontak utama orang tua/wali.
- [x] DOCX individual memuat alamat dan seluruh kontak wali yang dipilih.
- [x] Export tercatat tanpa menaruh nomor lengkap di audit description.
- [x] Wali kelas lama tidak dapat mengekspor kontak terkini.

### Mobile UX

- [x] Dashboard dan daftar nyaman pada 360 px.
- [x] Tidak ada horizontal scroll.
- [x] Form pelanggaran dapat diselesaikan dari HP.
- [ ] Form biodata dapat disimpan sebagai draft dan diajukan dari HP.
- [ ] Tombol WhatsApp dapat membuka chat dari HP dan laptop tanpa menyebabkan navigasi aplikasi hilang.
- [x] Timeline dan modal catatan tetap terbaca.
- [x] Aksi berisiko mempunyai konfirmasi yang jelas.

---

## 17. Verification commands

Jalankan dari root repo setelah setiap fase:

```powershell
php artisan route:list
php artisan test --filter=Homeroom
php artisan test --filter=StudentViolation
vendor\bin\pint --test
npm run typecheck
npm run build
git diff --check
```

Untuk perubahan migration:

- gunakan database testing melalui `RefreshDatabase`;
- verifikasi migrate dan rollback migration baru;
- jangan menjalankan `migrate:fresh` pada database development berisi data tanpa persetujuan eksplisit.

Manual matrix sebelum rilis:

1. Login sebagai wali kelas dengan satu kelas aktif.
2. Login sebagai wali kelas dengan histori periode lama.
3. Login sebagai guru non-wali.
4. Login sebagai admin.
5. Login sebagai siswa dan isi biodata dari draft sampai submitted.
6. Minta revisi sebagai wali lalu ajukan ulang sebagai siswa.
7. Uji siswa aktif, siswa pindah kelas, dan siswa nonaktif.
8. Uji satu wali, banyak wali, dan pergantian kontak utama.
9. Uji data nihil, satu kasus, dan banyak kasus.
10. Uji DOCX individual/rekap di Word/LibreOffice dan XLSX biodata di Excel/LibreOffice.
11. Uji viewport 360 px dan desktop.

---

## 18. Current repo map yang sudah diverifikasi

Fondasi existing:

- `routes/web.php`: route wali kelas berada dalam group `can:guru`.
- `resources/js/layouts/AuthenticatedLayout.tsx`: menu Wali Kelas diawali Ringkasan Wali Kelas, lalu Biodata, Absensi Harian, Catatan Pelanggaran, dan Voting Kelas.
- `app/Http/Controllers/HomeroomDashboardController.php` dan `HomeroomStudentController.php`: dashboard kelas serta profil siswa terpadu dengan otorisasi kelas/periode.
- `app/Http/Controllers/HomeroomNoteController.php` dan `HomeroomCommunicationController.php`: lifecycle catatan non-pelanggaran dan log komunikasi append-only.
- `app/Services/HomeroomDashboardService.php`, `HomeroomAnalyticsService.php`, `HomeroomAttendanceSummaryService.php`, `StudentAttentionService.php`, dan `HomeroomStudentOverviewService.php`: agregasi ringkasan/tren kelas, T terpisah, sinyal deterministik, serta timeline individual tanpa N+1.
- `resources/js/pages/Homeroom/Dashboard.tsx`, `StudentShow.tsx`, dan `Notes.tsx`: dashboard responsif, profil siswa terpadu, serta daftar/form catatan wali.
- `app/Http/Controllers/HomeroomAttendanceController.php`: absensi harian, validasi membership siswa, merge dengan presensi mapel, rekap, dan ekspor XLSX.
- `resources/js/pages/Homeroom/Attendance.tsx`: input H/S/I/A dan catatan per siswa.
- `resources/js/pages/Homeroom/Recap.tsx`: ringkasan bulanan dan tombol ekspor Excel.
- `app/Http/Controllers/StudentViolationController.php`: daftar/detail, create/edit, tindak lanjut, resolve/reopen, soft delete, validasi membership/periode, dan filter lengkap.
- `app/Models/StudentViolation.php` dan `StudentViolationFollowUp.php`: lifecycle kasus, soft delete, aktor perubahan, penyelesaian, tenggat, dan timeline.
- `resources/js/pages/Homeroom/Violations.tsx` dan `ViolationShow.tsx`: daftar kartu responsif, filter, form kasus, detail, timeline, serta aksi lifecycle.
- `resources/js/pages/StudentProfile/Edit.tsx`: Biodata Saya dengan identitas sinkronisasi read-only dan kontak orang tua/wali fleksibel.
- `database/migrations/2026_07_21_115811_create_student_violations_table.php`: skema awal pelanggaran.
- `app/Models/SyncedClass.php`: wali kelas terkini melalui `homeroom_teacher_id`.
- `app/Models/StudentEnrollment.php`: fondasi histori kelas siswa per tahun pelajaran.
- `app/Support/PeriodContext.php`: resolver periode akademik.
- `tests/Feature/HomeroomSafetyTest.php`: safety net akses, CRUD pelanggaran, membership, status T, dan ekspor XLSX.
- `tests/Feature/HomeroomDashboardTest.php`: agregasi dashboard, profil/timeline, isolasi kelas/periode, pembatasan kontak arsip, filter semester, dan batas query.
- `tests/Feature/StudentViolationLifecycleTest.php`: lifecycle, timeline, filter, audit, isolasi kelas/arsip, dan soft delete.
- `composer.json`: mempunyai PhpSpreadsheet dan PhpWord untuk export XLSX/DOCX.
- `docs/PANDUAN-WALI-KELAS.md`: panduan operasional Homeroom Workspace untuk wali kelas.

Gap yang harus diselesaikan:

- akses kolaboratif BK tetap ditutup sampai role/capability dan batas cakupannya disepakati;
- attachment privat tetap ditunda sampai jenis bukti, retensi, dan batas ukuran dikonfirmasi.

---

## 19. Keputusan produk

1. Nama payung fitur adalah **Homeroom Workspace / Ruang Kerja Wali Kelas**.
2. Catatan pelanggaran tetap menjadi domain tersendiri.
3. Catatan positif dan pembinaan non-pelanggaran tidak dimasukkan ke hitungan kasus.
4. DOCX menjadi format laporan resmi pertama; XLSX rekap absensi tetap dipertahankan.
5. Biodata siswa diisi melalui `/student/profile`; `/settings` tetap untuk akun/password.
6. Identitas dari sinkronisasi read-only, sedangkan kontak/alamat disimpan sebagai data pelengkap lokal.
7. Orang tua/wali memakai relasi one-to-many dengan satu kontak utama, bukan kolom ayah/ibu yang kaku.
8. XLSX menjadi format export massal biodata; DOCX digunakan untuk lembar individual.
9. Wali kelas lama tidak otomatis boleh melihat kontak terkini.
10. Tombol WhatsApp hanya membuka chat melalui `wa.me`; pengiriman tetap dilakukan pengguna di WhatsApp.
11. Pesan WhatsApp awal tidak menyertakan data sensitif secara otomatis.
12. Status T tetap milik absensi mapel dan menjadi sinyal keterlambatan bagi wali kelas.
13. Penilaian “perlu perhatian” harus deterministik dan dapat dijelaskan.
14. Tidak ada XP negatif atau leaderboard pelanggaran.
15. Periode dan membership harus benar sebelum fitur analytics diperluas.
16. Komunikasi orang tua dicatat manual pada versi pertama; pengiriman otomatis ditunda.
17. Akses BK memerlukan keputusan role/capability tersendiri.

---

## 20. Pertanyaan terbuka

Hal berikut perlu diputuskan sebelum fase terkait:

1. Apakah nomor HP siswa wajib atau tetap opsional.
2. Daftar detail alamat yang diwajibkan sekolah.
3. Apakah pekerjaan orang tua/wali perlu wajib atau opsional.
4. Apakah wali kelas boleh memperbaiki biodata langsung atau hanya meminta revisi.
5. Apakah export admin seluruh sekolah memerlukan konfirmasi tambahan.
6. Template kop DOCX resmi sekolah dan siapa saja yang menandatangani.
7. Apakah laporan individual menyertakan rekap kehadiran secara default.
8. Apakah catatan positif ditampilkan pada laporan orang tua secara default atau opt-in.
9. Apakah satu kelas dapat mempunyai wali pengganti dalam semester yang sama.
10. Siapa yang boleh membuka kembali kasus resolved.
11. Apakah BK akan memakai role baru atau capability pada akun guru.
12. Jenis dan batas ukuran attachment jika fase lampiran dijalankan.
13. Ambang awal siswa perlu perhatian untuk alpa dan keterlambatan.

Keputusan detail export/template tidak menghalangi Phase 0–2. Field wajib biodata perlu diputuskan sebelum implementasi final form Phase 2.

---

## 21. Definition of complete

Homeroom Workspace dinyatakan siap dipakai jika:

1. Wali kelas hanya dapat mengakses siswa dari kelas dan periode yang sah.
2. Siswa dapat mengisi biodata sendiri dan hanya melihat datanya sendiri.
3. Wali/admin dapat memverifikasi biodata dan mengekspor data sesuai kewenangan.
4. Nomor telepon tetap utuh pada XLSX dan tidak bocor kepada pengguna lain.
5. Riwayat tetap benar setelah siswa naik/pindah kelas dan wali kelas berganti.
6. Pelanggaran dapat dicatat, ditindaklanjuti, diselesaikan, dan dibuka kembali dengan audit.
7. Laporan individual dan rekap DOCX dapat dibuka serta tidak bocor lintas kelas.
8. Dashboard menjelaskan alasan setiap siswa ditandai perlu perhatian.
9. Keterlambatan mapel terlihat tanpa mengubah arti status harian.
10. Catatan positif dan pembinaan dapat disimpan terpisah dari pelanggaran.
11. Absensi mapel, absensi wali kelas, ekspor XLSX, dan Voting Kelas tetap berfungsi.
12. Automated test, typecheck, formatting check, production build, dan manual QA mobile lulus.

Prioritas produk: **integritas data dan histori periode terlebih dahulu, kemudian biodata self-service, lifecycle, serta laporan; analytics dan kolaborasi dikerjakan setelah fondasi tersebut stabil.**
