fktd 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fktd-0.1.0/.gitignore ADDED
@@ -0,0 +1,28 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+
7
+ # Build artifacts
8
+ build/
9
+ dist/
10
+
11
+ # Virtual env
12
+ .venv/
13
+ venv/
14
+
15
+ # Test / lint caches
16
+ .pytest_cache/
17
+ .ruff_cache/
18
+ .mypy_cache/
19
+
20
+ # Editor
21
+ .vscode/
22
+ .idea/
23
+
24
+ # OCR model caches
25
+ ~/.EasyOCR/
26
+
27
+ # Sample KTP images (privacy: may contain personal data) — excluded by default
28
+ image-test-sample/
fktd-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rezayw
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fktd-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: fktd
3
+ Version: 0.1.0
4
+ Summary: FKTD — Fraud KYC KTP Detector: OCR + strict cross-validation for Indonesian ID cards (KTP).
5
+ Project-URL: Homepage, https://github.com/rezayw4/Fraud-KYC-KTP-Detector
6
+ Project-URL: Issues, https://github.com/rezayw4/Fraud-KYC-KTP-Detector/issues
7
+ Author: rezayw4
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: fraud-detection,indonesia,ktp,kyc,ocr,tesseract
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
15
+ Requires-Python: >=3.9
16
+ Requires-Dist: easyocr>=1.7
17
+ Requires-Dist: numpy>=1.26
18
+ Requires-Dist: opencv-python>=4.10
19
+ Requires-Dist: pillow>=10.4
20
+ Requires-Dist: pydantic>=2.8
21
+ Requires-Dist: python-dateutil>=2.9
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.6; extra == 'dev'
25
+ Provides-Extra: paddle
26
+ Requires-Dist: paddleocr>=2.8; extra == 'paddle'
27
+ Requires-Dist: paddlepaddle>=2.6; extra == 'paddle'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # FKTD — Fraud KYC KTP Detector
31
+
32
+ OCR multi-engine + validasi silang **ketat** untuk KTP Indonesia. Bukan sekadar
33
+ cek field kosong — FKTD memanfaatkan struktur NIK untuk mendeteksi data palsu.
34
+
35
+ ## Flow
36
+
37
+ ```
38
+ upload gambar ──▶ OCR (EasyOCR / PaddleOCR) ──▶ ekstraksi field ──▶ deteksi fraud ──▶ FraudResult
39
+ ```
40
+
41
+ ## Instalasi
42
+
43
+ ```bash
44
+ pip install fktd # langsung lengkap: EasyOCR + deteksi fraud
45
+ ```
46
+
47
+ Cukup `pip install fktd` — EasyOCR sudah termasuk, jalan di mana saja (termasuk
48
+ macOS / Apple Silicon), tanpa perlu install binary sistem.
49
+
50
+ Mau engine PaddleOCR (akurasi ekstra, ideal di server Linux)? Tambahkan opsional:
51
+
52
+ ```bash
53
+ pip install 'fktd[paddle]' # opsional; paddlepaddle bisa rewel di Apple Silicon
54
+ ```
55
+
56
+ | Engine | Status | Kapan dipakai |
57
+ |---|---|---|
58
+ | **EasyOCR** | Sudah termasuk | Default. Mulus di Mac, native bahasa Indonesia. |
59
+ | **PaddleOCR** | Opsional `[paddle]` | Akurasi & kecepatan terbaik untuk dokumen; paling pas di Linux. |
60
+
61
+ ## Pemakaian
62
+
63
+ ```python
64
+ from fktd import FKTD
65
+
66
+ detector = FKTD(engine="easyocr") # atau engine="paddle"
67
+ result = detector.process("ktp.jpg")
68
+
69
+ print(result.is_passed) # True/False
70
+ print(result.risk_score) # 0 (aman) .. 100 (mencurigakan)
71
+ print(result.summary()) # daftar check yang gagal
72
+ print(result.data.model_dump()) # semua field hasil OCR
73
+ ```
74
+
75
+ ## Field yang diekstrak (20)
76
+
77
+ Provinsi · Kota/Kabupaten · NIK · Nama · Tempat Lahir · Tgl Lahir · Jenis Kelamin ·
78
+ Gol. Darah · Alamat · RT/RW · Kel/Desa · Kecamatan · Agama · Status Perkawinan ·
79
+ Pekerjaan · Kewarganegaraan · Berlaku Hingga · Tempat & Tgl Dikeluarkan ·
80
+ Foto (bool) · Tanda Tangan (bool)
81
+
82
+ ## Aturan deteksi fraud
83
+
84
+ **Kelengkapan** — semua field wajib harus terisi (kosong = CRITICAL).
85
+
86
+ **Cross-check NIK** (NIK ter-encode):
87
+
88
+ | Cek | Severity |
89
+ |---|---|
90
+ | NIK tepat 16 digit | CRITICAL |
91
+ | Tgl lahir di NIK == field Tgl Lahir | CRITICAL |
92
+ | Gender di NIK (DD>40 = perempuan) == field Jenis Kelamin | CRITICAL |
93
+
94
+ **Validasi lokasi (via API wilayah)** — kode di NIK dicocokkan ke data wilayah
95
+ resmi (API emsifa + snapshot offline 514 kab/kota):
96
+
97
+ | Cek | Severity |
98
+ |---|---|
99
+ | Kode provinsi (2 digit) valid & cocok field Provinsi | CRITICAL |
100
+ | Kode kab/kota (4 digit) valid & cocok field Kota/Kabupaten | CRITICAL |
101
+
102
+ > Contoh fraud: NIK `3171...` = Jakarta Selatan, tapi kartu tertulis "JAKARTA
103
+ > BARAT" (`3174`) → terdeteksi tidak cocok.
104
+
105
+ **Enum (exact match) — nilai resmi saja:**
106
+
107
+ | Field | Nilai resmi |
108
+ |---|---|
109
+ | Jenis Kelamin | LAKI-LAKI, PEREMPUAN |
110
+ | Agama | ISLAM, KRISTEN, KRISTEN PROTESTAN, KATOLIK, HINDU, BUDHA, KONGHUCU (6 yang diakui) |
111
+ | Status Perkawinan | BELUM KAWIN, KAWIN, CERAI HIDUP, CERAI MATI |
112
+ | Kewarganegaraan | WNI, WNA |
113
+ | Gol. Darah | A, B, AB, O, - |
114
+
115
+ **Format teks KTP asli:**
116
+ - Semua nilai field (setelah `:`) harus **HURUF KAPITAL**.
117
+ - **Nama tidak boleh mengandung angka**.
118
+ - RT/RW = `NNN/NNN`; tanggal lahir valid & wajar (umur 0–120, tidak di masa depan).
119
+ - **Berlaku Hingga harus `SEUMUR HIDUP`** (e-KTP sejak 2016 berlaku seumur hidup;
120
+ tanggal kedaluwarsa = kartu lama/tidak valid).
121
+
122
+ **OCR confidence** — confidence rendah pada NIK/Nama/Tgl Lahir menaikkan risiko.
123
+
124
+ **Vision** — keberadaan foto (deteksi wajah) & tanda tangan.
125
+
126
+ Hasil **PASS** bila: semua field wajib terisi, tidak ada kegagalan CRITICAL, dan
127
+ `risk_score < risk_threshold` (default 25). Mode data wilayah diatur lewat
128
+ `FKTD(wilayah_provider=...)`: `"auto"` (default, snapshot + API), `"api"` (live),
129
+ `"local"` (offline).
130
+
131
+ ## ⚠️ Disclaimer
132
+
133
+ **Khusus KTP elektronik (KTP-el / e-KTP).** FKTD dirancang untuk format **e-KTP**
134
+ — standar KTP Indonesia sejak 2011 dengan masa berlaku **SEUMUR HIDUP**. Aturan
135
+ seperti "Berlaku Hingga harus SEUMUR HIDUP" **tidak berlaku** untuk KTP non-
136
+ elektronik / KTP lama (sebelum 2011) yang masih memuat tanggal kedaluwarsa —
137
+ kartu semacam itu akan ditandai gagal oleh FKTD karena memang sudah tidak berlaku.
138
+
139
+ **Validasi bersifat struktural & heuristik, BUKAN verifikasi resmi:**
140
+
141
+ - Pengecekan NIK & wilayah hanya memvalidasi **struktur dan konsistensi** data di
142
+ kartu. FKTD **tidak** mengakses database kependudukan resmi (Dukcapil), jadi
143
+ **tidak dapat memastikan** sebuah NIK benar-benar terdaftar atau milik seseorang.
144
+ - Hasil `PASS` **tidak menjamin** KTP asli; hasil `FAIL` **tidak selalu berarti**
145
+ pemalsuan (bisa karena OCR meleset, kartu lama, atau foto berkualitas rendah).
146
+ - `risk_score` adalah indikator bantu, bukan keputusan hukum.
147
+
148
+ **Untuk KYC produksi**, hasil FKTD harus dikombinasikan dengan **verifikasi resmi**
149
+ ke Dukcapil/penyedia berlisensi (mis. layanan verifikasi NIK pemerintah) dan,
150
+ bila perlu, peninjauan manual.
151
+
152
+ **Privasi.** KTP memuat data pribadi (NIK, nama, alamat). Pastikan pemrosesan
153
+ mematuhi **UU PDP (UU No. 27/2022)** dan regulasi terkait: punya dasar hukum/
154
+ persetujuan, batasi penyimpanan, dan amankan datanya. Library ini tidak mengirim
155
+ gambar KTP ke mana pun; hanya pemanggilan API **data wilayah publik** (kode
156
+ provinsi/kab-kota) yang dilakukan ke jaringan — dan itu pun bisa dimatikan dengan
157
+ `wilayah_provider="local"`.
158
+
159
+ ## Lisensi
160
+
161
+ MIT
@@ -0,0 +1,124 @@
1
+ %PDF-1.4
2
+ %���� ReportLab Generated PDF document (opensource)
3
+ 1 0 obj
4
+ <<
5
+ /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R
6
+ >>
7
+ endobj
8
+ 2 0 obj
9
+ <<
10
+ /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
11
+ >>
12
+ endobj
13
+ 3 0 obj
14
+ <<
15
+ /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
16
+ >>
17
+ endobj
18
+ 4 0 obj
19
+ <<
20
+ /BaseFont /Symbol /Name /F3 /Subtype /Type1 /Type /Font
21
+ >>
22
+ endobj
23
+ 5 0 obj
24
+ <<
25
+ /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
26
+ >>
27
+ endobj
28
+ 6 0 obj
29
+ <<
30
+ /Contents 12 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
31
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
32
+ >> /Rotate 0 /Trans <<
33
+
34
+ >>
35
+ /Type /Page
36
+ >>
37
+ endobj
38
+ 7 0 obj
39
+ <<
40
+ /Contents 13 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
41
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
42
+ >> /Rotate 0 /Trans <<
43
+
44
+ >>
45
+ /Type /Page
46
+ >>
47
+ endobj
48
+ 8 0 obj
49
+ <<
50
+ /Contents 14 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
51
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
52
+ >> /Rotate 0 /Trans <<
53
+
54
+ >>
55
+ /Type /Page
56
+ >>
57
+ endobj
58
+ 9 0 obj
59
+ <<
60
+ /PageMode /UseNone /Pages 11 0 R /Type /Catalog
61
+ >>
62
+ endobj
63
+ 10 0 obj
64
+ <<
65
+ /Author (\(anonymous\)) /CreationDate (D:20260604012807+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260604012807+07'00') /Producer (ReportLab PDF Library - \(opensource\))
66
+ /Subject (\(unspecified\)) /Title (Tutorial Upload PyPI) /Trapped /False
67
+ >>
68
+ endobj
69
+ 11 0 obj
70
+ <<
71
+ /Count 3 /Kids [ 6 0 R 7 0 R 8 0 R ] /Type /Pages
72
+ >>
73
+ endobj
74
+ 12 0 obj
75
+ <<
76
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2286
77
+ >>
78
+ stream
79
+ GauHLD/\/e&H88.EF4G]>tmuAH[pQ9f4F9kL2;!`%J<OO(+lk=SO>'Q0^Q:;8A.EKm)3ks-9rPL,k(N`_rpGuJq:\6rjto+?7]N)@=h'Z\H1/+2D!b&pWJab:Pe!)5.,s/Sni["&/lBti'J<PA@U8">iJkG%8Pgml8^KL%`.V""XSrKdhCLNIrVnT6,>Cb$/-<5;7#r70o81JQ\',o`%ucOQ7:$1hCN$NMGas;8lg`:k4e?&c12KREllog02H$P$'nBA^!n3QAKW,`e:R'*`"28Q=Ot!??jXJ!P+75FH#rdrYUT,3pm)"MrM9ODi\!t+^]&cHmp3BKT'mLSUu9l`U!@$oJTiIIM<hbh&DODj9(<QZ9Xi((5-K;Xe0gRLg9,T\&oq2`O`d6J9)]@5\R')])33,.G;(#rG]u(@OX2Pi)46%6^L4kS7:'c\_h^A'F-.mFo3l%S!*^=<!QV`q1?tom3AtknC3oZ&)=E$HX^`,dM"rG+oC4U'kAF(p2tGJ;+0W_RfUd"cjuuRfp?N:6Ic;4uYCqiH,0`DqWjjJ\aigXAA&>N"Am5Od._78X/GJpQp-.o9@/,@A9Kb6bje)*&;"!aa(<kWJZB!8(i<OmVDYA#?!O-*G`8qjNU&^<UOsLD_%S\;(n@HmJ:kQ=aSBnE1E#SlqY&VbQqlc.9+pH^[$)P@i?dt@oZbMEB3&mLhVP@W@kSP6AIUMCT.l#',8R4N-3nJBWed_TQXt:<*=\#HAG`AG4HS=&AZ4^8EB+;k=$gZ*&'m8=*dG<>l<AOsEQ`i[:0gB[`Ob?Q8R*0!*YBbN>ZMKc8:r&5q;I/U`[`G0KY?EFba6`:30?$E!X:bZm@Kc1,GN#.dSqV;b",g-;:`@FVHl03g;/A&q>aDJ&5s!/D/NZ..l.5F>m(J=LF0nOZSH2cgkNrk2GF+^ZC1Ipkd3H'TgEG^M?'q/nW(stFZX2DlCM%2j2V/&1ZB__oc5)=5E#3?(cKe/5Wf'7kH+>m7TRfpe8Us9VoU,^E#WVnl<\ljd+Y'p+SY#L68XrQt"W%+32:s`>Eth_SCfE`m!(JWeG@>X=5)CdY-jAbu'G>kS'$?)"$N[J8DL!SJRUI4W^hq,tp8_$4[N7f8AY(8L,P>[i;Ke+Y*hQmVhP,<X='gfD:Z`]"'Qo8_T&?*]P&KnHAQ&*g'#dQ[Ae^.qPY!qjY[T>H^rJK]N#<DXNCqp_X/["&2OiuV2Cqtmo=B`M(@jAmh7@u07;E-/n(qPSS"aZ(8d\#1T.t->2jI\+B-MdA-efS$1:GaJ&P`,U)/!fgjYgpX=]^t;719o<,K^QDq%ZO.I"t;*a_R:<0o&Muh"M7&6DSil[XdX?nPGl!Sjdn@Pc%TM3mS9qRc>%LMc!lF+GqrSK`.Q]Jeem:+8Z1Z2sbdqFB`FI*U^M-]>)X?NR>cP2#UCW:$ofcN<`\4Ia06ETIbl!diRjn#!@Z7"g^RcJDRQ26e,KK'fYXk&:Z-H_q-K[Q$g/Q\76k;eY#<@SgMoDX'$o%10pe3S]A%'Y$dFC*S@,%W`>\32s[$X:l'5r-*XB$ZL!;hXg4n>_S^+*R_,[)H8W;"KTOaK1Je4ug6lZ;QW&\4Y_3Un]4VAIQPJ-TH9=qD/-7K9Z@/^pp&iNc6h@p:%!u?>TuB9SON#k87RCB_`?),VX6M`!6^.lC$))5TDB4J1cBpptG85nKK/]9Kq(+K^F$pdkJLoL'/@<TD[gV"Z3,bfFPZ'#"(0/EC1T=CN%^)8#m]jK\iGE(L8-j(d;s[/3E+!9"PM94-3nCoc?LTa!GU_0SO'.&s(($k7-f:[5Q5nUNpB_01L5@:V+AHq#6M=))XE[nSWScNrq$grQ-V>)EXA09,M$@=@k6!M1nGF<$db\7t!L(R3Jn^D/<MH!Zpspm6UV_gB_Ma(K807npl$O3]%Eog.UA*s'h"V%@UO`kdrF"5Y*H5s93;_urLWd,MR%6:G*Mr!Q./tl@.p&ltFYrE$RYTf>#)5mfW+`OZWK%]7VGZD9:N2C1Xi;GZWgV0"/'4PZ2:F=:]<>K:&7Qkf99E2'oIjK<(@o6''efU(CC8DbEPNZ=rm?72E/0)B_$;jga'`55];]fVl`#pe28C:u%Nb@)n@:G2s/l79\jB2aUIKoZ>hu[5g&@M-m[e&uV.uIuA)=n[8eG9m,-"/]*Ql:,#de=/\2r[S#$#J>=i!_P2nBtp%8Rhh[-?'i`<l;TY.'oK#I)]6<3,(BP,7l$P*RQ@b7/-o)Af"Y*^t.4D=Tm!`Jr[8)9c$hD598&iT,JE3hI8~>endstream
80
+ endobj
81
+ 13 0 obj
82
+ <<
83
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2586
84
+ >>
85
+ stream
86
+ GauHLH#FW\(B<9aik`UbEY))hEK1aF5T7[WR^T9Jao[LO_Or`M7F,*HViL?4pQ77p8%2qTCV^nuO7s]Fn"pO0IVeU=blE24_;O#OgO[`\Cl`fpq?>`9cMfpN((EXO"(DML(YD!CaKd$4jP<t!RtJd0e>455L_;).5'W=M]Bb(00RIeo7.Go1%1<DWbHPqh"upA,Z;@#mNpAb<g(k!r0S!")^$?3(.i:?C!8!Ca0mrcj)u)**_A-."WX="XUO*ikBPH]uKUP1pr+upM@$*.s?neUCMI7l\/CT3i0O,%DGDMC^O7,shqV-krM,\-kJ%W\jY=*Pr?UuaZ18(4/*829&iT:OlnO)1;i`U0[3;CFImB:Ih,k[%O',&pg4l;'D-e,f#OD0gd,lc((%te#ZicR(Y'J)jiYX.1pQElJ2i,n\jNXB-1$<jk=N<jY.*t8CO4(Kr4LoY7C`a&-b+qj*\=QUjs1m^h1q1:n5kL2JG=MV"/@kPU%*F*s74hXrsC=&!D..poKM76\S)],sbrbX(ZXH4;uMT8(2)&faJ"<K&>p*'m,\#h&HXYe*PBd#AuEV*D@7%mW`)QDPkUE^Z!d0%`dpFUuCl'DdeT,0NVZ[>%[jsfN/n).X"Gm`Tg7-&UB9!Aq#<jDR?I(>FN;,!.bc`mEC*E8Ibd]&+-:ANr4IC_`i>=!8UGLtBt*#tN5RWD!]e<I`fT"pF6>eplAn?gL!@t&XBk/VW(q[p**WtT]L6IZ+s$I_#--=E)0i[?ME7J:UDG)-G-[_4NW:g<T$pA:pLCKX_3RpK6<]<O;BI<5#RC1YQ2@An6I-_Rh(9XmbuKpp82`[W8IoYc\=(,NqfHhcXgl`4CM_I"i/nbA9;J@?PBcM'H?qZK+>$b34c>5RWA=)&s.mM!IC<fuBG.D9VnFMBJS=]>H4pAu%$=>!3cU+O`b)pjnUC1h)C7%u$LomU>*8r`=r]M]S5/*+k6,>+o_OsNfJa8D.C-GZW\[*"GTa`/NFD&*&78cWMSU6s*njU%W@3oO.ZX+5m#5V>LYSh*<hbo-Ac9OY)'=hP^^1t4p'9aZ/)W'j[`HiW2H-`R2bjI_ZI419(plm=<j^Kd^_O[FU*kI@=Lat3>h8h"d<mcbO.Hi"VGPpl4Xg[XD$0m.hFR=$U<#Y5m8+lUeJHROf^:+EL\STi6iFCk87e,(#X`1rl7kap<t1oiKR[&KU(7ii->?_2S4:O6]=:G+Dk'U<-RXUkt=Ck4fnkh<$k[d:5_`BDe7VKgfI51$]YR#$VCYpOsi>gB"Do2AJ///!@ePe4*0;>]aF`XRQc1sbiIOMJ&)MH!RE0C=Yd,JGJ3_Fj8V/1u',Juisu_rJnjB&7:F=_UKbQmJ+co/lJFj@qPW0n?KFSXS13`^Hgf7c2%XX5-s7kISS7b[3]^7&#P!797KQ7kBrrlWP!+;I`$]'j:Bto$qmHo?15%g&-8Qnt/t"s/prq)a<6LE3@A[qqMmTV@nU^5KjYm,Vh6J@qZtBLkAVCIYFf`nM8V%]M9@@L#/>g%'.'E]\<'eR6b3*9N9\GD*-`p"O=8>rQW=Ke2Dqj!m4nKM_tDk9_Lor/u')[4t!T/ibVGO)O-TF]AMkH(SOK3LeH,=5%[p]Ih+IAAf.dS$K!-q&5a75H$WZCTe?gj%qY>7'%fC%5'Cgco:j%%_T5;1lWh&-73Y)78E<Y?"FU&H&:2NJ@C3I[+8K<*$qI6plQkaDljh.Lakkg\XC$X&[#9PX;Dr33Y>;_]9=,,NO3UL[XUR:f.J28:r#U!k=*Z]HYckl\VSd0cM^@13X&^Lj.pqcPRiJmP$;j22HDp15S]T_L'/j6;?-%kYZ#YSV1"Ek\n`*%j3QSV=le9U,<$[2=]#:81(+"a3Q5GpDmYS3cY:D5HQ>sFJ<I3osXf3,\mj>eCGg>@\X0>e\42#54AuI.Ol4Rme@_n61rXOMRAEYSS(+BKS9$ZE"n4sm<WoLlXR:B/+@%M&<CT0Ug@utIU<<BqC\b2]A65R42>>M"IS(QJ+JO?qDn$%*Ka>o]10\X.c`R>!H._edc;d)<Q(`c.U;4/NHknt-3`\Q+sUruDJ;MDP4XCOapi#U"G41roqmXXL4.dg4]C9JYH@S3o,'IcRb)XGXpd62G2RItO`)qmt_.p/5sdZ?"DDu?VVl-nFl*5V]^kYjp\dW[AU,/lHLN\q?XYDO=#TEZ-:jW939T^s.\3B+'#.'s)B@f\DBc5Z'Z"Aq]m#,UR-9Z(=WM_m<qRKQPkN@QV/27D?*.d2h<Ys;(u1IN$"Zdc@@GO<+GqAK>%&)DQ,TF\(sSip[HrMm'4F*#XP`;6^g=kHl_LJUnSF=5>KEn[>dcE):u:'PK5K1DYXK-ouK`-gC/_RF-op4>c?Rcs$J.I-C!$FIn%PnEsE4dU!tGb$<):6h3[Js!,blk3].:TtA!$Oe$8hOF8;>XMonh\#0I40YS^C:_/M_db_#`L,'h]'F*0grnhX!_;93dB34FhmRrh*=\KGn4opSl3Y+p.a/b+hXmH/YMO@P\2RmMK["W>.2u/iU,-3JRA(X9kGbuNWLc#i[Lp`j)GT:@-tG*NfY7G.SG`tB$Fg<~>endstream
87
+ endobj
88
+ 14 0 obj
89
+ <<
90
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 826
91
+ >>
92
+ stream
93
+ GasIda_oie&A@rk"pbRG#"3MIW?.PY?.+@pWeUYhd$?4=elGC0i-]rCMPAg=P)95gOu%%5]GWJt37op'$\7t+/6<5sLNj%t&de)0p^kc#cNmOjE!_3^:hg2f8!HFcphX!*Z]7AHKT_uP7CZAA84@JN"S`[SM]%-+5jKQr#=aI[HjkP'Cuh<-Tj36j%&63hUEM6t^:K?.i"tPp<o/!+>lVHilZ`k?Bq'"pb.iZ*(?3;heL+f%!"fP;N?C))-@-:ImL[@j*.HC_AJ8/ff:Pi(M8o1A!n,CW_A,pI"?.DWs,"%sGXbO:"Xkf+=!pKuI%R)XTa:l68O^QXY.1]TdcE@;;\3i&OJ*'fg6laNh1faH@d2?gHb<SN%W-6h`e6Sl;>LU7-_&l-Q68qM^1"i*-U!47.O'c9&/teV:LGVB,'kdu[**J90`g+n6&4DTR+KC40!ft6\#l^R!4OSZ]1q^^r=HG6I<:nk\?*-h!?*M+DYN'0RK7HqYW?pl>N?0]eF.87EcOYHH/d7G`*Y20,apJUmI/EabNgJC+UX<c&^HBO9jcbD#dEM,T8*.*WV/_p,K8]tpa`?eWY]f&/?JllkG!9Rk;TQf%^s3JTc1(M;'VUe]DkNT742PTnn.:<?0)IK[V<%UhY,1'QC'@i&]NmC1c!^nkJRpb4n+VBqEEa.oS.gcf<.Ri9l'>?JtT/#Dj(knS]_[[mp)8E17\4C!l'B+2=5Y'+DI,FY2!$@;139T<=(t]?o"8`:pAcRgV\QG>WfR^*hI<^pp@1BLCa7fD;)@FgPm6SDundsHerhLH2bF+g/gjiB\]$:0`(qP$VZc~>endstream
94
+ endobj
95
+ xref
96
+ 0 15
97
+ 0000000000 65535 f
98
+ 0000000061 00000 n
99
+ 0000000122 00000 n
100
+ 0000000229 00000 n
101
+ 0000000341 00000 n
102
+ 0000000418 00000 n
103
+ 0000000523 00000 n
104
+ 0000000728 00000 n
105
+ 0000000933 00000 n
106
+ 0000001138 00000 n
107
+ 0000001207 00000 n
108
+ 0000001495 00000 n
109
+ 0000001567 00000 n
110
+ 0000003945 00000 n
111
+ 0000006623 00000 n
112
+ trailer
113
+ <<
114
+ /ID
115
+ [<8f4ee96732a5a80fb288346d97b09bc5><8f4ee96732a5a80fb288346d97b09bc5>]
116
+ % ReportLab generated PDF document -- digest (opensource)
117
+
118
+ /Info 10 0 R
119
+ /Root 9 0 R
120
+ /Size 15
121
+ >>
122
+ startxref
123
+ 7540
124
+ %%EOF
fktd-0.1.0/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # FKTD — Fraud KYC KTP Detector
2
+
3
+ OCR multi-engine + validasi silang **ketat** untuk KTP Indonesia. Bukan sekadar
4
+ cek field kosong — FKTD memanfaatkan struktur NIK untuk mendeteksi data palsu.
5
+
6
+ ## Flow
7
+
8
+ ```
9
+ upload gambar ──▶ OCR (EasyOCR / PaddleOCR) ──▶ ekstraksi field ──▶ deteksi fraud ──▶ FraudResult
10
+ ```
11
+
12
+ ## Instalasi
13
+
14
+ ```bash
15
+ pip install fktd # langsung lengkap: EasyOCR + deteksi fraud
16
+ ```
17
+
18
+ Cukup `pip install fktd` — EasyOCR sudah termasuk, jalan di mana saja (termasuk
19
+ macOS / Apple Silicon), tanpa perlu install binary sistem.
20
+
21
+ Mau engine PaddleOCR (akurasi ekstra, ideal di server Linux)? Tambahkan opsional:
22
+
23
+ ```bash
24
+ pip install 'fktd[paddle]' # opsional; paddlepaddle bisa rewel di Apple Silicon
25
+ ```
26
+
27
+ | Engine | Status | Kapan dipakai |
28
+ |---|---|---|
29
+ | **EasyOCR** | Sudah termasuk | Default. Mulus di Mac, native bahasa Indonesia. |
30
+ | **PaddleOCR** | Opsional `[paddle]` | Akurasi & kecepatan terbaik untuk dokumen; paling pas di Linux. |
31
+
32
+ ## Pemakaian
33
+
34
+ ```python
35
+ from fktd import FKTD
36
+
37
+ detector = FKTD(engine="easyocr") # atau engine="paddle"
38
+ result = detector.process("ktp.jpg")
39
+
40
+ print(result.is_passed) # True/False
41
+ print(result.risk_score) # 0 (aman) .. 100 (mencurigakan)
42
+ print(result.summary()) # daftar check yang gagal
43
+ print(result.data.model_dump()) # semua field hasil OCR
44
+ ```
45
+
46
+ ## Field yang diekstrak (20)
47
+
48
+ Provinsi · Kota/Kabupaten · NIK · Nama · Tempat Lahir · Tgl Lahir · Jenis Kelamin ·
49
+ Gol. Darah · Alamat · RT/RW · Kel/Desa · Kecamatan · Agama · Status Perkawinan ·
50
+ Pekerjaan · Kewarganegaraan · Berlaku Hingga · Tempat & Tgl Dikeluarkan ·
51
+ Foto (bool) · Tanda Tangan (bool)
52
+
53
+ ## Aturan deteksi fraud
54
+
55
+ **Kelengkapan** — semua field wajib harus terisi (kosong = CRITICAL).
56
+
57
+ **Cross-check NIK** (NIK ter-encode):
58
+
59
+ | Cek | Severity |
60
+ |---|---|
61
+ | NIK tepat 16 digit | CRITICAL |
62
+ | Tgl lahir di NIK == field Tgl Lahir | CRITICAL |
63
+ | Gender di NIK (DD>40 = perempuan) == field Jenis Kelamin | CRITICAL |
64
+
65
+ **Validasi lokasi (via API wilayah)** — kode di NIK dicocokkan ke data wilayah
66
+ resmi (API emsifa + snapshot offline 514 kab/kota):
67
+
68
+ | Cek | Severity |
69
+ |---|---|
70
+ | Kode provinsi (2 digit) valid & cocok field Provinsi | CRITICAL |
71
+ | Kode kab/kota (4 digit) valid & cocok field Kota/Kabupaten | CRITICAL |
72
+
73
+ > Contoh fraud: NIK `3171...` = Jakarta Selatan, tapi kartu tertulis "JAKARTA
74
+ > BARAT" (`3174`) → terdeteksi tidak cocok.
75
+
76
+ **Enum (exact match) — nilai resmi saja:**
77
+
78
+ | Field | Nilai resmi |
79
+ |---|---|
80
+ | Jenis Kelamin | LAKI-LAKI, PEREMPUAN |
81
+ | Agama | ISLAM, KRISTEN, KRISTEN PROTESTAN, KATOLIK, HINDU, BUDHA, KONGHUCU (6 yang diakui) |
82
+ | Status Perkawinan | BELUM KAWIN, KAWIN, CERAI HIDUP, CERAI MATI |
83
+ | Kewarganegaraan | WNI, WNA |
84
+ | Gol. Darah | A, B, AB, O, - |
85
+
86
+ **Format teks KTP asli:**
87
+ - Semua nilai field (setelah `:`) harus **HURUF KAPITAL**.
88
+ - **Nama tidak boleh mengandung angka**.
89
+ - RT/RW = `NNN/NNN`; tanggal lahir valid & wajar (umur 0–120, tidak di masa depan).
90
+ - **Berlaku Hingga harus `SEUMUR HIDUP`** (e-KTP sejak 2016 berlaku seumur hidup;
91
+ tanggal kedaluwarsa = kartu lama/tidak valid).
92
+
93
+ **OCR confidence** — confidence rendah pada NIK/Nama/Tgl Lahir menaikkan risiko.
94
+
95
+ **Vision** — keberadaan foto (deteksi wajah) & tanda tangan.
96
+
97
+ Hasil **PASS** bila: semua field wajib terisi, tidak ada kegagalan CRITICAL, dan
98
+ `risk_score < risk_threshold` (default 25). Mode data wilayah diatur lewat
99
+ `FKTD(wilayah_provider=...)`: `"auto"` (default, snapshot + API), `"api"` (live),
100
+ `"local"` (offline).
101
+
102
+ ## ⚠️ Disclaimer
103
+
104
+ **Khusus KTP elektronik (KTP-el / e-KTP).** FKTD dirancang untuk format **e-KTP**
105
+ — standar KTP Indonesia sejak 2011 dengan masa berlaku **SEUMUR HIDUP**. Aturan
106
+ seperti "Berlaku Hingga harus SEUMUR HIDUP" **tidak berlaku** untuk KTP non-
107
+ elektronik / KTP lama (sebelum 2011) yang masih memuat tanggal kedaluwarsa —
108
+ kartu semacam itu akan ditandai gagal oleh FKTD karena memang sudah tidak berlaku.
109
+
110
+ **Validasi bersifat struktural & heuristik, BUKAN verifikasi resmi:**
111
+
112
+ - Pengecekan NIK & wilayah hanya memvalidasi **struktur dan konsistensi** data di
113
+ kartu. FKTD **tidak** mengakses database kependudukan resmi (Dukcapil), jadi
114
+ **tidak dapat memastikan** sebuah NIK benar-benar terdaftar atau milik seseorang.
115
+ - Hasil `PASS` **tidak menjamin** KTP asli; hasil `FAIL` **tidak selalu berarti**
116
+ pemalsuan (bisa karena OCR meleset, kartu lama, atau foto berkualitas rendah).
117
+ - `risk_score` adalah indikator bantu, bukan keputusan hukum.
118
+
119
+ **Untuk KYC produksi**, hasil FKTD harus dikombinasikan dengan **verifikasi resmi**
120
+ ke Dukcapil/penyedia berlisensi (mis. layanan verifikasi NIK pemerintah) dan,
121
+ bila perlu, peninjauan manual.
122
+
123
+ **Privasi.** KTP memuat data pribadi (NIK, nama, alamat). Pastikan pemrosesan
124
+ mematuhi **UU PDP (UU No. 27/2022)** dan regulasi terkait: punya dasar hukum/
125
+ persetujuan, batasi penyimpanan, dan amankan datanya. Library ini tidak mengirim
126
+ gambar KTP ke mana pun; hanya pemanggilan API **data wilayah publik** (kode
127
+ provinsi/kab-kota) yang dilakukan ke jaringan — dan itu pun bisa dimatikan dengan
128
+ `wilayah_provider="local"`.
129
+
130
+ ## Lisensi
131
+
132
+ MIT
fktd-0.1.0/TESTING.pdf ADDED
@@ -0,0 +1,124 @@
1
+ %PDF-1.4
2
+ %���� ReportLab Generated PDF document (opensource)
3
+ 1 0 obj
4
+ <<
5
+ /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 6 0 R
6
+ >>
7
+ endobj
8
+ 2 0 obj
9
+ <<
10
+ /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
11
+ >>
12
+ endobj
13
+ 3 0 obj
14
+ <<
15
+ /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
16
+ >>
17
+ endobj
18
+ 4 0 obj
19
+ <<
20
+ /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
21
+ >>
22
+ endobj
23
+ 5 0 obj
24
+ <<
25
+ /Contents 12 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
26
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
27
+ >> /Rotate 0 /Trans <<
28
+
29
+ >>
30
+ /Type /Page
31
+ >>
32
+ endobj
33
+ 6 0 obj
34
+ <<
35
+ /BaseFont /Symbol /Name /F4 /Subtype /Type1 /Type /Font
36
+ >>
37
+ endobj
38
+ 7 0 obj
39
+ <<
40
+ /Contents 13 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
41
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
42
+ >> /Rotate 0 /Trans <<
43
+
44
+ >>
45
+ /Type /Page
46
+ >>
47
+ endobj
48
+ 8 0 obj
49
+ <<
50
+ /Contents 14 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
51
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
52
+ >> /Rotate 0 /Trans <<
53
+
54
+ >>
55
+ /Type /Page
56
+ >>
57
+ endobj
58
+ 9 0 obj
59
+ <<
60
+ /PageMode /UseNone /Pages 11 0 R /Type /Catalog
61
+ >>
62
+ endobj
63
+ 10 0 obj
64
+ <<
65
+ /Author (\(anonymous\)) /CreationDate (D:20260604012807+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260604012807+07'00') /Producer (ReportLab PDF Library - \(opensource\))
66
+ /Subject (\(unspecified\)) /Title (Dokumen Pengujian) /Trapped /False
67
+ >>
68
+ endobj
69
+ 11 0 obj
70
+ <<
71
+ /Count 3 /Kids [ 5 0 R 7 0 R 8 0 R ] /Type /Pages
72
+ >>
73
+ endobj
74
+ 12 0 obj
75
+ <<
76
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2264
77
+ >>
78
+ stream
79
+ Gb!;e>>s99'Ro4HS8"l_cimk"Z=Wd4Ksk4LQF(27Za9#bLdVA)^8/Jraj0n\4d*'i6L4iQ02%$:q+0\OF$9m;(4N4X*^p'IL2d'N!bF'u!Qk_(iCA,Sh#"fU/B@?!#==-f"U2bjMu#'%PJ%eL$f<7jm;R#lLG7\s^`A#:gP/\Dc-&7\MBA@*6nk:"&]*l=i*1N2MaN??CmT]C/Ku`A^bCB=GNZkB\7/.I]2TPU3</"AcA)K]<Oj%08U:BSD_QQacV#59B`UD;+%tOD&[oRV1mo,AMIE1;8b"BoEJ#DHBY*R2dGN0g-Pr*/_jC+2H`aH1Z961e&:q_Z@8>i_#a]o%%bGc=+Pa8N'Mg\PW*B.p9B01]o8(XsmM_WD6%3$CP>Mr5Vs5A7\3%Emk2U#Ke/U#p3+@TX0/AcSN.En<I)]RGMo<;2J^JS,E%sqqF.jc)!j77@@,kM!N-X,26.%P2'hBF,fD$Ahp4k-@K6VEZ:oSTE]Z=cs?;Do6oQ9Une=J!lGhf05HId@[!jFE>OG:F2.a8%!#R4taM(S#?>.sSB/?bcI@jS+V<R[uE>1<20K)MC%-PIB3_M)Vk*!!=4$Xe)3s0mB+p3I;TfdeKBk7RYJQ[+/CO%!/](`DT[,PrJ@o+7E%F"NmV&(,@T%d0@)D^WdR!q'L4R:kPFDk.[CY-=AmT:2%p1"#\hZmgPZQuc2o/T(GEaVZD?,u-(t9rN:W.O)5BbC"DFWgjSR/<NOZ:cO1\:M$[U_'+cu[$\u1&B;4#DIjT:0WVZQ(gNso?,/gR7`i.G@>nn\`DjK!PBAj`XP!OaO-<[WJV7g(?6d&j/l',g1uHGlJU^rGi8T!5]]V$Y`]*uq,\dK]L%33?T0Abe6C:G(Bo[RI%mIcL:0GZm6bjCn0RpAV335R*,\\MY7n@,sk:.JWBn/\3Q^Oh*E:4dj/ANg]9lAc#CX;CC$JN-L6B>PhQl\S7Et\b_d]+PX8).oGRHS#MB8T;GAf.L<:1XD=)-tF-a^(YecBDJ\RKTcfK^^!$,:s2Y-N/$e;]?[O=X'g1^_-6Z\C);?4=kMgB+a#T#3'^Eni_B3(7):ASM.E\0>(WH*H*Ir[bm"TRCRKL[:cKL\Uk_<3tkuL1([0UnZXS_nZ.*,kmiVVYSN_1s#QXKBkt3r(,;t]H%,jeE2s-/70TgA1C`fM_/";E8%aUK0#NsVdr!)7_Pl3tKu\L[29f^=ik>.tBu/)+=YI@4(:^HT>M`"h[$qNW5sbgb!,hOAqHL9oU5R/tf\rX[P27C"K:p?ogL1`$H[G%%3R%rI:8k#n>4mQ.Z%Gk@JiMf;ekJ,;0-qI9ScTIS7d;Tt[jY1'7EcP$:"UU@@]to7L;2WWTGt2ICNR/OTqI`*1leWq>t)&b?<^'$)j=Hnl#,0"iijVpL=i/eECIf(fHB.O,+(jO+IR4<`:hb)iM]ep?a87e=&Ij*j.`ZS#7jj_DM+>3F_Z$'IY,hQK-+<j?UitK7_aY.Ja:Us/Js;soEcAUh[0AjV[X,P_@cXu@5Iq,,drPZ)`Cp[hi>W5Y]%Ek9AJ9afEUb\fPK5"56QfL^T+)*L.^W#1rI4'Hfe0Ac[;%bS!:,=d!cBBJXL<HXJQf#>?K7AHR))tQbZkCZ#.7IbsDT#5o=!:4Tq0B0(21hPZtg_h-cB&-JLq$#8oGI2ih5K<(OZ7PM8G&h@eQ=kE!FTpZM3$eDCGi'1!J4eR1+*da9XAV2SNI$.Tu_?d)Jsno_9%]`i@AmB2AX>ql(j0pZf#N&I`OK+Omhkh6EXU%kN0)D!f4hO?`]'@M#.g];<=9G'<(b?Pd-d!kPcNS$N4Oua8T0AO8mU2-"qg*!GsZn6mW;jb;&;c+=c8GF(.=O+5,,R9*FR*+aTBp-Zq&APu3I^_cCrW]I]?rWl;-IKK)aU%j66ladRmdnO"i!A:$AbaL^U)I"VBg"_GLQ*Bs5-P?`aAg$[.fLb^),I_&,s8+MR]<Gb?X@'.2f<?Q)ta)-I:&KkR'<QY-!?<Wl/L6*R?"hJFc=N\K2e+;d^^8,ck-/Z+XT1G2<DQkn:?DKi[[Xcb;)BO4^p?n<V[0"k<K?d.:`q[+O(93Wd#"<5nI\>$q$E(WQK4qN>6WIZ&0-5Nn(eVAhJuY*(;R5l\PPCM-3`P,?;H?^(0.43Qct7f"6_!_5rrEUu3-d':JmnXJ21Ec`nh4=V\,6Kgf2#5/%Z/NrDQ+=&rh\YP+/_(*p-nY7?lee5rj#QS3J2o?ni^4-L7#e;VV;gC<NJ#>1rQV#~>endstream
80
+ endobj
81
+ 13 0 obj
82
+ <<
83
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 3355
84
+ >>
85
+ stream
86
+ GauHOlZ:cN'*%C7U8tHjMX2Xp7W3--&UPN3HbJ8QDeeUJU';HBN#nK1nTk02lPY88#Y;7c@$_>N8H"qT9i#u676nh!,6(GeJ.G",^EPp"(s[[LM?1V!piUiTh_R\Y*ChnN+gtt7";K*\M/,Da3",4fgU._o2[qHH;pfF1!lJ",=P"^*0`UqWM;g0p/QlaP<67J]0Yk#*,E#,-<RWN/*24pklI[f_Tm(W8]S)EEfl.\RF9X[R?,4_S*\LU4VF_W<J`.7NJ)8Nb8iVERX'"8"0PjJ2p?5k<X41b_gp:CN5&hJT#V%a4Y+))?s-ek<L96msI/\r5kMkdJb;!!!HnZ!sdEKHV%j'#83\8>"5qu?p7J;Ui+2l=bUe9X:M<64t@2YAqH,5\U3`2cJIibl0l-&\oI$Mpu1QbU49uXL6#[C;hqD82SE6fV>m//2W_q%9X9[1!W,WK$OMgr;^B93ZJ[T#WAKd+S1L#-=T'1c5q^k>-2T@3q=#Qbm5gO%n,mdYhD5@K:)NdMo;38pp_FZGptL'jRKF@A3a/IoIt/:qO&d20@s5Feu1EBV(Y$`DK95cPV*F<*#%'J']*bT"6@$OI9n'\5*C/<FHD:Gh(IJd-/&Zdt&f'$i*WaOs7>,[J7*5UjtCiHZ_E@9tJ8=D>ne1#I!`R;rnM@ci#l!nT9k*luGDMTHn3E5#C1:?0`kUV^,H5he/=5[6,Z7P&f?_Bj*QMG5W8h@WgDpD:ER8ru/_S`38YTX]`U\dj0mWpLZ!SS6IVoMrLLIEcaMd+9hH/UbNR6=4fgdROOG:S5.3M7u`R;((L'\]XQ(,?!%=f8dpPU@,OnKK"tGXGi\p#-&@8kffuG61*J'hA00prh,`IJ%<j^)rkgmCPo`0jGqk(O:HSE\^(4pF<t_2@bEZE4-@9F+""\A;)Z?N'qCD(D#QbF$C;_q24nr3;>_h("+?tT3dN/sdPDs=a.OZe,ita4%o=V1:aQXq;,(<Q'%atV,;-FGnVg1^%iYb$2>4#i)VCmo17+.=g^S/:UFZ==r;-ZK;>?C]0n0Q=L7;Y*>N3N;$^NolrB$ZL"5@Z];TNHm);01b_4oRq?=V15a4nXi.U1%GgJ*4L^m]E,?X_8@',DTuW"ZKa$a,+o^IoWPAeFXd.>B:H?6V]SlG:4DFn>mUZ05I?>%=>q`&WBO2-4Rm\mB=))WGldrCT4:)m>FtGYR4c`V$*EYDpVL<Zs*935L!]_gH#af@pS_pu_.0Am0mR[larjrJ-0;&Fk!&Ni+&g@qr^1F4!clFA16=,2R!@p,_beL<$]d]Su$DH*d%2Ej(>]4/d6I(r8"ViY06q*9&##l34\-j8*VLJ?/\-(5Z:D*Xi8irS*2t@0_=R#,ctOVC(\BbA70/C>sBu(I!3^:<#JYI@<irj(ZFF^.g2[@F/2[@D;Q_\D4)7/8pa4QC"Oe$_&_S)PCZBkUEa1l`Jd)eGq1DjI>'RMkP141dFY<V*7L`*J*d<"[%MYk#%`U-NM@chbudp(bOq%D?-&=i_A?o"lE8P)Si^\l$a<1Ii$Fo'Dq<Ufd_@N]F`\.]c*Gf`70sR_bA"q_+\4UU;E>f0R*b=\u9cc-M74j:;.*V7QhVcA'PQj.#J,__OGiO'f8,YKIg3Pg.o$0!(0f3L-\MPW!(M$7@<qLj/f=Fp/?6S*9Y:r?L"F#%aWRG"'furpHp87>\=fF8\2dop#4NCh]>#"p#,E2rWa[C+T!U\@C115jETgq"%G0@3nFut_^O9()Q#R_[1P#:1GuGaV(?l^j*-Vjg/HX,C[Z"0K9B^rrAn0S+KK5'"_O+2WB@G"_Ia6NhEeE\i$C8m0;T7_i`Vl13dPJL]X:[!I^aqO,RmA0DHFRpoDbMdVr8iXJ$U#Aol0/L5s3Hk^8Pu#US*O>(.cYdX?YuYnEVOmiUQKMh`_I)R@ah",qS%>XiH-B;Qk"!*H9E!\nT\oS8*&K@a?l7d"!]]6tq_f"OB(\!^7*hnT/YsDKBc=dIsFg#hmh(R$3!0)k;Dgli1'o;3:YXQn[6[LId'/B/T2`eaA[@3=+(+RRL-n2g@+.>,aTDG2?a7F@K],7d1mnCs'H"7Rq)VK,JOqi6aMq!NUWNd%oIM[=0ERJS1Q*a"eug79n2*1&45kB;4L"Q3I_iieb])b"sIE$sH1"%B>_b@Xari0kObPH'j8gW,B)pk6fm-JuScB4HC29?`R*>OFDT8rsA^sW]CIVro^r#b27?/LdTQR(eF(K!O[#Q/R2Dfj9VH\0<7&\:ZTEfTrp)*L\[%u\1/!2'AHsC<`KtNL\[%uV()tt'D\lkQ3Qk5+-Ko-`Bebn+!r9s`Sktgl[LAmAgd.XF,t9`+s/^8KZ.@`V!SiHMM.N`\k\Bh\Mk%2E>nJt/Egt;Q$lBt]/4B2dY54,_9UoU<jPdT`q+fa?AP1)"0(_^?p"A.^9cNO0C":XpBr%V5V%":*qfblBYDW;JL_X17GI>ZdM#b+L3W##iJ;r^Dl2#a<REblI_(Tm4H+ZVi9k]JFNtTNdVK#P*l5gtiJ6\ZWj*q4-CUO.X[CmGD:t*,;tb[5g!@EiWrDX_4AmLAa<lHU@,S%7RU4:;%Oe3Jc1UPT-#+q!pr$SP,]"'L!it[ZrCHknVVIoRi$&Smn9D3_-^:bMKIWl5:1i#"Op0<P+TT3&^1O[_GKk_]M-8^((S>nh^5R`.P:mFID@]<,97'(uS%%.q>]c3?DE6`Qe>%Sn3miW#TYk4t02jka$J_k=@jLV3b?Zm:Dmq66bHI8q(BkrbHP+[+ZAe>675Vq/CeZFQT"!ttbh/G_Xh'1AoWP^VOrV37Y1^,9aEb/GOrU3%F9sfFP:jt@Y?*[_I:1H[*j8b'eRaU3!DK>Q6hW^^@2:e10]Tbl`a/k>j)L5Jcl_MC[/(F:a&a!]A$2]-%Qa,49_oVddtCb$9h_e@p*oqi=hc3(ds=l,TIsIjVPo5sfq@=jfZ#CHpf*OlEg)kJ7FE4+^?';aT8:UECnoi7oR5^NKso=^<]!FsN"4iio]A;94E&?h/YBYf06DaP@5\k\WlE78&CH_<pE+/od[Gk`4FAd<m&7lnHR=`fd@0ts18I@R"#;.=hF#L6FMSOu=W&R.EjQ.D;S_,#WpHk?>qE0<EXj+W8D?qgM#-cS]*"Bh`ii(+X5$%m)E8<5=ea6^#]Hu(G`3F9Xag66q8N$i_8C6=^VauB]=s5IZKEbUJE;+OAC:@hYU=\>Vh]Y2o1V%M4Gl.W4OGRH/RE`_T.L_?iCboc,/oLV03L)h\Jdp^`Jf^k"tV@DQ/K4O?=ZWL9-Q^b<1E?QEQ??U.PKEqm&i=:<]QTSmEG#3m99qq\a?3FG_`Jm6N;K7?aBFdp'_@Brs,2C$I&~>endstream
87
+ endobj
88
+ 14 0 obj
89
+ <<
90
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 2059
91
+ >>
92
+ stream
93
+ GauHL>?BQ=&:WeDbZdG=KJ0WIpLTD"BM6fP$L[?@D"^/OPskD5q>uHNofKGm`<cZFEjg`*7^j8[I%Nka1;UaJZhZ[X!DYs@ra:=l5r\n/&dmS63"6CI*Y?6Z4Gs7q>t/*5LufSQc_-XHA@U:b)0'JJK&\r2EZGA6+kX5?-j34M+.uI._:aeT$V[<m@4`1$YIW;D@hQ\bR0B0r&D-DV#ZKr8(kd;S>*]O<$=64V\:+s@n,iH\'&tGp%O&K9nF],61;ZrsI)6q>TWU_b%JfrbY#CJ!Kug.aNT=54+E>eNgB"&J>!@D7CH+L_IRMr`G&>aj3<k0O*(l(LFLi*p3^@mCO4cds@Jd!p;#H\SqrF^sCF,9:Cs"/Ap,nVjX<*LDSfS^-?[dKK4Gg+Ph%NtDi=O&c&FbN(4QRI5SMf::Cq[nqW-&\Ha)W&\"G_tK\D=Wn).]IP,un+-'=VP71?HS"#'2m3_E6tPVK6'0,]W9,(Ia&SiV[Kl_qr&IDe2sAGQTZB*QNHELPIj1S<*8$`a-Rc,$o9!P6o"e1F-"h8mE3<S:O4(3T4mb_NSNKa"`erT9lms)BP'<ECR9c:V;nugknEnA;pQ'>I2"Y4gU"2qMl#D=WQh#3scs)jq?9V%NLm#EAe>XRcJ_Gs6)<!2e%@5e1l=]^W^X[\m/qG4%O;d+.^tOXuY_3Vm(e9.%=Fn]17&K[mg31D*1@HZ7*`2'e$#)+q!u/<kg\3_5]Xt+D(P$8,q8B__b%r,8>L'(a&j?#CHXk(@%Ws(,SIg%1fr5[?uTo_PR,Z7c*/S.&qTo-JS3UJbEDVI'8R]+5;>JC-Qk#[:Jl[jLCX#REm\I`U[lph(F-_remT`^4cT8%L0`qI]lM]"CZ9K4QJ.r\(#L4>R'0YJ1pTRjb7[Z"-?*&"7Ho0N?#]`IsBNT'W3>D8pu<A%TrFfA1s[/ofNu_d"#Z"c]V]Iq.k(s)C/%34k/jk4ACWsY2;eW\d'>D*C@Y:a^?"@V<c4l;C2Mo5;%QWoGl_["m;M->j`.<rc_AC^p"rt!d-ia`!#[OQ*U;p$a,+P[!fsOS#;EX>^X$)J^RO"Jh<8fArYeF^Tl@,XQFY;4>*L&T/o>6HT?m2;J-8>bCLuNl3oQ;G#7AR8u$9;NEFug.MZcSF[H[Db\47^_n)OsD3q^+W+"La%"I0q^T3PCJ%)4p%9'i+e8uTor<?#`^]<\r@YEueM4+!!c_f'UZ)IH!QJ9aFE\EHQmM:0&<['^sn=t.K=D81<fA0>8YfF-Kgo)g[[^ImWQCuC;7?+S%MkrjI<X"Ph(k`S:q\b?W`MG+o`!]]hiMattbq;%79!>?Hk<.`Xaf?CZWMU\sl@PqD1:u^(9Vb3'PmC,tWdIXnaEa?`?!?kQ75j9G=!c+I@pP51"0pS*37!LRB"SaHr/P8:rWXQD`o<$Fi-XVd%c9'l0Ag+gat6o1.;+Wc>gL6`TM)n*cbZ&h<Sfk=K0X)C"eXCOJQLmK30+4;2M/nqL5"SW,^$-c5HbZs[QN&$=9th9)I43,)d3a+e>rnE1d==D5cFbF$L:5`4H$_&=3WA)L.Xp+NX-.n`fjK9J4Zm#!@G5J!qQJe;j@AeSuMQk"-SNUrILQ>7o(0QXT%Jt8tcT>FB\\QY.oCtDUY%UE*HdQE-`CLddWf5KkFagrsI?>iUNK%Pu*@CX=qQ?4>17lDoF>h`oq-Ld*^nj4P`l@iG"d+l]*kF3r2XD+G8$)1f_4r<(kMO:jV?g3j(.P,nGD%(.P^KB_@[rHm6D*-_Ohe@m64cSt/9p:j-33j+PTT'Q(4h4:V-o:HK(4gYGGLf!0;2bK*VK;(9t>SZKN1D,X0BNp=[6.,3JHo[LLi-rJJM0H&B.XIp2;"\G7-4X5&SI3V$iQ'`?"Tm'OM2g+`E<7Ha)N;#(@d,`'";(RSDNjLES49Gag&V$f)r?/c"9TF2TCPf-H,Z""%D=^;TnD]GG'0]?g,YqCd&8Ee)T=U,&"Fcg\Pqh,3G[&9L-P.KXj40\%Fn8jmdUZTa)"=n5KMr2tGhX(`\U%<N>(dCDJ?(06M)ZLQ#B,_^K)~>endstream
94
+ endobj
95
+ xref
96
+ 0 15
97
+ 0000000000 65535 f
98
+ 0000000061 00000 n
99
+ 0000000122 00000 n
100
+ 0000000229 00000 n
101
+ 0000000341 00000 n
102
+ 0000000446 00000 n
103
+ 0000000651 00000 n
104
+ 0000000728 00000 n
105
+ 0000000933 00000 n
106
+ 0000001138 00000 n
107
+ 0000001207 00000 n
108
+ 0000001492 00000 n
109
+ 0000001564 00000 n
110
+ 0000003920 00000 n
111
+ 0000007367 00000 n
112
+ trailer
113
+ <<
114
+ /ID
115
+ [<7242f470c8f00ae737cffeb3fee2725d><7242f470c8f00ae737cffeb3fee2725d>]
116
+ % ReportLab generated PDF document -- digest (opensource)
117
+
118
+ /Info 10 0 R
119
+ /Root 9 0 R
120
+ /Size 15
121
+ >>
122
+ startxref
123
+ 9518
124
+ %%EOF
@@ -0,0 +1,21 @@
1
+ """FKTD — Fraud KYC KTP Detector.
2
+
3
+ OCR multi-engine (EasyOCR / PaddleOCR) + validasi silang ketat untuk KTP Indonesia.
4
+ """
5
+
6
+ from .detector import FKTD
7
+ from .fraud import detect
8
+ from .models import FraudCheck, FraudResult, KTPData, Severity
9
+ from .nik import NIKInfo, decode_nik
10
+
11
+ __version__ = "0.1.0"
12
+ __all__ = [
13
+ "FKTD",
14
+ "detect",
15
+ "decode_nik",
16
+ "NIKInfo",
17
+ "KTPData",
18
+ "FraudResult",
19
+ "FraudCheck",
20
+ "Severity",
21
+ ]