Section 10/151 menit

10. Privacy, On-Device vs Cloud, dan Etika AI

10. Privacy, On-Device vs Cloud, dan Etika AI

Decision Framework: On-Device vs Cloud

swift
Data Classification:
├── Sangat sensitif (biometrik, dokumen pribadi, rekaman suara)
│   → SELALU on-device, JANGAN kirim ke server manapun
├── Sensitif (foto, teks pribadi)
│   → On-device direkomendasikan
│   → Jika cloud, harus ada explicit consent + enkripsi
└── Tidak sensitif (gambar produk umum, teks publik)
    → On-device untuk latensi, cloud untuk akurasi lebih tinggi

Akurasi Requirement:
├── Medical/legal/financial (high stakes): cloud model + human review
└── Consumer features (text suggestion, face filter): on-device cukup

Connectivity:
├── Harus offline (aviation, remote area, enterprise): on-device wajib
└── Always connected: fleksibel

Privacy Best Practices

swift
// Minimal data collection: proses on-device, jangan simpan data yang tidak perlu

class PrivacyAwareOCR {

    // ✓ Proses dan langsung discard gambar
    func extractTextPrivately(from image: UIImage) async -> String? {
        let text = await extractText(from: image)
        // image tidak disimpan, tidak dikirim ke server
        return text
    }

    // ✓ Berikan kontrol ke user
    func extractWithUserConsent(from image: UIImage) async throws -> String {
        let authorized = await requestAnalysisPermission()
        guard authorized else { throw PrivacyError.userDenied }
        return (await extractText(from: image)) ?? ""
    }

    // ✓ Info.plist: jelaskan kepada user mengapa camera dibutuhkan
    // NSCameraUsageDescription: "Digunakan untuk memindai dokumen secara lokal di perangkat Anda"
    // Tidak ada data yang dikirim ke server

    private func extractText(from image: UIImage) async -> String? {
        guard let cgImage = image.cgImage else { return nil }
        let request = VNRecognizeTextRequest()
        request.recognitionLevel = .accurate
        try? VNImageRequestHandler(cgImage: cgImage).perform([request])
        return request.results?.compactMap { $0.topCandidates(1).first?.string }.joined(separator: " ")
    }

    private func requestAnalysisPermission() async -> Bool {
        // Tampilkan consent dialog
        return true
    }
}