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).
Source legend
Section titled “Source legend”- [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
0. Konteks & Brand Pillar
Section titled “0. Konteks & Brand Pillar”Bisnis
Section titled “Bisnis”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]
Brand Pillar
Section titled “Brand Pillar”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]
Iter 1 Framing
Section titled “Iter 1 Framing”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]
Timeline
Section titled “Timeline”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)”| Term | Meaning | Source |
|---|---|---|
| Sesi | Unit pengajaran (1 lesson, default 90 menit, default 1:1) | F |
| Siswa | Murid (term formal) | F |
| Tutor | Guru (term formal) | F |
| Tingkat | Tingkat pendidikan siswa (SD 1-6, SMP 7-9, SMA 10-12, Mahasiswa, Umum, Profesional) — CRUD-able stable rows | F |
| Segmentasi | Tier layanan (REGULER, REGULER_PLUS, INTERNASIONAL) | F |
| Kategori | Grouping subject (REGULER_KELAS, PROGRAM_KHUSUS, SERTIFIKASI, BAHASA_ASING, MUSIK, KOMPUTER) — bukan axis pricing | F |
| Subject | Mata pelajaran konkret (e.g., “Bahasa Mandarin”, “Piano”, “CPNS”) | F |
| SubjectLevel | Optional child per Subject (e.g., HSK 1-6 under Mandarin, Grade 1-8 under Piano) | F |
| Golongan | Tier tutor (GOL_1, GOL_2, GOL_3, GOL_4, NON_GOLONGAN; 1 tertinggi) — dimensi tambahan di TUTOR pricing matrix | F |
| Tahun Ajaran | Siklus Jul-Jun (e.g., 2026/2027 = Jul 2026 – Jun 2027). Pricing matrix versioned per tahun ajaran. | F |
| Tagihan | Student-side invoice per bulan (postpaid) | F |
| Honorarium | Tutor-side payout per bulan (internal — siswa NEVER sees) | F |
| Slot | Available time window dari tutor | F |
| mode_surcharge | Per-sesi optional surcharge field (escape hatch online vs offline pricing) | Δ+U |
| SLA | Service 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]”User Constraint
Section titled “User Constraint”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.
Iter 1 ACTIVE
Section titled “Iter 1 ACTIVE”- Admin login via Google OAuth + Google Workspace domain restrict (
@xprivate.educationonly) [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+)”UserTypeenum:ADMIN(active iter 1) ·TUTOR·SISWA·PARENT(DB-ready iter 2+)IdentityProviderentity:- Iter 1 active: Google OAuth (domain-restricted)
- DB-ready: email+password, social login (Google personal, Facebook, Apple)
UserIdentitylink table (User ↔ Identity many-to-many; user bisa link multiple identity)Role,Permission,RolePermission,UserRole(custom RBAC active iter 1)Sessionentity (active iter 1)TwoFactorMethodentity (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)AccountStatemachine: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 sebagaisubject. 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.
3. M1 — User Management (Admin) [F]
Section titled “3. M1 — User Management (Admin) [F]”Outcome: operator login secure + manage admin user roster + assign role/privilege.
Stories
Section titled “Stories”- 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)
Acceptance highlights
Section titled “Acceptance highlights”- OAuth flow restrict non-
@xprivate.educationdomain → reject with clear error - Forgot password token single-use + 1h expiry validated
- CRUD operations audit-logged (link A1)
4. M2 — Master Data Management [F]
Section titled “4. M2 — Master Data Management [F]”Outcome: operator manage master data tanpa breaking in-flight bookings (snapshot-based pricing).
4.1 Profil
Section titled “4.1 Profil”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_levelsflag (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_surchargeper-sesi optional field — escape hatch bila online ≠ offline pricing perlu beda [U]duration_minutesper-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_untilon old rows + insert bumped new rows - Hierarchical drill-down: Subject → Level → matrix per audience (NOT flat 6-column entry)
has_levelsauto-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_idlocked 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)
4.6 Misc Operational
Section titled “4.6 Misc Operational”- 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)
5. M3 — Schedule Management [F]
Section titled “5. M3 — Schedule Management [F]”Outcome: operator create + manage sesi dengan state machine tegas + audit-trailed.
5.1 State Machine (7 states)
Section titled “5.1 State Machine (7 states)”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).
| State | Meaning | Trigger by |
|---|---|---|
| REQUESTED | Sesi diminta, nunggu admin approve | Auto on create |
| APPROVED | Admin approve, slot di-lock | Admin only |
| REJECTED | Admin tolak (terminal) | Admin only |
| IN_PROGRESS | Sesi mulai | Admin proxy iter 1 (Tutor login iter 2+) |
| COMPLETED | Sesi selesai + materi confirmed | 2-step: tutor confirm (admin proxy iter 1) + admin validate |
| CANCELLED | Dibatalin post-APPROVED, w/ punishment | Siswa/tutor/admin (admin proxy iter 1) |
| RESCHEDULED | Old sesi closed, new linked sesi created | Siswa/tutor/admin (admin proxy iter 1) |
5.2 Stories
Section titled “5.2 Stories”- 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 fullNO_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 APPROVED —
config_idlocked, immune from later config change
5.3 Sesi Attributes
Section titled “5.3 Sesi Attributes”sesi_mode:ONLINE/OFFLINE_RUMAH_SISWA/OFFLINE_CUSTOMduration_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_typeenum (TIMING_OUTLIER/DURATION_OUTLIER/NO_SHOW_IMPLICIT/CONCURRENCY/PATTERN_ABUSE),anomaly_resolved_at,anomaly_resolved_by- Engine yang scan & flag = iter 2
6. M4 — Reporting [F]
Section titled “6. M4 — Reporting [F]”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)”- Student progress (siswa + admin) — sessions/bulan, materi belajar, kehadiran, foto report tutor
- Tagihan siswa (siswa + admin) — invoice bulanan, items per sesi, total tagih, status PAID/UNPAID, upload bukti bayar
- Honorarium tutor (tutor + admin ONLY — siswa NEVER sees) — itemized per sesi, total bayar, status, bukti transfer
6.2 Stories
Section titled “6.2 Stories”- 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.PAIDbulk - Operator mark
SettlementTeacher.PAIDbulk - 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 tocaller.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
7. A1 — Audit Trail (cross-cutting) [F]
Section titled “7. A1 — Audit Trail (cross-cutting) [F]”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.
Stories Iter 1
Section titled “Stories Iter 1”- “Send welcome email” checkbox di M1 admin user create form
- Same di M2 tutor create form, siswa create form
- Wiring ke
MailTemplateinfra (templatewelcomebaru) - Send log entry (who sent, to, template, timestamp)
DB-READY Iter 2+
Section titled “DB-READY Iter 2+”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)
9. M6 — HR Discipline + Termination [F]
Section titled “9. M6 — HR Discipline + Termination [F]”Outcome: HR team manage strike escalation + tutor suspension + termination flow.
Stories
Section titled “Stories”- 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_L1orPENDING_L2
10. M7 — Finance Workflow [F]
Section titled “10. M7 — Finance Workflow [F]”Outcome: finance team handle refund + credit note + monthly period close + outstanding aging.
10.1 Refund / Credit Note
Section titled “10.1 Refund / Credit Note”- 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)
10.2 Financial Period Close
Section titled “10.2 Financial Period Close”- 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_PROGRESSat close time → block close until finalized - Lock audit (who closed, when)
- Re-open option (senior admin approval + audit)
10.3 Outstanding Aging Integration
Section titled “10.3 Outstanding Aging Integration”- Reuse M4 outstanding aging dashboard
- Bad debt write-off flow (senior approval + audit + tax compliance flag)
10.4 Reconciliation
Section titled “10.4 Reconciliation”- Reconciliation export template (Excel finance-familiar w/ adjustments column)
- Adjustment audit trail visible
10.5 Tax & Slip
Section titled “10.5 Tax & Slip”pph_withheld_amountfield 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
10.6 Backup + DR
Section titled “10.6 Backup + DR”- 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 ≤4h Decision Tree
Section titled “Tutor Cancel ≤4h Decision Tree”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 XPrivateDenda Bracket (configurable, default)
Section titled “Denda Bracket (configurable, default)”| Bracket | Threshold | Denda % | Strike |
|---|---|---|---|
| 1 | ≤ 1 jam | 100% | +1 |
| 2 | ≤ 2 jam | 50% | +1 |
| 3 | ≤ 4 jam | 25% | +1 |
| 4 | > 4 jam | 0% | 0 |
| FM | Force majeure | 0% | 0 |
Siswa Cancel
Section titled “Siswa Cancel”| Lead time | Charge siswa | Honor tutor (no transport) |
|---|---|---|
| < 1 jam | 100% | 100% |
| < 2 jam | 50% | 50% |
| < 4 jam | 25% | 25% |
| ≥ 4 jam | 0 | 0 |
Strike Sanction
Section titled “Strike Sanction”- 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)
Force Majeure
Section titled “Force Majeure”- 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_notesfield — 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
12. Iter 1 NON-Goals (explicit) [F+Q&A]
Section titled “12. Iter 1 NON-Goals (explicit) [F+Q&A]”- 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
ONLINEdi-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 (
AccountStateschema 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)”| Capability | Schema element | Iter 1 active? | Iter 2 unlock |
|---|---|---|---|
| Multi-identity auth | UserType, IdentityProvider, UserIdentity | ADMIN only | TUTOR/SISWA/PARENT activate |
| 2FA | TwoFactorMethod | — | Activation flow |
| Login audit | LoginAuditEvent | — | Logging hook + Cloudflare rate-limit replacement |
| Email verification | EmailVerification | — | Activation flow |
| Password reset rich | PasswordReset | basic admin only | Tutor/siswa flow |
| Self-register state | AccountState machine | — | Self-register flow UI |
| Anomaly engine | anomaly_flag, anomaly_type, anomaly_resolved_at on Schedule | SLA flag + double-book only | Engine scan + queue UI |
| Notification system | NotificationTemplate, NotificationLog, NotificationPreference, channel abstraction | Manual welcome only | Auto-trigger + multi-channel |
| Payment gateway | PaymentMethod, PaymentTransaction interface | Manual transfer only | Gateway integration |
| Family group | FamilyGroup, FamilyMember | — | UI / billing combined |
| Multi-office | Office, transport calc by-office | Seed 1 office | Office mgmt UI |
| Bank soal | Shared core extensible (user/auth/billing/payment/audit ready) | — | Bank soal domain module |
| In-app chat | ChatThread, ChatMessage (optional schema) | — | Tutor-siswa chat UI |
| Dispute UI | Dispute, DisputeEvidence, DisputeThread | Admin-side manual only | Per-session UI for siswa |
| PWA Push notif | WebPushSubscription | — | Push registration + notif send |
| WhatsApp channel | Template store + send adapter | — | WhatsApp Business API integration |
| Document upload rich | DocumentUpload, DocumentVerification | Tutor kontrak + foto KTP basic | Rich KYC (ijazah/NPWP/portfolio verified) |
| Multi-currency | Currency, currency_id ref | IDR only | Currency switcher |
| EN locale | i18n key store | BI only | EN translation |
| Mode surcharge | mode_surcharge per sesi | Optional 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]”- Atomic “Clone Tahun Ajaran” — one click handles both
effective_untilon old + insert bumped new - Hierarchical drill-down navigation — Subject → Level → matrix per audience (NOT flat 6-column entry)
- Coverage gap detector — warn “Subject X has 60% combos populated (12/20)” with link to fix
has_levelsauto-show/hide — operator only sees Level picker when relevant- CSV import — bulk entry path mandatory
- Per-row validation — surface errors immediately at input
- Approval queue SLA flag — warn REQUESTED >24h
15. Key Workflows Summary
Section titled “15. Key Workflows Summary”15.1 Booking happy path
Section titled “15.1 Booking happy path”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)15.2 Cancellation workflow (tutor cancel)
Section titled “15.2 Cancellation workflow (tutor cancel)”Lihat section 11.
15.3 Cancellation workflow (siswa cancel)
Section titled “15.3 Cancellation workflow (siswa cancel)”Lihat section 11.
15.4 Force Majeure workflow
Section titled “15.4 Force Majeure workflow”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 belasungkawa15.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 Z15.6 Termination workflow (M6)
Section titled “15.6 Termination workflow (M6)”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 log15.7 Period Close (M7)
Section titled “15.7 Period Close (M7)”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)16. Cross-cutting Locked Decisions
Section titled “16. Cross-cutting Locked Decisions”| Area | Decision | Source |
|---|---|---|
| MVP framing | Admin-MVP iter 1 only | F+Q&A |
| Pricing model | 5D Matrix STUDENT + TUTOR (+Golongan) | F+Q&A |
| Pricing escape | Per-sesi mode_surcharge field | Δ+U |
| Glossary | Friend’s locked (Sesi/Siswa/Tutor/Tingkat/Subject/SubjectLevel/Golongan/Tahun Ajaran/Tagihan/Honorarium/Slot) | F |
| Versioning | Per Tahun Ajaran + atomic clone+bump + snapshot at APPROVED | F |
| Audit model | Audit middleware unified + immutable INSERT-only + 7y retention | F |
| Anomaly iter 1 | Minimal (SLA flag + double-book DB constraint) | Q&A |
| Anomaly iter 2 | Schema DB-ready (engine deferred) | Q&A |
| Notification iter 1 | Manual welcome email only | F |
| Notification iter 2 | Schema DB-ready (multi-channel) | Q&A |
| Admin RBAC | Custom flexible permission matrix dari iter 1 | Δ |
| Cancellation | Option (b) locked + configurable bracket + snapshot at APPROVED | FC |
| Strike | 3-strike termination + 90d decay | FC |
| Force Majeure | L1 + L2 banding 14d window | FC |
| HR M6 | Adopt penuh iter 1 | Q&A |
| Finance M7 | Adopt penuh iter 1 (incl. period close + honor slip PDF + PPh placeholder) | F+Q&A |
| KYC iter 1 | Friend’s simpler + foto KTP wajib | Δ |
| Auth design | Future-facing multi-identity/IdP/RBAC/state-machine schema dari iter 1 | U |
| Tutor/siswa actions iter 1 | Admin proxy entry (no tutor/siswa login) | Decision in this doc |
| Tech stack | Open evaluation di Step 2 (friend’s stack = 1 kandidat) | Q&A |
| Deadline | Scope-first, ship-when-ready (no hard ship 2026-06-30) | Q&A |
17. Authority Boundary [F]
Section titled “17. Authority Boundary [F]”- 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].
18. Source Provenance Summary
Section titled “18. Source Provenance Summary”- 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_surchargeescape - 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.)
19. Next Steps (post-approval)
Section titled “19. Next Steps (post-approval)”- 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. - Schema design detail for auth (multi-identity future-facing) + 5D Pricing Matrix + state machine + audit.
- (Step 3+) Bootstrap codebase + stub examples.
20. Open Items — Resolutions
Section titled “20. Open Items — Resolutions”Resolved (Q&A round 2)
Section titled “Resolved (Q&A round 2)”| Item | Resolution | Notes |
|---|---|---|
| Tutor portal vs admin proxy iter 1 | ✅ Admin proxy confirmed | Tutor 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 spec | ✅ Minimal: Office table only | Schema: 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 1 | ✅ i18n key store dari awal | Pakai 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 tutor | ✅ Defer 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). |
Acknowledged Dependencies / Backlog
Section titled “Acknowledged Dependencies / Backlog”- 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).
21. Sign-off Status
Section titled “21. Sign-off Status”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:
- 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).
- Confirm latest best practice via WebSearch/WebFetch untuk tiap pick.
- Address partner-authority items (ORM, routing, validation, monorepo, testing, deployment) dengan recommendation.
- Formalize bank soal architecture (plug-in domain module pattern, shared core interface) — per Step 1 deferred item.
- Detail auth schema future-facing (multi-identity / multi-IdP / RBAC / state machine / 2FA-ready / login-audit-ready) — per user constraint.
- Detail 5D Pricing Matrix schema + Tahun Ajaran versioning + snapshot mechanism.
- Detail state machine schema + audit middleware + event sourcing-lite (jika perlu) untuk dispute domain.
- 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.