# Panduan Area Super Admin

Halaman ini menjelaskan empat halaman di balik `/admin/*` — apa yang bisa
dikerjakan di sana, dan aturan yang menahannya. Ditujukan untuk tim dan untuk
siapa pun yang memegang akun super admin, bukan untuk pengguna umum.

> Acuan kebenarannya tetap [Spesifikasi Fitur](spesifikasi-fitur.md). Kalau
> halaman ini berbeda, yang berlaku spesifikasi.

---

## Watak Peran Super Admin

Super admin adalah **penjaga data master**, bukan pengelola eksekusi:

- Mengelola user, divisi, arsip proyek, dan jejak audit.
- **Membaca** seluruh Scuto — kecuali tugas pribadi orang lain, yang memang tidak
  pernah masuk query mana pun.
- **Tidak menulis** apa pun di ranah operasional: tidak membuat, mengubah, atau
  menghapus proyek dan tugas; tidak me-review; tidak berkomentar; tidak mengelola
  anggota proyek.

Kelonggaran bacanya dipasang hanya untuk kemampuan `view`/`viewAny`. Gate tulis —
`update`, `delete`, `review`, `discuss`, `manageMembers` — tidak ikut, jadi super
admin bisa membuka apa pun tanpa bisa mengubahnya.

Seluruh route `/admin/*` berada di balik gate `administer-system`. Menu
Administration di sidebar hanya dirender untuk super admin, tapi **yang menahan
adalah gate-nya**, bukan menu yang disembunyikan — mengetik URL-nya tetap
menghasilkan `403`.

Super admin juga tidak punya menu **My Tasks** sama sekali; route-nya dijaga gate
tersendiri, jadi membuat dan membaca pun tertutup.

---

## User Management — `/admin/users`

Daftar user, 15 baris per halaman, diurutkan nama. Tersedia pencarian
**nama/NIK/email** dan penyaring status aktif–nonaktif, keduanya berjalan di
server.

| Aksi | Keterangan |
|------|------------|
| **Add User** | Nama, NIK, email, kata sandi awal, dan satu penempatan divisi (opsional). Semuanya satu transaksi. |
| **Edit user** | Nama, NIK, email. Mengubah email mengosongkan verifikasinya. |
| **Division memberships** | Dikirim sebagai *sync* — divisi yang tidak ikut dikirim akan dilepas. Ini jalur untuk pemetaan lebih dari satu divisi. |
| **Change password** | Menyetel kata sandi baru; otomatis menyalakan wajib-ganti. |
| **Require password change** | Mewajibkan penggantian pada login berikutnya, tanpa mengganti kata sandinya sekarang. |
| **Deactivate / Activate** | Pengganti "hapus user". Tombolnya mati untuk akun sendiri. |

Hal-hal yang perlu diketahui sebelum memakainya:

- **Untuk sekarang akun hanya dinonaktifkan, belum bisa dihapus.** Belum ada route
  `destroy` di sini. Penghapusan akun **sudah diputuskan menjadi wewenang super
  admin** (K9 revisi, spesifikasi 01.3), tapi menunggu prasyaratnya: banyak jejak
  menggantung pada `users.id`, sebagian dengan `cascade` (proyek yang pernah ia
  buat ikut lenyap) dan sebagian dengan `restrict` (penghapusan gagal di tengah
  jalan). Keenam foreign key itu dibereskan lebih dulu, tombolnya menyusul.
- **Hapus akun sendiri sedang dicabut.** Kartu *Delete account* di Settings →
  Profile masih hidup dan bertentangan dengan aturan di atas — pengelolaan akun
  bukan wewenang pemiliknya. Rinciannya di spesifikasi 01.6.
- **Penonaktifan ditolak** selama user masih menjadi **satu-satunya owner** sebuah
  proyek aktif; pesan errornya menyebut proyek mana yang menahan. Proyek terarsip
  tidak ikut menahan, dan reaktivasi tidak diperiksa sama sekali.
- **`must_change_password` selalu menyala** pada akun yang lahir dari form ini —
  kata sandi awalnya diketahui super admin, jadi tidak ada alasan
  mempertahankannya.
- **NIK wajib mengikuti pola `^[A-Z]+-[0-9]+$`** (mis. `SK-000123`). Huruf kecil
  **ditolak**, bukan dinaikkan otomatis, karena pencocokan login bersandar pada
  nilai persis.
- **Form ini tidak bisa membuat super admin.** Kolom `role` tidak pernah disentuh
  dan berada di luar `$fillable`; setiap akun dari antarmuka selalu berperan user
  biasa.

### Dari mana super admin lahir

Hanya lewat CLI, dan hanya ada **satu kursi** super admin:

```bash
# Instalasi baru — password diminta lewat prompt tersembunyi,
# bukan argumen, agar tidak tersimpan di riwayat shell.
php artisan user:create-super-admin {nik} {name} {email}

# Mengangkat penerus dari akun yang sudah ada.
# Ditolak selama kursinya masih terisi:
php artisan user:set-role {nik} super_admin
php artisan user:set-role {nik} user     # turunkan pemegang lama dulu
```

**Tidak ada jalur seeder, dan itu disengaja** — menaruh super admin di
`migrate:fresh --seed` berarti menuliskan kata sandi akun paling berwenang ke
dalam repositori.

---

## Division Management — `/admin/divisions`

Divisi hanya dibuat, diubah, dan dihapus dari sini. Kolom daftarnya: nama,
**prefix**, jumlah anggota, dan beban kerjanya.

| Aksi | Keterangan |
|------|------------|
| **Edit division** | Nama, prefix, deskripsi. |
| **Manage members** | Satu-satunya jalur menambah, mengeluarkan, dan mengubah peran anggota divisi — termasuk jabatan bebas (`role_label`). |
| **Delete division** | Mati selama divisi masih punya tugas, proyek, atau template recurring. |

Yang perlu diingat:

- **Prefix menjadi awalan kode tugas** (`SK-000012`) dan **terkunci begitu divisi
  punya tugas** — mengubahnya setelah kode terbit akan membuat satu divisi punya
  dua pola kode.
- **Slug tidak ikut berubah** saat nama diperbarui, supaya URL yang sudah
  dibagikan tidak mati.
- **Halaman Members di dalam divisi bersifat baca-saja.** Admin dan Supervisor
  divisi tidak mengelola keanggotaan — mereka hanya mengelola template recurring
  task, proyek yang mereka buat, dan tugas divisi.
- **Pelepasan anggota ditolak** selama ia masih memegang tugas terbuka di divisi
  itu atau masih menjadi pelaksana sebuah template recurring. Menurunkan seseorang
  menjadi `viewer` diperlakukan sama dengan melepasnya sejauh menyangkut template.
- Penghapusan divisi bersifat *soft delete*, dan keanggotaannya dilepas dalam satu
  transaksi.

---

## Activity Log — `/admin/activities`

Jejak perubahan seluruh aplikasi, bersifat **hanya-tambah**: tidak ada endpoint
yang mengubah atau menghapus barisnya.

**Yang tercatat:** pembuatan (termasuk nilai awalnya), perubahan beserta diff per
kolom, penghapusan, pemulihan, dan penghapusan permanen — untuk User, Division,
DivisionMember, Project, RecurringTask, Task, serta turunan task (Comment,
Attachment, Proof, TaskReview, TaskDeadlineRequest). Login, logout, dan percobaan
login gagal dicatat lewat listener terpisah; pada login gagal hanya NIK yang
dicoba yang disimpan.

**Yang sengaja tidak tercatat:**

- **Tugas pribadi** — mengauditnya berarti membocorkan isinya ke halaman yang
  justru dibaca super admin.
- Kolom teknis seperti `updated_at`, `deleted_at`, dan seluruh penanda
  `*_notified_at` (pola akhirannya yang dijaga, bukan daftar namanya, supaya
  penanda berikutnya ikut aman).
- Kolom sensitif diganti `[redacted]` — nama kolomnya tetap tercatat, isinya
  tidak.

**Penyaringan & ekspor:** kata kunci (aksi, pelaku, label subjek, deskripsi),
divisi, jenis aksi, dan rentang tanggal `Y-m-d`. Tombol **Export CSV** mengikuti
filter yang sedang aktif, di-stream per 500 baris, diawali BOM UTF-8, dan sel yang
diawali `=`, `+`, `-`, `@`, tab, atau carriage return diberi kutip satu untuk
meredam CSV formula injection.

> **Log ini sengaja tidak dibersihkan.** Yang memicu peninjauan ulang bukan
> kalender melainkan halamannya sendiri mulai terasa lambat — dan yang tumbuh
> paling cepat adalah percobaan login gagal.

---

## Archives — `/admin/archives`

Daftar proyek yang dihapus (soft delete), lengkap dengan divisi, jumlah tugas,
waktu penghapusan, dan pelakunya — nama pelaku diambil dari jejak audit karena
tabel proyek tidak menyimpannya. Tersedia pencarian nama/deskripsi dan penyaring
divisi.

| Aksi | Akibatnya |
|------|-----------|
| **Restore project** | Mengembalikan barisnya. Tugas memang tidak pernah ikut terhapus, hanya tersembunyi lewat relasi proyeknya. |
| **Delete permanently** | Menghapus tugas induk satu per satu agar tiap penghapusan tercatat di audit; komentar, bukti, dan lampiran ikut terbersihkan; berkas fisiknya dihapus setelah transaksi commit. |

> **Retensi 30 hari.** Proyek terhapus dibersihkan permanen otomatis oleh
> `projects:purge-archived`, terjadwal harian pukul 02:00. Jalur penghapusannya
> **satu** dan dipakai bersama oleh tombol *Delete permanently* dan command
> terjadwal — memanggil `forceDelete` langsung akan meninggalkan berkas yatim di
> penyimpanan.

---

## Yang Tidak Ada di Area Ini

Jangan menjanjikannya saat demo:

- **Dashboard khusus super admin** (jumlah user, divisi, proyek per status). Super
  admin melihat dashboard yang sama dengan semua orang — dan karena biasanya bukan
  anggota divisi mana pun, isinya cenderung kosong.
- **Log per divisi atau per user.** Permission `read-division-activity-log` dan
  `read-my-activity-log` tercantum di `permission_group.json` tapi belum punya
  halaman maupun route. Yang dilihat non-super-admin hanya timeline per proyek di
  tab Info.
- **Penghapusan akun user** — sudah diputuskan akan ada di sini, tapi belum dibangun;
  lihat catatan prasyaratnya di atas.
- **Ekspor CSV** selain Activity Log.

---

## Catatan Arsitektur yang Mudah Terlewat

- **`permission_group.json` adalah dokumen, bukan mesin izin.** Dari seluruh
  isinya, hanya nama scope `system` yang benar-benar dipakai lewat gate
  `administer-system`. Otorisasi sesungguhnya hidup di `ProjectPolicy`,
  `TaskPolicy`, `DivisionPolicy`, dan `PersonalTaskPolicy` — **kalau keduanya
  berbeda, yang berlaku policy.**
- **Query daftar punya cabang super admin tersendiri** (proyek, media, recurring),
  karena scope-nya ada di query, bukan di gate.
- **Daftar divisi memang terbuka untuk semua user**, sebagai direktori kantor.
  Yang terbuka hanya nama, deskripsi, dan anggotanya; isi divisinya tetap dijaga.
