E-Pondok
ID EN
← Beranda
Referensi Developer

Referensi Developer E-Pondok

Sisi teknis E-Pondok — konsep, model data, pipeline kios, keamanan internal, arsitektur, dan HTTP API lengkap. Untuk setup produk langkah demi langkah, lihat Panduan Setup.

Pengenalan

E-Pondok adalah sistem kehadiran & relasi untuk pondok modern. Satu kios wajah di gerbang mencatat siapa yang datang dan pergi, buku tamu digital mengelola kunjungan, dan dashboard merangkai data itu jadi laporan serta peta relasi institusi yang hidup.

Dirancang untuk realitas pondok: bekerja di lokasi dengan jaringan tidak stabil (offline-first), tumbuh bersama banyak pondok (multi-tenancy), dan menjaga keamanan tanpa beban operasional yang berat.

Apa yang didapat

  • Kehadiran wajah tanpa sentuh dengan deteksi arah masuk/keluar otomatis.
  • Anti-spoofing — menolak foto, video, dan masker wajah palsu.
  • Buku tamu digital dengan kategori, tujuan, dan kontribusi kunjungan.
  • Manajemen relasi institusi: kontak, lembaga mitra, tag, dan tindak lanjut.
  • Dashboard ringkasan + analitik kehadiran.
  • Magic-link login tanpa password; setiap kios menandatangani permintaan.

Konsep inti

Pondok = tenan

Satu pondok adalah satu tenan (tenant) yang terisolasi. Setiap pondok mendapat subdomain sendiri — misal pondokabc.epondok.id — dan datanya tidak pernah bercampur dengan pondok lain meski berbagi satu basis data.

Tiga permukaan (surfaces)

  • Apex — domain induk epondok.id. Landing publik, pendaftaran, checkout, dan dokumentasi ini.
  • Platform — subdomain platform.epondok.id. Admin super: kelola akun, berlangganan, dan menyediakan pondok baru.
  • Tenant — subdomain *.epondok.id. Aplikasi admin per pondok (dashboard, kehadiran, pengunjung, relasi, perangkat).
Catatan dev

Di lokal, localhost dan *.workers.dev dianggap tenant. Tambahkan ?surface=platform pada URL untuk memaksa permukaan platform saat pengembangan.

Peran (roles)

Person di pondok mempunyai salah satu peran berikut:

santriPelajar/santri pondok
ustadzPengajar
staffStaf operasional
pengurusPengurus pondok

Peran admin di sisi aplikasi: admin (akses penuh termasuk Perangkat), pengurus, dan platform (super-admin di apex).

Kios

Kios adalah perangkat di gerbang — aplikasi desktop yang menjalankan pipeline wajah dan mencatat kehadiran/pengunjung. Setiap kios terdaftar dengan kunci publiknya sendiri dan menandatangani setiap permintaan.

Alur cepat

Dari nol hingga kehadiran otomatis dalam lima langkah.

Pindah ke Panduan Setup

Panduan produk lima langkah (daftar → langganan → buat pondok → pasang kios → daftar wajah → live), dengan pratinjau langsung tiap form, kini ada di Panduan Setup. Halaman ini menyimpan referensi teknis.

Dashboard

Halaman utama tenant. Ringkasan real-time dari seluruh modul. Sumber data: GET /api/dashboard.

Kartu ringkasan

  • Kehadiran — hadir hari ini, absen, terlambat, total populasi, tren harian.
  • Pengunjung — kunjungan hari ini, bulan ini, kunjungan dosen 3 tahun.
  • Relasi — baru, mitra aktif, potensial, strategis, jaringan alumni.
  • Follow-up — jumlah yang jatuh tempo.

Persons & enrollmen

Person = setiap individu di pondok (santri, ustadz, staff, pengurus). CRUD penuh lewat /api/persons.

Enrollmen wajah

Enrollmen menangkap wajah, mengubahnya menjadi embedding 512-dimensi, lalu menyimpannya di Vectorize. Saat enroll, opsi checkDuplicates mencegah wajah yang sama terdaftar dua kali, dan qualityScore mencatat kualitas tangkapan.

enroll flow
capture frame
→ anti-spoofing (MiniFASNet)   // tolak foto/video/masker
→ embedding 512-d (InsightFace)
→ POST /api/persons/:id/enrollments
      { embedding, deviceId, qualityScore, checkDuplicates: true }
  • POST /api/persons/:id/verify-face — mencocokkan embedding baru vs enrollmen person.
  • DELETE /api/persons/:id/enrollments/:eid — nonaktifkan enrollmen lama (bukan hapus permanen).
Build kios

Pipeline wajah asli butuh fitur cargo —features real-face. Tanpa fitur itu, kios memakai embedding mock di pengembangan.

Kehadiran

Inti produk. Kios menangkap wajah di gerbang → mencocokkan ke Vectorize → arah masuk/keluar dideteksi otomatis → event disimpan dengan skor kepercayaan (confidence) dan id perangkat (device_id).

Offline-first

Kios mencatat kehadiran meski jaringan putus, mengantrekannya secara lokal, lalu menyinkronkan otomatis saat online. Tidak ada absensi yang hilang karena gangguan jaringan.

Query

  • GET /api/attendance — daftar event (Paged), filter personId, role, from, to.
  • GET /api/attendance/presence — siapa yang sedang di dalam.
  • GET /api/attendance/analytics — daily entries/exits, top late, most punctual, filter window & role.

Pengunjung

Buku tamu digital. Setiap kunjungan dapat kategori, tujuan, check-in/out, dan nomor pengunjung (visitor_no).

Kategori

parent_guardianlecturerteachergovernment_officialcommunity_leaderalumnivendorgeneralother

Kontribusi kunjungan

Tiap kunjungan dapat mencatat kontribusi untuk pelaporan: workshop, guest_lecture, training, mentoring, community_service, research_collaboration, recruitment_opportunity, other — dengan topik, audiens, peserta, dan hasil.

Relasi institusi

Peta jejaring pondok agar tetap hidup dan terlacak.

Kontak

RelationshipContact menyimpan nama, lembaga, jabatan, keahlian, status (new / active / potential / alumni / strategic), dan catatan.

Tag kolaborasi

CollaborationTag (slug + label) bebas dilampir/lepas pada kontak untuk mengelompokkan mitra — mis. pengajar-tamu, beasiswa.

Follow-up

Tindak lanjut terjadwal: contact_id, due_date, assigned_to, status (open / in_progress / completed / cancelled). Filter overdue menyoroti yang sudah lewat jatuh tempo.

Perangkat

Halaman Perangkat (admin saja) mengelola kios. Setiap kios terdaftar dengan device_uid unik global, kunci publik Ed25519, dan opsional bound_network.

  • POST /api/devices/register — daftarkan kios baru.
  • POST /api/devices/:id/revoke — cabut akses (kios tidak bisa sync lagi).
  • POST /api/devices/:id/activate — aktifkan ulang.
  • last_seen_at melacak sinkronisasi terakhir.
device_uid global unik

device_uid unik lintas seluruh pondok (bukan per-pondok). Jangan gunakan UID yang sama untuk dua kios.

Kios desktop

Aplikasi desktop (Tauri) yang dipasang di perangkat gerbang. Menjalankan seluruh pipeline wajah secara lokal: tangkap frame → anti-spoofing → embedding → cocokkan → kirim event ke backend.

  • UI layar-penuh untuk check-in cepat di gerbang.
  • Daftar person & perangkat dimuat dari backend dengan token kios.
  • Umpan balik visual (flash) & suara (TTS) saat wajah dikenali.
  • Build aarch64 untuk Android layaknya (eksperimental).

Offline-first & sinkronisasi

Karena koneksi di pondok sering tidak stabil, kios tidak bergantung pada internet untuk mencatat. Antrian event lokal disinkronkan lewat rute device-authed (sync) saat koneksi pulih. Backend menerima idempotently — tidak ada ganda saat retry.

sync sequence
1. event dicatat lokal (kios offline)
2. masuk ke antrian sinkron
3. saat online → POST ke rute sync (ditandatangani Ed25519)
4. backend verifikasi tanda tangan + dedup
5. dashboard langsung memperbarui

Anti-spoofing wajah

Sebelum embedding dibuat, frame diperiksa oleh MiniFASNet untuk membedakan wajah asli dari foto, video, atau masker. Hanya wajah asli (class index 1) yang diproses lebih lanjut.

Preprocessing

Model anti-spoofing butuh input BGR mentah pada rentang [0, 255] — bukan tensor ternormalisasi. Pipeline kios menyiapkan frame sesuai itu.

Pembaruan otomatis

Kios memeriksa /kiosk/update.json untuk versi baru. Rilis disimpan di bucket R2 epondok-kiosk-releases dan dicatat di tabel kiosk_release. Updater bawaan Tauri mengunduh & memasang pembaruan, ditandatangani dengan kunci Tauri. Akun kios dipasangkan dengan pin b7e6.

Admin platform

Permukaan platform (platform.epondok.id) adalah ruang super-admin: menyediakan pondok baru, mengelola langganan, dan mengubah status pondok (active / suspended). Token platform terpisah dari token tenant — keduanya origin berbeda.

Multi-pondok

Satu sistem, banyak pondok. Setiap pondok mendapat subdomain & data terisolasi. Secara teknis: kolom pondok_id pada semua tabel tenan, resolver subdomain→pondok, dan JWT membawa pondokId sehingga setiap query terbatas pada pondok pemilik token.

Urutan deploy

Saat menambah tabel tenan baru, pondok_id + foreign key harus ikut sejak awal. Constraint global & FK di D1 tidak bisa diubah secara arbitrer pasca-fakta.

Harga & kursi

Tagihan berbasis kursi (seats) via Polar. Pembayaran bulanan, minimal 10 kursi.

Rentang kursiPer kursi / bln
10–29$0.90
30–59$0.50
60–99$0.42
100$0.50
101+$0.30
Webhook

Webhook Polar memakai spesifikasi Standard Webhooks (Svix) — tiga header + base64 signature, bukan polar-*. cancel = masa tenggat, revoke = segera. POLAR_WEBHOOK_SECRET wajib di produksi.

Penandatanganan perangkat

Setiap kios memegang kunci privat Ed25519 dan mengirim kunci publiknya saat registrasi. Setiap permintaan sync/kehadiran ditandatangani; middleware deviceAuth memverifikasi tanda tangan sebelum memproses. Kios yang dicabut (revoked) ditolak mentah.

Isolasi tenan

Isolasi pondok dijaga berlapis: subdomain → pondok (resolver), pondok_id pada tiap baris, dan pondokId di JWT. Tidak ada titik akhir tenant yang bisa membaca data pondok lain. Semua lalu lintas terenkripsi saat transit (TLS).

Arsitektur

  • Cloudflare Workers — edge API, serverless, global.
  • D1 — basis data SQLite, multi-tenant via pondok_id.
  • Vectorize — indeks embedding wajah 512-d untuk pencocokan cepat.
  • Polar — langganan & checkout; Standard Webhooks untuk status.
  • R2 — rilis kios (epondok-kiosk-releases).
Riwayat

Backend pernah berjalan di Bun + Postgres + pgvector, lalu dimigrasikan ke Workers + D1 + Vectorize. Jejak lama mungkin terlihat di komentar atau skema — yang berjalan sekarang adalah versi Cloudflare.

Routing

host mapping
epondok.id            → apex     (landing, /docs)
platform.epondok.id   → platform (super-admin: provisioning, billing)
*.epondok.id          → tenant   (aplikasi admin per pondok)
localhost / *.workers.dev → tenant (dev)

Model data

Entitas inti dan field kuncinya:

EntitasField penting
Personid, full_name, role, phone, active
EnrollmentRowperson_id, device_id, quality_score, active
AttendanceEventperson_id, ts, event_type(entry/exit), confidence, device_id
Visitorvisitor_no, name, category, purpose, arrival_ts, departure_ts
VisitContributiontype, topic, audience, participants, outcomes
RelationshipContactname, institution, status, tags
CollaborationTagslug, label
FollowUpcontact_id, due_date, assigned_to, status
Devicedevice_uid, public_key, status, bound_network, last_seen_at
Pondokid, slug, name, status

Semua entitas tenan juga membawa pondok_id untuk isolasi.

Referensi API

API JSON di balik aplikasi. Semua rute daftar mengembalikan amplop terpaginasi:

Paged<T>
{
"items":  T[],
"total":  number,
"limit":  number,
"offset": number
}

Contoh request dengan token:

curl
curl -H "Authorization: Bearer [REDACTED:Authorization header] header] \
"https://pondokabc.epondok.id/api/attendance?from=2026-01-01&limit=50"

Rute tenant

Autentikasi

POST/api/auth/loginPhone + password → { token, user }
POST/api/auth/magic/requestSend a magic-link to email
POST/api/auth/magic/verifyExchange magic-link token → { token, user }
GET/api/auth/meCurrent admin session

Dashboard

GET/api/dashboardAttendance, visitor, relation, follow-up summary

Pondok (publik)

GET/api/pondoksPondok list for the landing directory

Persons

GET/api/personsList (Paged<Person>) — role, active, q
GET/api/persons/:idPerson detail
POST/api/personsCreate person (full_name, role, phone)
PATCH/api/persons/:idUpdate
DELETE/api/persons/:idDelete (soft delete)

Enrollmen wajah

GET/api/persons/:id/enrollmentsPerson's enrollment history
POST/api/persons/:id/enrollmentsEnroll embedding (+ deviceId, qualityScore, checkDuplicates)
DELETE/api/persons/:id/enrollments/:eidDeactivate enrollment
POST/api/persons/:id/verify-faceMatch embedding vs person's enrollments

Kehadiran

GET/api/attendanceEvent list (Paged) — personId, role, from, to
GET/api/attendance/presenceWho is currently inside
GET/api/attendance/analyticsWindow analytics — daily, top late, most punctual

Pengunjung

GET/api/visitorsList (Paged) — category, from, to, open, q
GET/api/visitors/:idVisit detail
POST/api/visitorsCheck-in (name, phone, category, purpose, …)
POST/api/visitors/:id/checkoutCheck-out
GET/api/visitors/:id/contributionsVisit contributions
POST/api/visitors/:id/contributionsRecord contribution (type, topic)

Relasi

GET/api/contactsContact list (Paged) — q, status, institution, tag
GET/api/contacts/:idContact detail
POST/api/contactsCreate contact (name, phone)
PATCH/api/contacts/:idUpdate
POST/api/contacts/:id/tagsAttach tag (slug)
DELETE/api/contacts/:id/tags/:slugDetach tag
GET/api/contacts/:id/follow-upsContact follow-ups

Follow-up

GET/api/follow-upsList (Paged) — status, overdue
POST/api/follow-upsCreate (contact_id, due_date, assigned_to)
PATCH/api/follow-ups/:idUpdate status / due date

Tag

GET/api/tagsList collaboration tags
POST/api/tagsCreate tag (slug, label)

Perangkat

GET/api/devicesList (Paged) — q, status (admin)
POST/api/devices/registerRegister kiosk (device_uid, public_key, bound_network)
POST/api/devices/:id/revokeRevoke access
POST/api/devices/:id/activateReactivate

Rute platform (apex)

Platform (apex)

Hanya admin platform. Token terpisah dari tenant — apex & subdomain adalah origin berbeda.
POST/api/platform/registerRegister platform account (name, email, password)
POST/api/platform/loginPlatform login
POST/api/platform/magic/requestPlatform magic-link
POST/api/platform/magic/verifyVerify platform magic-link
GET/api/platform/meCurrent platform session
GET/api/platform/slug/checkCheck pondok slug availability
POST/api/platform/checkoutCreate Polar checkout session (seats)
GET/api/platform/pondokList pondok owned by the account
POST/api/platform/pondokCreate a new pondok (slug, name)
PATCH/api/platform/pondok/:idUpdate pondok name / status
Rute device-authed

Rute kiosk & sync dipakai kios dan dilindungi tanda tangan Ed25519, bukan token admin. Tidak didokumentasikan untuk pemakaian langsung.