Skip to content

001 Mvp

XPrivate Education — Iter 1 (Admin-MVP) Scope

Section titled “XPrivate Education — Iter 1 (Admin-MVP) Scope”

Doc: plans/scope/001-mvp.md Status: Draft 1 (pending user review & approval) Date drafted: 2026-05-25 Iter target: Admin-MVP (pure backoffice). Customer-facing self-service = iter 2+. Timeline: Scope-first, ship-when-ready (no hard deadline locked).


  • [F] = friend’s design plan (extra/admin-mvp-1-design-plan.md)
  • [FC] = friend’s cancellation policy decision (extra/2026-05-25-xprivate-tutor-cancel-policy-v1.md)
  • [Q&A] = decision dari Q&A klarifikasi reconciliation
  • [U] = explicit user constraint (overrides default)
  • [Δ] = override of friend’s doc default

XPrivate Education adalah platform les privat (privattuition) Indonesia — offline + online. Remake dari versi awal (bisnis pattern lama tidak match ekspektasi). Future expansion: bank soal. [Q&A]

Pillar utama = trust via audit kuat & dispute resolution discipline. Sistem harus mampu telusur balik tiap perubahan state penting (sesi lifecycle, billing, payment, dispute, master data) untuk dispute resolution kuat. [Q&A]

Admin-MVP ONLY (pure backoffice). Customer-facing self-service (siswa/tutor signup, payment gateway, auto-notif, Zoom integration, mobile push, dispute UI) = iter 2+. [F+Q&A]

Scope-first, ship-when-ready. Tidak ada hard ship 2026-06-30 — kualitas scope > kalendar. [Q&A overrides F default deadline]


1. Domain Glossary (LOCKED — gunakan term ini exact di code + UI)

Section titled “1. Domain Glossary (LOCKED — gunakan term ini exact di code + UI)”
TermMeaningSource
SesiUnit pengajaran (1 lesson, default 90 menit, default 1:1)F
SiswaMurid (term formal)F
TutorGuru (term formal)F
TingkatTingkat pendidikan siswa (SD 1-6, SMP 7-9, SMA 10-12, Mahasiswa, Umum, Profesional) — CRUD-able stable rowsF
SegmentasiTier layanan (REGULER, REGULER_PLUS, INTERNASIONAL)F
KategoriGrouping subject (REGULER_KELAS, PROGRAM_KHUSUS, SERTIFIKASI, BAHASA_ASING, MUSIK, KOMPUTER) — bukan axis pricingF
SubjectMata pelajaran konkret (e.g., “Bahasa Mandarin”, “Piano”, “CPNS”)F
SubjectLevelOptional child per Subject (e.g., HSK 1-6 under Mandarin, Grade 1-8 under Piano)F
GolonganTier tutor (GOL_1, GOL_2, GOL_3, GOL_4, NON_GOLONGAN; 1 tertinggi) — dimensi tambahan di TUTOR pricing matrixF
Tahun AjaranSiklus Jul-Jun (e.g., 2026/2027 = Jul 2026 – Jun 2027). Pricing matrix versioned per tahun ajaran.F
TagihanStudent-side invoice per bulan (postpaid)F
HonorariumTutor-side payout per bulan (internal — siswa NEVER sees)F
SlotAvailable time window dari tutorF
mode_surchargePer-sesi optional surcharge field (escape hatch online vs offline pricing)Δ+U
SLAService Level Agreement — komitmen waktu tanggap operasional. “SLA flag” = badge warn bila item lewat threshold tanggap (mis. REQUESTED >24h tanpa approve/reject admin = SLA breach, di-flag di approval queue)Term

2. Auth & Identity (CRITICAL — future-facing design) [U]

Section titled “2. Auth & Identity (CRITICAL — future-facing design) [U]”

Auth flow harus didesain future-facing dari iter 1. Auth = paling nightmare untuk diubah belakangan. Schema harus support multi-identity / multi-IdP / custom RBAC / 2FA-ready / login audit-ready dari awal — meskipun iter 1 cuma admin yang aktif login.

  • Admin login via Google OAuth + Google Workspace domain restrict (@xprivate.education only) [F]
  • Forgot password (email reset token, 1h expire, single-use) — backup path bila OAuth issue [F]
  • Session management (timeout + remember-me) [F]
  • Custom flexible RBAC dengan permission matrix runtime-editable [Δ overrides F’s 3-role minimal]
  • Admin onboarding checklist: enforce Google account 2FA on (policy + training) [F]

Iter 1 DB-READY (schema present, future-facing untuk iter 2+)

Section titled “Iter 1 DB-READY (schema present, future-facing untuk iter 2+)”
  • UserType enum: ADMIN (active iter 1) · TUTOR · SISWA · PARENT (DB-ready iter 2+)
  • IdentityProvider entity:
    • Iter 1 active: Google OAuth (domain-restricted)
    • DB-ready: email+password, social login (Google personal, Facebook, Apple)
  • UserIdentity link table (User ↔ Identity many-to-many; user bisa link multiple identity)
  • Role, Permission, RolePermission, UserRole (custom RBAC active iter 1)
  • Session entity (active iter 1)
  • TwoFactorMethod entity (DB-ready; iter 1 rely on Google account 2FA)
  • PasswordReset, EmailVerification (DB-ready iter 2+)
  • LoginAuditEvent (DB-ready iter 2+; iter 1 mitigate via Cloudflare rate-limit per F non-goal)
  • AccountState machine: PENDING_INTERVIEW → APPROVED → ACTIVE → SUSPENDED → ARCHIVED (DB-ready untuk self-register flow iter 2+)

Iter 1 Auth Implication: Tutor & Siswa Actions

Section titled “Iter 1 Auth Implication: Tutor & Siswa Actions”
  • Iter 1: tutor mark Start / attendance / materi / foto report = admin proxy entry (admin enters via UI on tutor’s behalf). Audit captures admin sebagai actor + tutor + sesi sebagai subject. UI bisa di-label “Tutor mark X” untuk clarity, tapi diakses hanya admin.
  • Iter 2+: tutor portal login (basic email/pwd atau magic link) → tutor mark sendiri. Audit capture identitas tutor langsung.
  • Trade-off: iter 1 audit slightly weaker (admin proxy abstraction), accepted untuk fokus admin-MVP. Schema sudah ready bila tutor login di-aktifkan.

Outcome: operator login secure + manage admin user roster + assign role/privilege.

  • Operator login (Google OAuth — primary, domain restrict @xprivate.education)
  • Forgot password (email reset token, 1h expire, single-use)
  • Session timeout + remember-me
  • Admin CRUD admin users (create, edit, deactivate)
  • Admin assign role (custom RBAC dari iter 1 [Δ])
  • Admin assign granular privilege per role
  • Operator profile view (own info, role, last login)
  • Manual trigger welcome email (link ke A2)
  • Admin onboarding checklist: enforce Google account 2FA (policy + training)
  • OAuth flow restrict non-@xprivate.education domain → reject with clear error
  • Forgot password token single-use + 1h expiry validated
  • CRUD operations audit-logged (link A1)

Outcome: operator manage master data tanpa breaking in-flight bookings (snapshot-based pricing).

Tutor CRUD:

  • Nama, Golongan, kontak, alamat KYC, lat/long, bio, foto
  • Foto KTP wajib (upload R2) [Δ]
  • Kontrak PDF upload + signed flag
  • Subject list (subjects yang tutor bisa ajar)
  • Slot mgmt (weekly availability window)

Siswa + Parent fields CRUD:

  • Nama, Tingkat, Segmentasi
  • Parent fields (name, phone, relation)
  • Alamat KYC, lat/long, foto
  • Foto KTP / akta wajib (upload R2) [Δ]
  • Preferred tutor (TeacherMatch hint untuk admin)

4.2 Catalog Dimensions (CRUD-able, runtime-edit, admin-managed)

Section titled “4.2 Catalog Dimensions (CRUD-able, runtime-edit, admin-managed)”
  • Subject + SubjectLevel — parent+child schema, has_levels flag (auto-show/hide level picker)
  • Tingkat — stable individual rows (SD 1-6, SMP 7-9, SMA 10-12, Mahasiswa, Umum, Profesional)
  • Segmentasi — operator-managed (REGULER, REGULER_PLUS, INTERNASIONAL initial)
  • Kategori — operator-managed (REGULER_KELAS, PROGRAM_KHUSUS, SERTIFIKASI, BAHASA_ASING, MUSIK, KOMPUTER initial)
  • Golongan — operator-managed (GOL_1..4 + NON_GOLONGAN initial)

4.3 5D Pricing Matrix (versioned per Tahun Ajaran) [F+Δ]

Section titled “4.3 5D Pricing Matrix (versioned per Tahun Ajaran) [F+Δ]”

STUDENT matrix:

  • Subject × SubjectLevel? × Tingkat × Segmentasi → amount/sesi (Tagihan amount)

TUTOR matrix:

  • Subject × SubjectLevel? × Tingkat × Segmentasi × Golongan → amount/sesi (Honorarium amount)

Properties:

  • Versioned per Tahun Ajaran (effective_from, effective_until)
  • Snapshot at sesi APPROVED (sesi capture pricingMatrixIdStudent, pricingMatrixIdTutor, amountStudent, amountTutor)
  • Sparse allowed (admin can leave combos empty)
  • Mid-flight override OK (admin can edit current matrix without rolling year)
  • mode_surcharge per-sesi optional field — escape hatch bila online ≠ offline pricing perlu beda [U]
  • duration_minutes per-sesi (default 90 from app config); price tetap (asumsi flat-per-sesi industri norm; bila perlu pro-rate, di-handle per-sesi adjustment)

UX Affordances (per F’s pricing matrix RAT):

  • Atomic “Clone Tahun Ajaran” — one click: effective_until on old rows + insert bumped new rows
  • Hierarchical drill-down: Subject → Level → matrix per audience (NOT flat 6-column entry)
  • has_levels auto-show/hide level picker
  • CSV import + bulk-edit
  • Per-row validation feedback
  • Coverage gap detector: warn “X% combos populated for Subject Y”

4.4 Cancellation Policy Editor (configurable bracket) [FC]

Section titled “4.4 Cancellation Policy Editor (configurable bracket) [FC]”

cancellation_policy_config + cancellation_bracket (per F’s schema):

  • Editable: threshold_hours, charge_pct_siswa, honor_pct_tutor, substitution_denda_pct, base_penalty_enabled, strike_added
  • Versioned effective_from, effective_until
  • Snapshot at APPROVED (cancellation_policy_config_id locked per sesi, immune from later config change)

4.5 App Config (runtime, audit-tracked) [F]

Section titled “4.5 App Config (runtime, audit-tracked) [F]”
  • transport_bracket (default <20km=Rp10.000, >20km=Rp12.000)
  • session_default_duration_minutes (90)
  • tutor_cancel.self_sub_window_hours (4)
  • tutor_cancel.no_penalty_threshold_hours (4)
  • siswa_cancel.no_penalty_threshold_hours (4)
  • strike_decay_days (90)
  • strike_threshold_terminate (3)
  • force_majeure.approval_levels (2)
  • force_majeure.appeal_window_days (14)
  • Pricing audit log (every matrix change: who, when, from-to, reason)
  • Bulk operations: copy row / copy column / %-bump
  • Soft-delete + cascade rules (Subject/Tingkat delete = status ARCHIVED, FK preserved)
  • Data validation (phone +62/0xxx, email, lat/long sanity, required field enforcement)
  • Duplicate detection (siswa/tutor by phone/email match → soft-warn at create)
  • Pricing matrix sanity check (negative prevent; >10x average flag warning)

Outcome: operator create + manage sesi dengan state machine tegas + audit-trailed.

REQUESTED → APPROVED → IN_PROGRESS → COMPLETED
↓ ↓
REJECTED CANCELLED (terminal)
↓ optional
RESCHEDULED → REQUESTED (new linked sesi)

Sub-states: NO_SHOW_STUDENT, NO_SHOW_TUTOR (COMPLETED variant w/ billing rules).

StateMeaningTrigger by
REQUESTEDSesi diminta, nunggu admin approveAuto on create
APPROVEDAdmin approve, slot di-lockAdmin only
REJECTEDAdmin tolak (terminal)Admin only
IN_PROGRESSSesi mulaiAdmin proxy iter 1 (Tutor login iter 2+)
COMPLETEDSesi selesai + materi confirmed2-step: tutor confirm (admin proxy iter 1) + admin validate
CANCELLEDDibatalin post-APPROVED, w/ punishmentSiswa/tutor/admin (admin proxy iter 1)
RESCHEDULEDOld sesi closed, new linked sesi createdSiswa/tutor/admin (admin proxy iter 1)
  • Operator create sesi (admin direct, 1:1 mode for iter 1)
  • Operator approve/reject sesi (single or bulk w/ state validation)
  • Operator edit sesi before APPROVED (date/time/tutor/lokasi)
  • Sesi reschedule workflow: RESCHEDULED state, new linked sesi REQUESTED, slot release+lock, reason + initiator, notify tutor + siswa (manual WhatsApp iter 1)
  • Sesi materi log (admin proxy iter 1): topik utama, sub-topik, halaman buku, PR/tugas, target sesi berikutnya, foto report (R2)
  • Calendar view: siswa weekly/monthly + tutor weekly/monthly + global ops; drag-friendly reschedule
  • Sesi conflict detection: validate at approve; DB unique constraint (tutor_id, date, start_time) (= anomaly minimal iter 1)
  • No-show handling:
    • NO_SHOW_STUDENT → siswa kena charge full
    • NO_SHOW_TUTOR → escalate ke cancellation flow
  • Bulk reschedule: operator pick tutor + date range + new tutor/slot → bulk reassign
  • Operator cancel sesi (terminal + reason + denda calc per config bracket)
  • Operator reschedule sesi
  • TimeSlot DB uniqueness constraint
  • Tutor mark sesi attendance + materi + foto report (R2 storage) — admin proxy iter 1
  • Admin validate completion (2-step COMPLETED gate)
  • Approval queue UI + SLA flag (warn REQUESTED >24h) — = anomaly minimal iter 1
  • Cancellation calc engine — auto-calc per config bracket; operator override w/ alasan + audit
  • Force Majeure workflow — L1 operator review + L2 banding 14d window
  • Substitute matching UI (admin-side): list tutors sort by distance, no service radius iter 1, manual dispatch via WhatsApp
  • Cancellation policy snapshot at APPROVEDconfig_id locked, immune from later config change
  • sesi_mode: ONLINE / OFFLINE_RUMAH_SISWA / OFFLINE_CUSTOM
  • duration_minutes (default 90 from app config)
  • sesi_lat, sesi_long (admin entry iter 1)
  • mode_surcharge (optional, escape hatch [U])

5.4 Anomaly Detection (iter 1 minimal + DB-ready iter 2)

Section titled “5.4 Anomaly Detection (iter 1 minimal + DB-ready iter 2)”

Iter 1 ACTIVE:

  • SLA flag (warn REQUESTED >24h tanpa action di approval queue)
  • DB unique constraint (tutor_id, date, start_time) — prevent double-book at insert

DB-READY iter 2 (schema present, engine deferred):

  • anomaly_flag (boolean), anomaly_type enum (TIMING_OUTLIER / DURATION_OUTLIER / NO_SHOW_IMPLICIT / CONCURRENCY / PATTERN_ABUSE), anomaly_resolved_at, anomaly_resolved_by
  • Engine yang scan & flag = iter 2

Outcome: operator + tutor + siswa view appropriate report dengan privacy boundary.

Note: iter 1, “tutor view” + “siswa view” = admin proxy (admin pull report on tutor’s/siswa’s behalf untuk WhatsApp delivery). Self-service portal iter 2+.

6.1 Three Report Families (with privacy guard)

Section titled “6.1 Three Report Families (with privacy guard)”
  1. Student progress (siswa + admin) — sessions/bulan, materi belajar, kehadiran, foto report tutor
  2. Tagihan siswa (siswa + admin) — invoice bulanan, items per sesi, total tagih, status PAID/UNPAID, upload bukti bayar
  3. Honorarium tutor (tutor + admin ONLY — siswa NEVER sees) — itemized per sesi, total bayar, status, bukti transfer
  • Generate monthly student progress per siswa
  • Generate monthly Tagihan per siswa (snapshot-based)
  • Generate monthly Honorarium per tutor (Golongan-based, snapshot)
  • Export Excel per report
  • Operator mark Settlement.PAID bulk
  • Operator mark SettlementTeacher.PAID bulk
  • Outstanding receivables aging: buckets 0-30 / 31-60 / 61-90 / 90+ days, per-siswa drilldown
  • Manual adjust per settlement (nominal + alasan + audit)
  • Privacy guard: siswa-facing endpoint scoped to caller.siswaId, tutor scoped to caller.tutorId, admin sees all (iter 1: admin proxy semua)
  • Audit-trail mark-paid actions
  • Reconciliation export template (Excel finance-familiar format)
  • Sesi materi visibility admin dashboard: materi per siswa (timeline), search/filter, export Excel monthly summary
  • Manual reminder broadcast trigger: operator nudge late-payment siswa OR low-completion tutor via WhatsApp template

Outcome: every operator action di critical touch-points + master-data-edit + cancel + FM logged + queryable.

  • Audit middleware logs: actor, action, entity_type, entity_id, before_state, after_state, timestamp, ip
  • Coverage:
    • Schedule actions (create/approve/reject/cancel/finalize/reschedule)
    • Settlement actions (mark-paid bulk/single, adjust)
    • Master-data changes (pricing matrix edit, config change, Tingkat add/edit, Subject add/edit, Cancellation Policy edit)
    • FM workflow events (claim, approve, reject, banding submit, banding result)
    • Auth events (admin user CRUD, role/privilege assign — iter 1; login events DB-ready iter 2)
  • Minimal viewing UI: list view by date range + actor filter
  • Audit immutable — DB constraint: INSERT-only, no UPDATE, no DELETE
  • Audit retention 7 years — storage planning + archive policy doc
  • Basic search by entity_id (untuk dispute case pull tutor X / siswa Y history)

8. A2 — Notification Trigger (narrowed iter 1) [F]

Section titled “8. A2 — Notification Trigger (narrowed iter 1) [F]”

Outcome iter 1: operator manually trigger welcome email saat create admin user / tutor / siswa.

  • “Send welcome email” checkbox di M1 admin user create form
  • Same di M2 tutor create form, siswa create form
  • Wiring ke MailTemplate infra (template welcome baru)
  • Send log entry (who sent, to, template, timestamp)
  • NotificationTemplate, NotificationLog, NotificationPreference
  • Channel abstraction (Email / WhatsApp / PWA Push / SMS)
  • Auto-trigger event hooks (invoice generated, payment confirmed/failed, dispute updated, session reminder H-1, anomaly resolved)
  • User notification preference (per channel, per event)

Outcome: HR team manage strike escalation + tutor suspension + termination flow.

  • Strike count visible per tutor (active dalam 90d window)
  • Strike detail audit (when, why, by whom, alasan)
  • Manual escalation UI (HR/admin decide suspend / final-warning / terminate)
  • Suspend tutor temporarily (block from booking, with reason + duration, audit)
  • Terminate tutor kerjasama (final + audit)
  • Termination checklist (final settlement payout + document return + access revoke + archive flag)
  • Tutor archive (preserved data + read-only access via tutor.status=ARCHIVED)
  • Tutor reactivation flow (suspended → active back, senior approval + audit)
  • Final settlement auto-trigger at termination — auto-trigger settlement payout calc untuk remaining unpaid sesi (legal obligation)
  • Access revoke immediate — terminate = revoke OAuth tokens + login disabled at same transaction
  • Pending FM claim blocker — block termination if FM claim status PENDING_L1 or PENDING_L2

Outcome: finance team handle refund + credit note + monthly period close + outstanding aging.

  • Operator initiate refund (sesi cancelled post-bill, dispute, special case)
  • Credit note generation (reduce siswa bill + audit + reason mandatory)
  • Refund disbursement tracking (off-system, status notes)
  • Settlement reversal (mark UNPAID → reversed, audit)
  • Monthly close checklist UI (step-through: bills generated, payments reconciled, honor batch ready, FM cases reviewed, adjustments processed)
  • Period lock flag (after close: no new bookings backdated, no late-mark-paid retroactive)
  • Period close blocker: if any sesi IN_PROGRESS at close time → block close until finalized
  • Lock audit (who closed, when)
  • Re-open option (senior admin approval + audit)
  • Reuse M4 outstanding aging dashboard
  • Bad debt write-off flow (senior approval + audit + tax compliance flag)
  • Reconciliation export template (Excel finance-familiar w/ adjustments column)
  • Adjustment audit trail visible
  • pph_withheld_amount field per honor batch (operator manual input)
  • Captured untuk reporting; detailed tax engine defer iter 2
  • Honor payment slip — tutor receive slip w/ breakdown (base + transport + extra-time + adjustments + PPh)
  • Export PDF per tutor per month
  • Daily backup procedure (RTO/RPO target = partner authority Step 2)
  • Restore drill cadence (partner define)
  • Backup retention policy (partner define per legal req 7y for audit)

11. Cancellation Policy — Locked Decisions [FC]

Section titled “11. Cancellation Policy — Locked Decisions [FC]”
TUTOR cancel ≤ 4 jam sebelum sesi
├─ Option α: Tutor cari pengganti SENDIRI dari komunitas xprivate
│ ├─ SUCCESS → Sesi jadi dengan pengganti
│ │ ✓ Tutor original: NO penalty, NO strike, NO warning (CLEAN)
│ │ ✓ Pengganti: full Honorarium (siapa ngajar dia dibayar)
│ │ ✓ Siswa: bayar normal
│ │
│ └─ FAILURE → fall ke Option β
└─ Option β: Escalate ke XPrivate (transfer liability)
├─ XPrivate dispatch pengganti Z (kalau ada) atau sesi cancel
├─ Tutor original kena (regardless sesi jadi/tidak):
│ • Zero pay sesi yg dicancel (lost opportunity)
│ • Denda graduated: 100% / 50% / 25% of 1 sesi cost (configurable bracket)
│ • +1 strike
└─ Denda = REVENUE ke XPrivate
BracketThresholdDenda %Strike
1≤ 1 jam100%+1
2≤ 2 jam50%+1
3≤ 4 jam25%+1
4> 4 jam0%0
FMForce majeure0%0
Lead timeCharge siswaHonor tutor (no transport)
< 1 jam100%100%
< 2 jam50%50%
< 4 jam25%25%
≥ 4 jam00
  • Strike 1: Warning + audit log entry
  • Strike 2: Final warning + temporary suspend 7 hari
  • Strike 3: Termination kerjasama
  • Strike decay: 90 hari rolling window (oldest strike expires after 90d)
  • Categories: SAKIT, DUKA, DARURAT, BENCANA, LAINNYA
  • Approver: L1 operator review → APPROVE (no penalty) atau REJECT (escalate normal)
  • Banding: tutor berhak ajukan banding ke L2 dalam 14 hari
  • L2 review → UPHOLD (final) atau OVERTURN (refund penalty)
  • Audit log all events
  • Optional comp_notes field — finance off-system bayar belasungkawa

Mitigations (per FC Critic + Red-Teamer concerns)

Section titled “Mitigations (per FC Critic + Red-Teamer concerns)”
  • Kontrak explicit clause (deduction, FM definition, banding process, decay) — legal counsel review sebelum tutor sign-on
  • Reliability dashboard ke tutor (self-view only, transparency) — bukan published ke siswa (UU ITE 27A defamation risk)
  • Strike decay 90d (bukan permanent record)
  • FM clear process
  • (Iter 2+) Reserve tutor pool standby coverage
  • Instrument from day 1: cancel rate, cancel-time distribution, reason histogram, retention, dispute volume, exit interviews

  • Customer-facing self-service signup (siswa/tutor)
  • Payment gateway (Midtrans/Xendit) — manual proof upload tetap iter 1
  • Auto-trigger notifications (booking confirm, reminder, receipt)
  • Semi-private sesi (1:N), bundling programs, diskon programs
  • Online Zoom integration (sesi ONLINE di-track sebagai mode, tapi link generation/recording = iter 2+)
  • Mobile push (FCM / PWA Push)
  • WhatsApp notification integration
  • 2FA TOTP (rely Google account 2FA; schema TwoFactorMethod DB-ready)
  • Login audit + account lockout (Cloudflare rate-limit mitigate; schema LoginAuditEvent DB-ready)
  • Indonesia invoice PPN formal compliance (belum PKP)
  • PDP UU 27/2022 formal (basic consent only iter 1)
  • In-app chat siswa-tutor
  • Self-service booking siswa
  • Dispute UI per-session (admin manual flow only iter 1)
  • Family group implementation (schema DB-ready)
  • Multi-office implementation (schema DB-ready)
  • Bank soal domain module (shared core schema extensible iter 1)
  • Self-register state machine UI (AccountState schema DB-ready)
  • EN locale (BI only iter 1 — admin tools internal)
  • Multi-currency (IDR only iter 1; currency_id field DB-ready optional)
  • Tutor portal login (iter 1 admin proxy; auth schema DB-ready)
  • Siswa portal login (iter 1 admin proxy; auth schema DB-ready)

13. DB-Ready Items (Iter 2+ Schema Prepared)

Section titled “13. DB-Ready Items (Iter 2+ Schema Prepared)”
CapabilitySchema elementIter 1 active?Iter 2 unlock
Multi-identity authUserType, IdentityProvider, UserIdentityADMIN onlyTUTOR/SISWA/PARENT activate
2FATwoFactorMethodActivation flow
Login auditLoginAuditEventLogging hook + Cloudflare rate-limit replacement
Email verificationEmailVerificationActivation flow
Password reset richPasswordResetbasic admin onlyTutor/siswa flow
Self-register stateAccountState machineSelf-register flow UI
Anomaly engineanomaly_flag, anomaly_type, anomaly_resolved_at on ScheduleSLA flag + double-book onlyEngine scan + queue UI
Notification systemNotificationTemplate, NotificationLog, NotificationPreference, channel abstractionManual welcome onlyAuto-trigger + multi-channel
Payment gatewayPaymentMethod, PaymentTransaction interfaceManual transfer onlyGateway integration
Family groupFamilyGroup, FamilyMemberUI / billing combined
Multi-officeOffice, transport calc by-officeSeed 1 officeOffice mgmt UI
Bank soalShared core extensible (user/auth/billing/payment/audit ready)Bank soal domain module
In-app chatChatThread, ChatMessage (optional schema)Tutor-siswa chat UI
Dispute UIDispute, DisputeEvidence, DisputeThreadAdmin-side manual onlyPer-session UI for siswa
PWA Push notifWebPushSubscriptionPush registration + notif send
WhatsApp channelTemplate store + send adapterWhatsApp Business API integration
Document upload richDocumentUpload, DocumentVerificationTutor kontrak + foto KTP basicRich KYC (ijazah/NPWP/portfolio verified)
Multi-currencyCurrency, currency_id refIDR onlyCurrency switcher
EN localei18n key storeBI onlyEN translation
Mode surchargemode_surcharge per sesiOptional field (use bila perlu)

14. Critical UX Affordances (don’t skip) [F per RAT]

Section titled “14. Critical UX Affordances (don’t skip) [F per RAT]”
  1. Atomic “Clone Tahun Ajaran” — one click handles both effective_until on old + insert bumped new
  2. Hierarchical drill-down navigation — Subject → Level → matrix per audience (NOT flat 6-column entry)
  3. Coverage gap detector — warn “Subject X has 60% combos populated (12/20)” with link to fix
  4. has_levels auto-show/hide — operator only sees Level picker when relevant
  5. CSV import — bulk entry path mandatory
  6. Per-row validation — surface errors immediately at input
  7. Approval queue SLA flag — warn REQUESTED >24h

Admin create sesi (REQUESTED)
→ Admin approve (APPROVED, snapshot pricing + cancel policy)
→ Admin proxy tutor mark Start (IN_PROGRESS)
→ Admin proxy mark attendance + materi + foto report
→ Admin validate completion (COMPLETED, 2-step gate)
→ Settlement auto-created (UNPAID, snapshot pricing dari APPROVED config)
→ Monthly billing cycle:
- Tagihan siswa generated
- Siswa bayar offline, kirim bukti via WhatsApp ke admin
- Operator mark Settlement.PAID (bulk capable)
→ Monthly honorarium cycle:
- Honorarium tutor generated
- Finance batch transfer off-system
- Operator mark SettlementTeacher.PAID (bulk capable)

Lihat section 11.

Lihat section 11.

Tutor claim FM (via WhatsApp ke admin iter 1)
→ Admin entry claim di backoffice + evidence
→ L1 Operator review → APPROVE (no penalty) atau REJECT (escalate normal)
→ If REJECT: tutor banding dalam 14d window
→ L2 Admin review → UPHOLD (final) atau OVERTURN (refund penalty)
→ Audit log all events
→ Optional comp_notes — finance off-system bayar belasungkawa

15.5 Substitute matching (admin-side, iter 1)

Section titled “15.5 Substitute matching (admin-side, iter 1)”
Tutor X cancel via WhatsApp → admin info
→ Admin open schedule detail X → klik [Cari Sub]
→ List candidates sorted by distance ascending:
Filter: subject match + slot bebas + status ACTIVE
Display: nama, distance km, Golongan, last_active, [Pilih]
→ Admin pilih candidate Z → dispatch via WhatsApp manual
→ Z accept via WhatsApp → admin update sesi assignment ke Z
→ Sesi jalan dengan Z
HR trigger termination
→ Block kalau ada FM claim PENDING_L1/L2 (resolve dulu)
→ Termination checklist:
- Final settlement payout (auto-trigger calc)
- Document return
- Access revoke immediate (revoke OAuth tokens + login disabled)
- Archive flag (tutor.status=ARCHIVED, read-only preserve)
→ Audit log
Finance trigger monthly close
→ Block kalau ada sesi IN_PROGRESS (finalize dulu)
→ Checklist step-through:
- Bills generated
- Payments reconciled
- Honor batch ready
- FM cases reviewed
- Adjustments processed
→ Period lock flag (no backdated bookings, no retroactive mark-paid)
→ Lock audit
→ Optional re-open (senior approval + audit)

AreaDecisionSource
MVP framingAdmin-MVP iter 1 onlyF+Q&A
Pricing model5D Matrix STUDENT + TUTOR (+Golongan)F+Q&A
Pricing escapePer-sesi mode_surcharge fieldΔ+U
GlossaryFriend’s locked (Sesi/Siswa/Tutor/Tingkat/Subject/SubjectLevel/Golongan/Tahun Ajaran/Tagihan/Honorarium/Slot)F
VersioningPer Tahun Ajaran + atomic clone+bump + snapshot at APPROVEDF
Audit modelAudit middleware unified + immutable INSERT-only + 7y retentionF
Anomaly iter 1Minimal (SLA flag + double-book DB constraint)Q&A
Anomaly iter 2Schema DB-ready (engine deferred)Q&A
Notification iter 1Manual welcome email onlyF
Notification iter 2Schema DB-ready (multi-channel)Q&A
Admin RBACCustom flexible permission matrix dari iter 1Δ
CancellationOption (b) locked + configurable bracket + snapshot at APPROVEDFC
Strike3-strike termination + 90d decayFC
Force MajeureL1 + L2 banding 14d windowFC
HR M6Adopt penuh iter 1Q&A
Finance M7Adopt penuh iter 1 (incl. period close + honor slip PDF + PPh placeholder)F+Q&A
KYC iter 1Friend’s simpler + foto KTP wajibΔ
Auth designFuture-facing multi-identity/IdP/RBAC/state-machine schema dari iter 1U
Tutor/siswa actions iter 1Admin proxy entry (no tutor/siswa login)Decision in this doc
Tech stackOpen evaluation di Step 2 (friend’s stack = 1 kandidat)Q&A
DeadlineScope-first, ship-when-ready (no hard ship 2026-06-30)Q&A

  • Founder/Owner = product scope, domain decisions, business policies, kill criteria, tech stack final pick (Q&A: open eval Step 2)
  • Eng Partner (Engineering Director) = ALL engineering implementation:
    • ORM pick (Drizzle / Prisma / Kysely / raw SQL)
    • Routing library (Hono / itty-router / native Workers)
    • Validation library (Zod / Valibot / Yup)
    • Monorepo tooling
    • Repo structure
    • Build / CI / deployment pipeline
    • Testing strategy + framework
    • Code style + linting
    • Definition of Done specifics
    • RTO/RPO targets + backup detail

Tech stack itself (Svelte vs alternatives, CF Workers vs Vercel/Bun, Postgres vs other, R2 vs S3, etc.) = open evaluation di Step 2 [Q&A overrides F’s tech lock].


  • From friend’s admin-mvp-1-design-plan.md: M1-M7 + A1+A2 epic structure, state machine 7 states, glossary, schema illustrations (Drizzle examples), workflow templates, RAT-driven UX affordances, audit middleware spec, configurability list
  • From friend’s 2026-05-25-xprivate-tutor-cancel-policy-v1.md: cancellation policy Option (b), denda bracket, strike sanction, FM workflow, mitigation list
  • From our Q&A reconciliation: framing adoption decisions, custom RBAC override, anomaly DB-ready, notification minimal+DB-ready, KYC simpler + foto KTP, pricing model adoption with mode_surcharge escape
  • From user constraints:
    • Auth flow future-facing dari iter 1 (multi-identity / multi-IdP / RBAC / state machine / 2FA-ready / login-audit-ready)
    • Tech stack OPEN evaluation Step 2
    • Scope-first, no hard ship deadline
    • DB-ready pattern untuk fitur WANT-to-have (family/multi-office/bank soal/etc.)

  1. Step 2: Architecture — research & confirm tech stack pick (friend’s stack = strong candidate, evaluate alternatives), then partner-authority items (ORM, routing, validation, monorepo, testing, deployment). Output: plans/ARCHITECTURE.md.
  2. Schema design detail for auth (multi-identity future-facing) + 5D Pricing Matrix + state machine + audit.
  3. (Step 3+) Bootstrap codebase + stub examples.

ItemResolutionNotes
Tutor portal vs admin proxy iter 1Admin proxy confirmedTutor tidak login iter 1. Admin entry semua tutor actions (mark Start, attendance, materi log, foto report) atas nama tutor. Audit captures admin as actor + tutor + sesi as subject. Tutor portal login = iter 2 (schema ready).
Multi-office DB-ready specMinimal: Office table onlySchema: tabel Office (multi-row support) + transport calc by-office. MVP seed 1 row. No ServiceArea concept iter 1 / iter 2 DB-ready scope. Expand bila multi-cabang demand muncul.
Locale strategy iter 1i18n key store dari awalPakai i18n library (semua text via key) sejak iter 1. Iter 1 cuma BI translation di-isi. EN swap iter 2 = tinggal add translation file, no refactor.
Reliability dashboard ke tutorDefer iter 2 (selaras tutor portal)Iter 1: tidak ada tutor self-view UI. Reliability metrics (cancel rate, on-time %, dispute count) tetap di-track sistem → admin akses internal untuk strike escalation decision. Tutor self-view portal = iter 2 (bersama tutor login). NEVER published ke siswa (UU ITE 27A defamation risk per FC mitigation).
  • Bank soal architecture detail: claim “shared core extensible” tetap abstract. Akan di-formalize di Step 2 Architecture — domain module pattern, plug-in interface, billing/payment shared model. Tidak masuk scope iter 1.
  • Reserve tutor pool (per FC mitigation #5): iter 2+ backlog. Setelah cancel rate observable (≥90d post-launch per FC kill criteria), evaluate apakah perlu standby pool untuk supply resilience.
  • Legal counsel review cancel policy (per FC Pre-Sprint-1 Checklist): non-engineering dependency. Harus done sebelum tutor sign kontrak v2 (perjanjian kerja sama explicit clause untuk deduction, FM definition, banding, decay). Owner: founder/legal, bukan engineering scope.
  • Pre-launch tutor pilot 5 tutors (per FC): non-engineering. Owner: founder. Kill criterion: ≥2 refuse re-sign citing cancel policy → revisit Option (b) → (a).

Step 1 (Scope) gates:

  • Q&A klarifikasi business model (multiple rounds)
  • Reconciliation dengan friend’s design plan + cancellation policy doc
  • Draft plans/scope/001-mvp.md
  • Draft sites/xprivate-education-mvp.pages.dev/index.html (proposal page)
  • Draft sites/xprivate-education-mvp.pages.dev/flowcharts.html (12 business flow tabs + glossary tab 13)
  • Address open items §20 (all resolved or acknowledged)
  • User sign-off Step 1 — 2026-05-26

22. ▶️ Resume Pointer — Next Session

Section titled “22. ▶️ Resume Pointer — Next Session”

Status: Step 1 (Scope) DONE & signed off 2026-05-26. User pause.

Next step: Step 2 (Architecture & tech stack).

Saat resume — paste prompt ini ke Claude Code:

“Lanjut Step 2 Architecture untuk XPrivate Education.”

Yang akan Claude lakukan di Step 2:

  1. Research tech stack — friend’s stack (Svelte + shadcn-svelte · CF Workers · Neon Postgres · R2 · SigNoz · Google OAuth) sebagai salah satu kandidat, evaluate alternatives per layer (frontend framework / backend runtime / database / object storage / observability / auth library).
  2. Confirm latest best practice via WebSearch/WebFetch untuk tiap pick.
  3. Address partner-authority items (ORM, routing, validation, monorepo, testing, deployment) dengan recommendation.
  4. Formalize bank soal architecture (plug-in domain module pattern, shared core interface) — per Step 1 deferred item.
  5. Detail auth schema future-facing (multi-identity / multi-IdP / RBAC / state machine / 2FA-ready / login-audit-ready) — per user constraint.
  6. Detail 5D Pricing Matrix schema + Tahun Ajaran versioning + snapshot mechanism.
  7. Detail state machine schema + audit middleware + event sourcing-lite (jika perlu) untuk dispute domain.
  8. Output: plans/ARCHITECTURE.md.

Gate: user puas dengan Step 2 → baru lanjut Step 3 (Bootstrap codebase).

Context references for resume:

  • This file: plans/scope/001-mvp.md
  • HTML proposal: sites/xprivate-education-mvp.pages.dev/index.html
  • Flowcharts: sites/xprivate-education-mvp.pages.dev/flowcharts.html
  • Friend’s design input: extra/admin-mvp-1-design-plan.md + extra/2026-05-25-xprivate-tutor-cancel-policy-v1.md
  • Claude memory: /home/tigor/.claude/projects/-home-tigor-Projects-XPrivate-xprivate/memory/ (MEMORY.md + project_xprivate_overview.md + feedback files)

End of scope.md v1 — Step 1 DONE. Resume di Step 2 sesuai §22.