Roadmap
# Schoolmantic — Roadmap ke Produksi
Estimasi total: ±20 minggu kerja (solo dev fullstack). Setiap fase menghasilkan deliverable yang bisa langsung diuji.
---
## Fase 1 — Foundation ✅ SELESAI
**Target:** Project scaffold, skema DB, seed data.
- [x] Konsep aplikasi & keputusan arsitektur
- [x] Setup Bun + Hono + Drizzle ORM + PostgreSQL
- [x] 32 tabel (enums, 12 domain schema files)
- [x] Migration awal (`0000_breezy_avengers.sql`)
- [x] Seed data: 1 sekolah, 10 guru, 50 siswa, 50 wali, 2 kelas, jadwal, notif template, subscription plans
- [x] `.env`, `.gitignore`, `drizzle.config.ts`
---
## Fase 2 — API: Auth & Tenant Guard ✅ SELESAI
**Target:** Semua role bisa login, JWT bekerja, tenant context aman.
- [x] Hono server entry (`src/index.ts`) + middleware stack (CORS, logger)
- [x] Helper normalisasi HP (`+62...`) dan lowercase email (`src/lib/phone.ts`)
- [x] `POST /api/v1/auth/login` — login via email atau HP, return JWT + refresh token + `tenant_options[]`
- [x] `POST /api/v1/auth/refresh` — rotate refresh token
- [x] `POST /api/v1/auth/logout` — revoke refresh token
- [x] `POST /api/v1/auth/change-password` — ganti password + revoke semua refresh token
- [x] `GET /api/v1/auth/me` — info user + tenant_options aktif
- [x] Middleware `requireAuth` (`src/middleware/requireAuth.ts`) — verifikasi JWT HS256
- [x] Middleware `requireSchoolContext` (`src/middleware/requireSchoolContext.ts`) — cek membership + cek suspension
- [x] Guards: `requireSchoolAdmin()`, `requireHomeroomOrAdmin()`, `requireSaasOwner()`
- [x] Rate limiter in-memory per-IP untuk login (maks 10 req/menit, `src/lib/rateLimit.ts`)
- [x] Test: tenant isolation — SaaS owner bukan member → 403, school ID tidak ada → 403
- [x] Test: multi-role — tenant_options berisi semua membership aktif user
- [x] Bug fix: Hono 4.12.x requires explicit `'HS256'` arg di `verify()`
---
## Fase 3 — API: Master Data (CRUD) ✅ SELESAI
**Target:** School admin bisa kelola semua data master via API.
- [x] `GET/PUT /api/v1/schools/:id` — profil sekolah (GPS, TZ, settings)
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/employees` (+ ?search, ?type)
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/students` (+ ?search, ?classId)
- [x] `GET/POST/DELETE /api/v1/schools/:id/guardians` (+ ?search)
- [x] `POST/DELETE /api/v1/schools/:id/guardian-students` — relasi wali-siswa
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/classes` + `GET /classes/:id/students`
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/subjects`
- [x] `GET/POST/DELETE /api/v1/schools/:id/teaching-assignments`
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/academic-years` + semesters
- [x] `POST /api/v1/schools/:id/enrollments` — assign siswa ke kelas/tahun ajaran
- [x] `GET/POST/PUT/DELETE /api/v1/schools/:id/schedule-templates` + slots
- [x] `POST /api/v1/schools/:id/class-schedule-assignments`
- [x] `POST /api/v1/schools/:id/employee-schedule-assignments`
- [x] `GET/POST/DELETE /api/v1/schools/:id/holidays` (+ ?year)
- [x] `GET/POST/DELETE /api/v1/schools/:id/schedule-overrides` (+ ?dateFrom, ?dateTo)
- [x] Soft delete di semua resource — partial unique index aktif
- [x] Smoke test semua endpoint berhasil
---
## Fase 4 — API: Absensi
**Target:** Semua sumber absensi (manual, biofinger, selfie) bekerja. Laporan harian akurat.
**Estimasi:** 2 minggu
- [ ] Helper resolusi jadwal: cari override → fallback ke template kelas/pegawai
- [ ] Helper status absensi: HADIR / TERLAMBAT / LIBUR berdasarkan jam + jadwal + holidays
- [ ] `POST /api/v1/schools/:id/attendance/students/manual` — input manual oleh wali kelas / school admin
- [ ] `POST /api/v1/schools/:id/attendance/employees/manual`
- [ ] `POST /api/v1/schools/:id/attendance/biofinger-event` — ingest raw event dari mesin (→ `attendance_events`, rekonsiliasi ke `attendance_daily_*`)
- [ ] `POST /api/v1/schools/:id/attendance/employees/selfie` — upload selfie + GPS, validasi radius, simpan ke S3
- [ ] Presigned URL endpoint untuk upload selfie ke S3 (MinIO dev / S3 prod)
- [ ] `GET /api/v1/schools/:id/attendance/students` — filter by class, date, status
- [ ] `GET /api/v1/schools/:id/attendance/employees` — filter by date, status
- [ ] `PUT /api/v1/schools/:id/attendance/:entryId` — koreksi absensi (+ audit log)
- [ ] Hak akses: wali kelas hanya bisa input/edit kelas miliknya
- [ ] Skema & endpoint stub face recognition (`POST /api/v1/schools/:id/attendance/face-event`) — implementasi model menyusul
---
## Fase 5 — API: Perizinan (Izin)
**Target:** Wali siswa bisa submit izin, wali kelas / school admin approve.
**Estimasi:** 3–4 hari
- [ ] `POST /api/v1/schools/:id/leave-requests` — submit (by wali siswa, pegawai, atau school admin)
- [ ] Upload dokumen opsional (presigned URL S3)
- [ ] `GET /api/v1/schools/:id/leave-requests` — filter by status, subject, date
- [ ] `PUT /api/v1/schools/:id/leave-requests/:id/approve`
- [ ] `PUT /api/v1/schools/:id/leave-requests/:id/reject`
- [ ] `PUT /api/v1/schools/:id/leave-requests/:id/cancel`
- [ ] Saat APPROVED → sync status ke `attendance_daily_*` di rentang tanggal terkait
- [ ] Audit log: setiap perubahan status izin
---
## Fase 6 — API: Notifikasi
**Target:** Outbox terisi otomatis saat event absensi/izin, worker eksternal siap di-hook.
**Estimasi:** 3–4 hari
- [ ] `GET/POST/PUT/DELETE /api/v1/schools/:id/notification-templates`
- [ ] Service `triggerNotification(schoolId, templateCode, data)` — render template, insert ke outbox per channel
- [ ] Hook notifikasi ke: siswa hadir, siswa pulang, siswa tidak hadir, izin approved/rejected
- [ ] `GET /api/v1/schools/:id/notifications/outbox` — SaaS owner / school admin monitoring
- [ ] FCM push: kirim `PUSH` dari outbox menggunakan Firebase Admin SDK
- [ ] WA/Telegram: endpoint polling untuk worker eksternal `GET /api/v1/internal/notifications/pending?channel=WHATSAPP`
- [ ] `PATCH /api/v1/internal/notifications/:id/status` — update SENT/FAILED dari worker eksternal
- [ ] Device push token: `POST /api/v1/auth/push-token`, `DELETE /api/v1/auth/push-token`
---
## Fase 7 — API: Berlangganan & Billing
**Target:** SaaS owner bisa kelola paket dan approve pembayaran. Trial expiry otomatis.
**Estimasi:** 3–4 hari
- [ ] `GET /api/v1/saas/subscription-plans` (SaaS owner)
- [ ] `GET /api/v1/schools/:id/subscription` — info paket aktif, sisa trial, student count
- [ ] `POST /api/v1/schools/:id/payments` — submit bukti pembayaran (presigned S3 upload)
- [ ] `PUT /api/v1/saas/payments/:id/approve` — SaaS owner approve → update `school_subscriptions.status = ACTIVE`
- [ ] `PUT /api/v1/saas/payments/:id/reject`
- [ ] Cron job / Bun scheduled task:
- Setiap hari: cek `trial_ends_at` → set GRACE
- Setiap hari: cek GRACE sudah 7 hari → set SUSPENDED
- Hitung `billing_student_count` tiap awal bulan
- [ ] Middleware: block request ke endpoint sekolah kalau status SUSPENDED (return 402)
---
## Fase 8 — API: SaaS Owner & Pelanggan Dashboard
**Target:** SaaS owner dan pelanggan bisa lihat dan kelola dari API.
**Estimasi:** 2–3 hari
- [ ] `GET /api/v1/saas/customers` — daftar pelanggan, filter status
- [ ] `PUT /api/v1/saas/customers/:id/activate`
- [ ] `PUT /api/v1/saas/customers/:id/deactivate`
- [ ] `GET /api/v1/saas/stats` — total sekolah, total siswa, revenue summary
- [ ] `GET /api/v1/customers/me/schools` — daftar sekolah milik pelanggan
- [ ] `POST /api/v1/customers/me/schools` — tambah sekolah baru + pilih paket
- [ ] `GET /api/v1/schools/:id/dashboard` — jumlah pegawai, siswa, hadir hari ini (per kategori)
---
## Fase 9 — API: Laporan & Export
**Target:** Semua laporan standar tersedia, bisa export PDF dan Excel.
**Estimasi:** 1 minggu
- [ ] `GET /api/v1/schools/:id/reports/class-monthly?classId=&month=` — rekap absensi per kelas per bulan
- [ ] `GET /api/v1/schools/:id/reports/student?studentId=&from=&to=` — rekap per siswa
- [ ] `GET /api/v1/schools/:id/reports/school-stats?month=` — statistik dashboard (grafik bulanan, perbandingan kelas)
- [ ] Export PDF: gunakan `@react-pdf/renderer` atau `pdfmake` (atau Puppeteer headless)
- [ ] Export Excel: gunakan `ExcelJS`
- [ ] `GET /api/v1/schools/:id/reports/class-monthly/export?format=pdf|xlsx`
- [ ] `GET /api/v1/schools/:id/reports/student/export?format=pdf|xlsx`
---
## Fase 10 — Web: Landing Page (`www.schoolmantic.com`)
**Target:** Website publik responsif dengan animasi, informasi produk, pricing, kontak.
**Estimasi:** 1 minggu
- [ ] Nuxt 4 project setup di `apps/landing`
- [ ] Tailwind CSS + animasi (motion/framer, atau Nuxt transitions)
- [ ] Komponen: Hero (tagline + CTA), Features, How It Works, Pricing (3 tier), Testimonial, FAQ, Footer
- [ ] Warna futuristik, card warna-warni, background terang
- [ ] Fully responsive (mobile-first)
- [ ] Kontak WhatsApp: 62811945222 (wa.me link)
- [ ] Alamat CV Polmantic Media Citra
- [ ] SEO: meta tag, Open Graph, sitemap.xml, robots.txt
- [ ] Deploy preview (Vercel / Netlify / server)
---
## Fase 11 — Web: Dashboard App (`app.schoolmantic.com`)
**Target:** Semua role bisa menggunakan dashboard web secara penuh.
**Estimasi:** 3–4 minggu
- [ ] Nuxt 4 project setup di `apps/web`, middleware auth + tenant
- [ ] Login page (email atau HP), tenant selector, first-login change-password
- [ ] **SaaS Owner:** daftar pelanggan, aktifkan/nonaktifkan, daftar pembayaran approve/reject, statistik global
- [ ] **Pelanggan:** tabel sekolah (jumlah pegawai, siswa, hadir hari ini), tambah sekolah, pilih paket, tambah school admin
- [ ] **School Admin:** CRUD pegawai, kelas, siswa (+ wali), mata pelajaran, jadwal, hari libur, override jadwal, input absensi semua kelas, kelola izin, template notifikasi, setting sekolah
- [ ] **Wali Kelas:** input absensi kelas miliknya, approve/reject izin siswa kelasnya
- [ ] **Pegawai biasa:** lihat jadwal mengajar, absensi diri sendiri
- [ ] **Wali Siswa:** rekap absensi anak (multi-sekolah), submit izin + upload dokumen
- [ ] **Siswa:** rekap absensi + izin diri sendiri (read-only)
- [ ] Laporan: rekap bulanan kelas, rekap siswa, grafik statistik, tombol export PDF/Excel
- [ ] Komponen grafik: `Chart.js` atau `ApexCharts`
- [ ] UU PDP: halaman "Pengaturan Privasi" → download data + hapus akun
---
## Fase 12 — Mobile: Flutter App
**Target:** Semua role bisa menggunakan app mobile, selfie absensi berjalan dengan GPS.
**Estimasi:** 3–4 minggu
- [ ] Flutter project setup di `apps/mobile`
- [ ] Login (email / HP) + tenant selector + first-login change-password
- [ ] HTTP client + JWT + refresh token interceptor
- [ ] Role-aware navigation (drawer / bottom nav berubah per role)
- [ ] **Pelanggan:** dashboard ringkasan sekolah
- [ ] **School Admin:** shortcut CRUD master data, input absensi, approve izin
- [ ] **Wali Kelas:** input absensi kelas, approve izin
- [ ] **Pegawai:** selfie absensi (kamera + GPS), lihat absensi diri
- `camera` package untuk selfie
- `geolocator` + `permission_handler` untuk GPS
- Upload selfie via presigned URL ke S3
- Validasi radius di server, tampil error jika di luar radius
- [ ] **Wali Siswa:** rekap absensi anak, submit izin + foto dokumen
- [ ] **Siswa:** rekap absensi diri
- [ ] Push notification: Firebase Messaging (`firebase_messaging`) + handler foreground/background
- [ ] Offline-mode: tidak ada — tampilkan pesan jika tidak ada koneksi
- [ ] Build APK (Android), submit ke Play Store
---
## Fase 13 — Security & Hardening
**Target:** Aplikasi aman sebelum go-live.
**Estimasi:** 3–5 hari
- [ ] OWASP review: SQL injection (Drizzle parameterized — sudah aman), XSS (Nuxt escape — review), CSRF
- [ ] Input validation: Zod schema di setiap endpoint API (request body + query params)
- [ ] Helmet middleware Hono (security headers)
- [ ] CORS: whitelist hanya `schoolmantic.com`, `app.schoolmantic.com`, localhost dev
- [ ] Rate limiting produksi (uprate: login, register, upload)
- [ ] S3 bucket: private, no public access, signed URL expire 15 menit
- [ ] Audit log: verifikasi semua aksi krusial tercatat (lihat §16 konsep)
- [ ] Pengujian tenant isolation: semua endpoint yang terekspos via browser dev tools
- [ ] Dependency audit: `bun audit` / `npm audit`
- [ ] Password policy: min 8 karakter (enforce di Zod)
- [ ] UU PDP endpoint: `GET /api/v1/me/export-data`, `DELETE /api/v1/me/account`
---
## Fase 14 — DevOps & Produksi
**Target:** Infrastruktur produksi stabil, backup otomatis, monitoring aktif.
**Estimasi:** 1 minggu
### Server & Deploy
- [ ] Pilih hosting: VPS (DigitalOcean / Vultr / AWS EC2) atau PaaS (Railway / Render)
- [ ] `Dockerfile` untuk API (Bun image)
- [ ] `docker-compose.prod.yml`: API + PostgreSQL + (opsional) MinIO
- [ ] CI/CD: GitHub Actions → test → build → deploy on push to `main`
- [ ] Health check endpoint: `GET /api/health`
- [ ] Graceful shutdown (handle SIGTERM di Hono server)
### Domain & SSL
- [ ] DNS: `www.schoolmantic.com` → landing server, `app.schoolmantic.com` → dashboard server / CDN, `api.schoolmantic.com` → API server
- [ ] SSL: Let's Encrypt via Caddy / nginx (auto-renew)
### Database Produksi
- [ ] PostgreSQL managed (Supabase / RDS) atau self-host dengan WAL backup
- [ ] Backup otomatis: pg_dump harian → upload ke S3, retensi 30 hari
- [ ] Connection pooling: PgBouncer (jika load tinggi)
- [ ] Set `default_transaction_isolation` yang sesuai
### Storage Produksi
- [ ] AWS S3 bucket dengan lifecycle policy (selfie expire 1 tahun)
- [ ] CDN (CloudFront / Cloudflare) untuk foto profil & dokumen
### Monitoring
- [ ] Error tracking: Sentry (API + Web + Flutter)
- [ ] Uptime monitoring: UptimeRobot / BetterUptime
- [ ] Log aggregation: Loki + Grafana atau Logtail
- [ ] Alert: server down, error rate spike, disk space
---
## Fase 15 — UAT & Go-Live
**Target:** Uji coba dengan 1–2 sekolah nyata, perbaikan, launch.
**Estimasi:** 2–3 minggu
- [ ] Onboarding sekolah beta (1–2 sekolah pilot)
- [ ] Panduan onboarding: PDF / video singkat cara setup sekolah
- [ ] Feedback loop: form feedback + WhatsApp support
- [ ] Bug fixing dari feedback beta
- [ ] Pembuatan akun produksi pertama (SaaS owner)
- [ ] Smoke test: login semua role, input absensi, terima notifikasi, export laporan
- [ ] **Go-Live** 🚀
---
## Ringkasan Timeline
| Fase | Deskripsi | Durasi | Status |
|---|---|---|---|
| 1 | Foundation + Schema + Seed | 3 hari | ✅ Selesai |
| 2 | API Auth + Tenant Guard | 1–1.5 minggu | ⬜ |
| 3 | API Master Data CRUD | 1.5–2 minggu | ⬜ |
| 4 | API Absensi | 2 minggu | ⬜ |
| 5 | API Perizinan | 3–4 hari | ⬜ |
| 6 | API Notifikasi | 3–4 hari | ⬜ |
| 7 | API Billing + Subscription | 3–4 hari | ⬜ |
| 8 | API SaaS Owner + Pelanggan | 2–3 hari | ⬜ |
| 9 | API Laporan + Export | 1 minggu | ⬜ |
| 10 | Web Landing Page | 1 minggu | ⬜ |
| 11 | Web Dashboard (semua role) | 3–4 minggu | ⬜ |
| 12 | Mobile Flutter | 3–4 minggu | ⬜ |
| 13 | Security & Hardening | 3–5 hari | ⬜ |
| 14 | DevOps & Infrastruktur Produksi | 1 minggu | ⬜ |
| 15 | UAT + Go-Live | 2–3 minggu | ⬜ |
| | **Total estimasi** | **~20 minggu** | |
---
> **Prioritas pengembangan yang disarankan:**
> Selesaikan Fase 2–9 (API lengkap) terlebih dahulu sebelum mulai Fase 10–12 (frontend/mobile).
> Dengan API yang lengkap, web dan mobile bisa dikembangkan paralel atau di-outsource.
Comments
Post a Comment