No description
  • TypeScript 50.8%
  • Go 36.4%
  • CSS 12%
  • JavaScript 0.4%
  • Makefile 0.2%
Find a file
cola d2e3f1a1b9
All checks were successful
check / check (push) Successful in 2m47s
docs: tell the run recipe about the settings encryption key
SETTINGS_ENCRYPTION_KEY has no development default, so the recipe as written
started a server that could not decrypt the SMTP password admins store on the
Pengaturan page. Both forms of the server now set it, with a note on why the
key must not change once secrets are on file.

Also points at .env.example and the README table as the list to check after a
pull or merge, since a new feature can add a required variable long before
this page catches up, and records that pkill on the server pattern also kills
the shell issuing it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 15:53:25 +07:00
.claude/skills/run-app docs: tell the run recipe about the settings encryption key 2026-09-17 15:53:25 +07:00
.forgejo/workflows feat(release): add guarded application versioning 2026-09-02 21:35:03 +07:00
cmd feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
docs feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
internal feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
migrations feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
scripts feat(release): add guarded application versioning 2026-09-02 21:35:03 +07:00
uploads Initial commit: SINAU LMS 2026-08-28 18:35:36 +07:00
web feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
.dockerignore feat: keep production state in ./data instead of named volumes 2026-09-02 13:18:55 +07:00
.env.example feat: let admins configure outgoing mail and require email verification at sign-up 2026-09-17 10:59:57 +07:00
.gitignore chore: keep the scraped BKN survey dump out of the repo 2026-09-17 15:53:25 +07:00
.golangci.yml feat: enforce the layering rules instead of describing them 2026-09-02 19:03:26 +07:00
AGENTS.md docs: correct what the README promises someone setting this up 2026-09-14 19:44:13 +07:00
CHANGELOG.md feat: let the public join a training with an access code instead of an account 2026-09-17 10:59:57 +07:00
docker-compose.prod.yml feat(release): add guarded application versioning 2026-09-02 21:35:03 +07:00
docker-compose.yml Initial commit: SINAU LMS 2026-08-28 18:35:36 +07:00
Dockerfile feat: sweep pictures no entry ever came to reference 2026-09-13 00:48:04 +07:00
flake.lock Initial commit: SINAU LMS 2026-08-28 18:35:36 +07:00
flake.nix Initial commit: SINAU LMS 2026-08-28 18:35:36 +07:00
go.mod feat: bring the certificate and questionnaire flow toward BKN parity 2026-09-11 01:15:05 +07:00
go.sum feat: bring the certificate and questionnaire flow toward BKN parity 2026-09-11 01:15:05 +07:00
Makefile feat(release): add guarded application versioning 2026-09-02 21:35:03 +07:00
README.md feat: let admins configure outgoing mail and require email verification at sign-up 2026-09-17 10:59:57 +07:00
VERSION feat(release): add guarded application versioning 2026-09-02 21:35:03 +07:00

Ruang Sinau

Sistem Informasi dan Pengembangan Kompetensi ASN untuk Belajar dan Berkarya

Ruang Sinau adalah Learning Management System untuk penyelenggaraan pelatihan ASN Pemerintah Daerah. Aplikasi menyatukan pengelolaan peserta, pelatihan, video, webinar, quiz, progres belajar, penilaian, dan sertifikat dalam satu platform berbasis role.

Tentang Ruang Sinau

Ruang Sinau menyediakan pengalaman yang berbeda untuk setiap pengguna:

  • Participant — ASN maupun peserta umum — mendaftar sendiri, lalu mendapatkan learning portal responsif untuk menemukan pelatihan, melanjutkan kelas, menonton video, mengerjakan quiz, mengikuti webinar, dan mengunduh sertifikat.
  • Instructor mendapatkan workspace untuk mengelola pelatihan yang ditugaskan, materi, webinar, dan enrollment.
  • Admin mendapatkan akses lintas resource untuk mengelola peserta, pelatihan, enrollment, sertifikat, dashboard, dan audit log.

Fitur

  • Pendaftaran mandiri peserta, dibedakan ASN (NIP wajib) atau umum; akun langsung aktif.
  • Aktivasi akun buatan admin melalui single-use activation link.
  • Login JWT, password bcrypt, RBAC, dan resource-level authorization.
  • Profil kepegawaian ASN dengan validasi NIP 18 digit; peserta umum cukup profil ringkas.
  • Lifecycle pelatihan draft → published → archived.
  • Enrollment dengan pemeriksaan kapasitas dan status machine terkontrol.
  • Video lokal atau YouTube, dengan waktu tonton diakumulasi di server (lompat ke depan dan idle tidak dihitung) dan completion threshold.
  • Bahan bacaan: PDF yang diunggah, atau artikel yang ditulis langsung di aplikasi.
  • Quiz pilihan ganda dan benar/salah, dalam dua peran. Quiz materi mengikuti sepotong materi dan cukup dikerjakan — ia tidak punya KKM. Post-test adalah penilaian pelatihan dan satu-satunya quiz yang harus lulus.
  • Quiz materi yang menyela videonya sendiri pada detik yang ditentukan, bukan hanya menunggu di akhir.
  • Auto-completion untuk pelatihan setelah seluruh video ditonton, seluruh bahan bacaan dibuka, seluruh quiz materi dikerjakan, dan post-test lulus.
  • Kurikulum berurutan: materi disusun dalam modul dan dikerjakan berurutan, dengan gerbang urutan divalidasi di server.
  • Sertifikat PDF bernomor unik untuk enrollment yang selesai.
  • Dua mode katalog: pelatihan (materi berurutan) atau webinar (sesi live), yang diselesaikan dengan mengisi kuesioner evaluasinya — itu satu-satunya syaratnya.
  • Webinar terintegrasi dengan jadwal, meeting link, dan status.
  • Q&A sesi webinar: peserta bertanya dan mendukung pertanyaan, penyelenggara menjawab.
  • Glosarium istilah: halaman publik AZ beserta dasar regulasi tiap istilah, dan pengelolaan draf/terbit oleh admin.
  • Profil instansi penyelenggara berikut logo, dengan halaman publiknya sendiri.
  • Dashboard per role dan audit log untuk aktivitas sensitif.
  • Antarmuka Ruang Sinau responsif dengan light/dark mode.

Teknologi

Bagian Teknologi
Backend Go, chi, pgx
Database PostgreSQL 16, Goose migrations
Authentication JWT, bcrypt
Frontend React 19, TypeScript, Vite
UI Shadcn/ui, Tailwind CSS 4, Lucide icons, Framer Motion
Server state TanStack Query
Client state Zustand
Development Nix flake, Docker Compose

Arsitektur

Repository menggunakan modular monolith. Setiap business domain memiliki model, repository, service, handler, dan test sendiri di bawah internal/<domain>.

cmd/
├── account/              # CLI untuk membuat akun admin/instructor
├── sweep/                # CLI penyapu gambar yatim di UPLOAD_DIR
└── server/               # HTTP application entry point

internal/
├── auth/                 # Login, activation, JWT, RBAC
├── participant/          # Profil dan lifecycle participant
├── training/             # Pelatihan dan status workflow
├── enrollment/           # Enrollment dan completion rules
├── quiz/                 # Soal, attempt, scoring, grading
├── certificate/          # Penerbitan sertifikat PDF
├── video/                # Storage dan progress video
├── document/             # Bahan bacaan — PDF unggahan atau artikel — dan progress baca
├── module/               # Kurikulum berurutan: modul, item, gerbang urutan
├── evaluation/           # Kuesioner yang menyelesaikan sebuah webinar
├── qna/                  # Tanya jawab seputar sesi webinar
├── webinar/              # Jadwal dan meeting webinar
├── glossary/             # Glosarium istilah beserta dasar regulasinya
├── organization/         # Instansi penyelenggara dan logonya
├── account/              # Manajemen akun staff (CLI + API)
├── audit/                # Audit trail
├── dashboard/            # Statistik per role
├── publiccertificate/    # Verifikasi sertifikat publik
├── publictraining/       # Prospektus pelatihan publik (tanpa login)
├── publicwebinar/        # Halaman webinar publik (tanpa login)
└── platform/             # Database, middleware, HTTP server

web/src/
├── app/                  # Router, provider, application shell
├── components/ui/        # Shadcn/ui primitives
├── features/             # UI, API, hook, dan type per domain
├── lib/                  # Helper teknis yang dipakai primitives
└── shared/               # API client dan komponen lintas feature

Keputusan arsitektur dijelaskan di docs/adr.

Menjalankan Lokal

1. Siapkan toolchain

Dengan Nix, satu perintah menyediakan semuanya:

nix develop path:.

Tanpa Nix, pasang sendiri toolchain berikut lewat package manager distro masing-masing. Versinya mengikuti pin yang sudah ada di repository, supaya hasil lokal sama dengan CI:

Tool Versi Pin
Go ≥ 1.23 go.mod
Node.js + npm 24 flake.nix, image CI
goose v3.24.1 Dockerfilego install github.com/pressly/goose/v3/cmd/goose@v3.24.1
golangci-lint v2.13.1 .forgejo/workflows/check.yml — hanya untuk make check
PostgreSQL 16 docker-compose.yml — lewat Docker atau dipasang langsung

Langkah-langkah selanjutnya sama untuk keduanya; bedanya hanya pengguna Nix menjalankannya dari dalam nix develop, yang lain dari shell biasa.

2. Siapkan konfigurasi dan PostgreSQL

cp .env.example .env

PostgreSQL bisa disiapkan lewat Docker atau langsung, dan DATABASE_URL bawaan di .env.example cocok untuk keduanya.

Dengan Docker:

docker compose up -d postgres

Tanpa Docker, jalankan satu instance yang datanya milik repository ini sendiri, sehingga tidak bentrok dengan PostgreSQL lain di mesin yang sama:

PGDATA="$HOME/.local/share/sinau/pgdata"

# sekali saja:
initdb -D "$PGDATA" -U lms -A trust -E UTF8

# setiap mulai kerja:
pg_ctl -D "$PGDATA" -l "$PGDATA/pg.log" \
  -o "-p 5432 -h 127.0.0.1 -k $PGDATA" start

# sekali saja, setelah instance-nya hidup:
createdb -h 127.0.0.1 -p 5432 -U lms lms

-A trust berarti tanpa password di lokal; DATABASE_URL yang menyertakan password lms tetap diterima. Menghentikannya: pg_ctl -D "$PGDATA" stop.

Setelah database siap, muat konfigurasi dan jalankan migrasi:

set -a
source .env
set +a
make migrate-up

Ganti JWT_SECRET dan seluruh credential contoh di .env sebelum digunakan di luar development lokal.

3. Buat akun staff pertama

Atur variabel berikut di .env:

ACCOUNT_EMAIL=admin@pemda.go.id
ACCOUNT_DISPLAY_NAME=Administrator SINAU
ACCOUNT_ROLE=admin
ACCOUNT_PASSWORD=replace-with-a-strong-password

Kemudian jalankan:

make create-account

ACCOUNT_ROLE menerima nilai admin atau instructor. Perintah ini hanya diperlukan untuk admin pertama pada database kosong — akun staff berikutnya dibuat admin melalui halaman Akun di aplikasi dan aktif lewat activation link. Participant mendaftar sendiri di halaman /signup; admin juga bisa mendaftarkan satu peserta dari halaman Peserta ketika pendaftarannya bersifat penugasan resmi (docs/account-management.md).

Untuk development lokal, akun admin yang biasa dipakai:

Email    : admin@example.go.id
Password : RahasiaAdmin123!

Akun ini hanya ada di database lokal masing-masing — buat dengan make create-account menggunakan nilai di atas. Jangan gunakan credential ini di luar development.

4. Jalankan backend

go run ./cmd/server

Backend tersedia di http://localhost:8080 dan health check di http://localhost:8080/health.

5. Jalankan frontend

Pada terminal lain (pengguna Nix: masuk nix develop path:. dulu):

cd web
npm install
npm run dev

Frontend tersedia di http://localhost:5173.

Konfigurasi

Variable Kegunaan
DATABASE_URL PostgreSQL connection string
JWT_SECRET Secret minimal 32 karakter untuk signing JWT
HTTP_ADDR Alamat backend, default :8080
WEB_ORIGIN Origin frontend untuk CORS
PUBLIC_BASE_URL Tujuan QR verifikasi pada sertifikat. Kosong berarti mengikuti WEB_ORIGIN
UPLOAD_DIR Direktori penyimpanan video dan sertifikat
WEB_DIST_DIR Direktori hasil build frontend. Kosong di development
ACTIVATION_BASE_URL URL halaman aktivasi frontend
SETTINGS_ENCRYPTION_KEY Passphrase minimal 32 karakter untuk mengenkripsi rahasia yang disimpan dari halaman Pengaturan (kata sandi SMTP)
ACCOUNT_* Input sementara untuk CLI pembuatan staff

Lihat .env.example untuk contoh lengkap.

Verifikasi

Jalankan dari shell yang berisi toolchain di atas:

make check

Perintah tersebut menjalankan:

  • pemeriksaan nama package terlarang (make check-layout)
  • pemeriksaan versi toolchain (make check-toolchain)
  • pemeriksaan konsistensi versi rilis (make check-version)
  • go vet ./...
  • golangci-lint run
  • go test ./...
  • ESLint
  • TypeScript typecheck
  • Vitest
  • Vite production build

Formatting dipisahkan dari verification karena mengubah source:

make fmt

Build untuk Deployment

make build

Menghasilkan dua artifact di satu direktori:

bin/
├── server      # binary Go, tanpa runtime dependency di host
└── dist/       # hasil vite build

Di server, arahkan WEB_DIST_DIR ke dist tersebut. Server API menyajikan frontend sekaligus, jadi tidak ada web server tambahan yang perlu dipasang — alasannya di ADR 010.

Deployment membutuhkan tiga hal: isi bin/, direktori migrations/ untuk goose, dan environment variable pada tabel di atas. UPLOAD_DIR harus persisten karena video dan sertifikat tersimpan di filesystem.

Perhatikan: bin/server dan bin/dist adalah artifact terpisah dan bisa tidak sinkron. Backend baru dengan frontend lama tetap berjalan tanpa keluhan, dan gejalanya menyerupai bug aplikasi. Salin bin/ sebagai satu kesatuan. bin/VERSION dan bin/COMMIT mencatat identitas paket tersebut; endpoint /health melaporkan nilai yang sama dari binary server.

Versioning dan Rilis

Backend, frontend, migrasi, dan paket deployment memakai satu Semantic Version dari file VERSION. Perubahan versi dilakukan ketika menyiapkan rilis dari master, bukan untuk setiap commit atau merge. Tag Git beranotasi v<version> menandai rilis resmi dan memicu workflow pembentukan artifact.

Prosedur pemilihan versi, release commit, validasi, tagging, dan publikasinya ada di docs/releasing.md.

Continuous Integration

make check dijalankan otomatis pada setiap push dan pull request melalui Forgejo Actions (.forgejo/workflows/check.yml). CI tidak memakai Nix flake dan menetapkan versi toolchain-nya sendiri — alasannya di ADR 009.

Dokumentasi

Status

Ruang Sinau saat ini merupakan MVP fungsional. Integrasi object storage, email delivery, dan SSO/LDAP disiapkan sebagai pengembangan berikutnya.